Operadores

Los operadores en Zephir son similares a los de PHP, y también heredarán algunos de sus comportamientos.

Operadores Aritméticos

Son soportados los siguientes operadores:

Operación Ejemplo
Negación -a
Suma a + b
Resta a - b
Multiplicación a * b
División a / b
Módulo a % b

Operadores bit a bit

Son soportados los siguientes operadores:

Operación Ejemplo
And a & b
Or (o inclusivo) a | b
Xor (o exclusivo) a ^ b
Not ~a
Mover a la izquierda a << b
Mover a la derecha a >> b

Ejemplo:

if a & SOME_FLAG {
    echo "tiene la bandera";
}

Para más información sobre la comparación de variables dinámicas vea el manual de PHP.

Comparación de Operadores

Los operadores de comparación dependen del tipo de variables en comparación. Por ejemplo, si ambos operandos de la comparación son variables dinámicas, el comportamiento es igual que en PHP:

Ejemplo Operación Descripción
a == b Igual true si a es igual a b después de arreglar de otro modo las variables.
a === b Idéntico true si a es igual a b, y ambas son del mismo tipo.
a != b No iguales true si a no es igual a b, después de arreglar de otro modo las variables.
a <> b No iguales true si a no es igual a b, después de arreglar de otro modo las variables.
a !== b No idénticos true si a no es igual a b, o ambos no son del mismo tipo.
a < b Menor Que true si a es estrictamente menor que b.
a > b Mayor que true si a es estrictamente mayor que b.
a <= b Menor o igual que true si a es menor o igual que b.
a >= b Mayor o igual que true si a es mayor o igual que b.

Ejemplo:

if a == b {
    return 0;
} else {
    if a < b {
        return -1;
    } else {
        return 1;
    }
}

Operadores Lógicos

Son soportados los siguientes operadores:

Operación Ejemplo
And a && b
Or a || b
Not !a

Ejemplo:

if a && b || !c {
    return -1;
}
return 1;

Operador Ternario

Zephir soporta el operador ternario habilitado en C o PHP:

let b = a == 1 ? "x" : "y"; // b es igual a "x" si a es igual a 1, en otro caso será igual a "y"

Operadores Especiales

Son soportados los siguientes operadores:

Empty

Este operador permite chequear si una expresión esta vacía. 'Empty' significa que la expresión es igual a null, a una cadena de texto vacía, o a un array vacío:

let someVar = "";
if empty someVar {
    echo "¡esta vacía!";
}

let someVar = "hola";
if !empty someVar {
    echo "¡no esta vacía!";
}

Fetch

'Fetch' es un operador que reduce una operación común en PHP a una sola instrucción:

<?php

if (isset($myArray[$key])) {
    $value = $myArray[$key];
    echo $value;
}

En Zephir, puedes escribir el mismo código de la siguiente manera:

if fetch value, myArray[key] {
    echo value;
}

'Fetch' solo retornará true si la clave 'key' es un item válido en el array, y solo si tiene un valor 'value' asignado.

Isset

Este operador comprueba que una propiedad o un índice esté definido en un array o en un objecto:

let someArray = ["a": 1, "b": 2, "c": 3];
if isset someArray["b"] { // comprueba que el array tenga el índice "b"
    echo "si, hay un índice 'b'\n";
}

Utilizando isset como una expresión de retorno:

return isset this->{someProperty};

Nota: en Zephir isset funciona como la función array_key_exists de PHP, isset en Zephir retornará true incluso cuando el índice del array o la propiedad del objecto sean nulas.

Typeof

Este operador comprueba el tipo de una variable. typeof puede usarse con un operador de comparación:

if (typeof str == "string") { // o !=
    echo str;
}

También puede trabajar como la función gettype de PHP.

return typeof str;

Cuidado si desea comprobar que si un objeto es "callable", siempre tienes que usar typeof como un operador de comparación, no como una función.

Sugerencias de Tipos

Zephir siempre trata de comprobar si un objeto implementa métodos y propiedades llamado/accedido a una variable, que se infiere que es un objeto:

let o = new MyObject();

// Zephir comprueba si "myMethod" es implementado en MyObject
o->myMethod();

Sin embargo, debido al dinamismo heredado de PHP, a veces no es fácil saber la clase de un objeto, entonces Zephir no puede producir informes de errores con eficacia. Una sugerencia de tipo le indica al compilador que clase se relaciona con una variable dinámica, permitiendo que el compilador hacer más verificaciones de compilación:

// Decirle al compilador que "o"
// es una instancia de la clase MyClass
let o = <MyClass> this->_myObject;
o->myMethod();

Estos "consejos de tipo" son débiles. Esto significa que el programa no comprueba si el valor es de hecho una instancia de la clase especificada, ni si implementa la interfaz especificada. Si desea comprobarlo en ejecución cada vez, utilice un tipo estricto:

// Siempre comprueba si la propiedades es una instancia
// de MyClass antes de asignarla
let o = <MyClass!> this->_myObject;
o->myMethod();

Consejos de Predicción de Rama

¿Qué es la predicción de rama? Revisa este artículo o este otro artículo en la Wikipedia. En entornos donde el desempeño es muy importante, puede ser útil introducir estos consejos.

Considere el siguiente ejemplo:

let allPaths = [];
for path in this->_paths {
    if path->isAllowed() == false {
        throw new App\Exception("Un mensaje de error");
    } else {
        let allPaths[] = path;
    }
}

Los autores del código anterior saben, de antemano, que es poco probable que ocurra la condición que produce la excepción. Esto significa que, el 99.9% del tiempo, nuestro método ejecuta esa condición, pero probablemente nunca se evalúe como verdadero. Para el procesador, esto podría ser difícil de saber, pero le podríamos presentar una sugerencia allí:

let allPaths = [];
for path in this->_paths {
    if unlikely path->isAllowed() == false {
        throw new App\Exception("Un mensaje de error");
    } else {
        let allPaths[] = path;
    }
}