Operators¶
Zephir, a language designed for building PHP extensions, comes with a set of operators inherited from PHP, each serving specific purposes. Let's delve into the various operator categories and examples:
Arithmetic Operators¶
Zephir supports standard arithmetic operators:
Operation | Example |
---|---|
Negation | -a |
Addition | a + b |
Subtraction | a - b |
Multiplication | a * b |
Division | a / b |
Modulus | a % b |
Bitwise Operators¶
These operators work with individual bits:
Operation | Example |
---|---|
And | a & b |
Or (inclusive or) | a | b |
Xor (exclusive or) | a ^ b |
Not | ~a |
Shift left | a << b |
Shift right | a >> b |
Example:
Learn more about comparison of dynamic variables in the php manual.
Comparison Operators¶
Comparison operators depend on the type of variables compared. For example, if both compared operands are dynamic variables, the behavior is the same as in PHP:
Example | Operation | Description |
---|---|---|
a == b | Equal | true if a is equal to b after type juggling. |
a === b | Identical | true if a is equal to b, and they are of the same type. |
a != b | Not equal | true if a is not equal to b after type juggling. |
a <> b | Not equal | true if a is not equal to b after type juggling. |
a !== b | Not identical | true if a is not equal to b, or they are not of the same type. |
a < b | Less than | true if a is strictly less than b. |
a > b | Greater than | true if a is strictly greater than b. |
a <= b | Less than or equal to | true if a is less than or equal to b. |
a >= b | Greater than or equal to | true if a is greater than or equal to b. |
Example:
Logical Operators¶
Dealing with boolean values:
Operation | Example |
---|---|
And | a && b |
Or | a || b |
Not | !a |
Example:
Ternary Operator¶
Equivalent to C or PHP:
// b is set to "x" if a is equal to 1, otherwise "y" is assigned as the value
let b = a == 1 ? "x" : "y";
Special Operators¶
Empty¶
This operator allows checking whether an expression is empty. 'Empty' means the expression is null
, is an empty string, or an empty array:
let someVar = "";
if empty someVar {
echo "is empty!";
}
let someVar = "hello";
if !empty someVar {
echo "is not empty!";
}
Fetch¶
'Fetch' is an operator that reduces a common operation in PHP into a single instruction:
In Zephir, you can write the same code as:
'Fetch' only returns true
if the 'key' is a valid item in the array, and only in that case is 'value' populated.
Isset¶
This operator checks whether a property or index has been defined in an array or object:
let someArray = ["a": 1, "b": 2, "c": 3];
if isset someArray["b"] { // check if the array has an index "b"
echo "yes, it has an index 'b'\n";
}
Using isset
as a return expression:
Note that isset
in Zephir works more like PHP's function array_key_exists, isset
in Zephir returns true even if the array index or property is null.
Typeof¶
This operator checks a variable's type. 'typeof' can be used with a comparison operator:
It can also work like the PHP function gettype
.
Be careful, if you want to check whether an object is 'callable', you always have to use typeof
as a comparison operator, not a function.
Type Hints¶
Zephir always tries to check whether an object implements methods and properties called/accessed on a variable that is inferred to be an object:
However, due to the dynamism inherited from PHP, sometimes it is not easy to know the class of an object, so Zephir can't produce error reports effectively. A type hint tells the compiler which class is related to a dynamic variable, allowing the compiler to perform more compilation checks:
// Tell the compiler that "o"
// is an instance of class MyClass
let o = <MyClass> this->_myObject;
o->myMethod();
These "type hints" are weak. This means the program does not check if the value is in fact an instance of the specified class, nor whether it implements the specified interface. If you want it to check this every time in execution, use a strict type:
// Always check if the property is an instance
// of MyClass before the assignment
let o = <MyClass!> this->_myObject;
o->myMethod();
Branch Prediction Hints¶
What is branch prediction? Check this article or refer to the Wikipedia article. In environments where performance is very important, it may be useful to introduce these hints.
Consider the following example:
let allPaths = [];
for path in this->_paths {
if path->isAllowed() == false {
throw new App\Exception("Some error message here");
} else {
let allPaths[] = path;
}
}
The authors of the above code know in advance that the condition that throws the exception is unlikely to happen. This means that, 99.9% of the time, our method executes that condition, but it is probably never evaluated as true. For the processor, this could be hard to know, so we could introduce a hint there: