This documentation explains the uses of all operators.
;
Terminates an instruction. The semicolon is optional and can be inferred in most cases, depending on which type of token terminates a line. However, it's useful on occasion for one-liners.
doSomething(); doSomethingElse()
Tokenized as OP_SEMI
.
,
Separates function arguments and collection entries.
myFunc(1, 2, 3)
$myList = [1, 2, 3]
Tokenized as OP_COMMA
.
:
Separates key-value pairs.
If it follows a bareword immediately (without whitespace in between), it is
assumed that the bareword is the key for an object or hash pair and is tokenized
as PROP_VALUE
.
$object = (key: "value", other: "another")
Any other expression can precede it, in which case it is tokenized as
OP_VALUE
.
$object = ("key": "value", "other": "another")
The symbol data type (e.g. :sym
) is tokenized separately as VAR_SYM
; see
Symbols.
Tokenized as PROP_VALUE
or OP_VALUE
.
.
Accesses a property on an object.
Bareword properties such as .propName
, including the period (.
), are
tokenized as a single PROPERTY
token.
$value = $object.propName
For non-barewords, OP_PROP
is used and must be followed by an expression
delimited in square brackets [
and ]
. This allows property names to be
evaluated at runtime.
$prop = "propName"
$value = $object.[$prop] # note: NOT the same as $object[$prop]
Tokenized as PROPERTY
or OP_PROP
.
=
Separates an assignable expression from its new value. At its left must be an assignable variable, property, index, or other type of lvalue.
$x = 1
$object.property = "hello"
$list[0] = "world"
Tokenized as OP_ASSIGN
.
See also
?=
OP_LASSIGN
- lazy assignment+=
OP_ADD_A
- addition assignment-=
OP_SUB_A
- subtraction assignment*=
OP_MUL_A
- multiplication assignment/=
OP_DIV_A
- division assignment
?=
Separates an assignable expression from its lazy-computed value. At its left must be an assignable variable, property, or other type of lvalue.
Lazy assignment allows the evaluation of a property or variable's value to be deferred until it is referenced somewhere. This is useful for decreasing load time when it is unknown whether a value will ever be used in the particular program.
$x ?= doSomething()
# doSomething will not be called until $x is accessed below
$y = $x
# now $x and $y have the semi-permanent value returned by doSomething()
Tokenized as OP_LASSIGN
.
See also OP_ASSIGN
.
->
The return operator does three things:
- With a bareword to its left and expression at right, adds a named value to the return object of the function but allows execution to continue.
- With nothing to its left and an expression at right, overrides the return object with the specified single return value and stops execution of the function.
- All by itself, as a standalone instruction, stops execution of the function, yielding the return object in its current state.
All functions, methods, and callbacks start with an empty return object. This is useful for returning multiple values, especially if the routine is extensible through user-defined event callbacks which may find use in returning values.
Case 1 - Within the body of the function, the return object is represented by
the special variable *return
, but rarely
should you need to access it that way because of the convenient syntax provided
by this operator. The return operator, in the form of propName -> $value
,
provides a more appealing syntax for the functionally equivalent
*return.propName = $value
.
func addOneToEach {
need $x: Num, $y: Num
newX -> $x + 1
newY -> $y + 1
}
addOneToEach(5, 10) # returns (newX: 6, newY: 11)
Case 2 - The return operator can be used in place of the return keyword
that exists in many other languages, like so: -> $returnValue
. Ferret has
no return keyword. Consider the following one-liner as an example:
[1,2,3].map! { -> $_ * 2 } # [2, 4, 6]
Note that when used within an event callback, it is possible that the provided
value will not ultimately be returned by the event call. If multiple callbacks
have an explicit ->
statement, the value of the lattermost statement is used.
func simple {
-> "t"
}
func complex {
want $x: Num
if $x {
gotX -> true
value -> $x
->
}
-> "reached bottom"
}
simple() # returns "t"
complex(5) # returns (gotX: true, value: 5)
complex() # returns "reached bottom"
Case 3 - The return operator can stop execution of the function without providing a value. In this case, the functions yields the return object, NOT a void value.
func calculate {
# in progress already, so return!
if $alreadyCalculating
->
# continue...
}
Tokenized as OP_RETURN
.
::
Separates namespace symbols.
Since contexts and classes are simple objects, this is functionally equivalent to the property operator, except that autoloading is also considered.
When accessing classes, contexts, and interfaces, you should always use ::
(rather than .
) so that the compiler knows which files to include. In the
below example, the compiled code automatically includes the Math::Point
class.
$intercept = Math::Point(1, 0)
For shared variables (which, by convention, have lowercase names), use the
normal .
accessor.
$origin = Math::Point.origin
Tokenized as OP_PACK
.
Maybe don't use this. I can't decide its fate.
?
Indicates that a value may not be present and ignores the entire current instruction in such a case.
This operator is especially useful when the presence of a value is unknown, but
the use of if
would be repetitive.
if $x
doSomethingWith($x)
# is better written
doSomethingWith($x?)
Frequent use case involving named handlers
# if there is nothing at $handlers[$command], nothing happens.
# if there is, it is called.
$handlers[$command]?()
# this is functionally equivalent to
if $handlers[$command]:
$handlers[$command]()
Tokenized as OP_MAYBE
.
See also once-computed properties
and the lazy assignment operator (?=
).
...
Indicates that a function argument should consume the remainder of the passed values. When specified, a function can be called with a variable number of arguments which will be passed to the implementation as a list.
func getSum {
need $nums: Num...
-> $nums.sum
}
getSum(1, 2, 3, 4, 5) # 15
The ellipsis can be preceded by any number of regular named arguments.
func party {
need $day: Str, $people: Str...
say("On $day, we are throwing a party. $people.length are coming:")
for $name in $people
say(" $name")
}
party(
"Saturday",
"Shirley", "Shelly",
"Sherry", "Cheryl",
"Sheila", "Chanel",
"Shannon", "Shania"
)
If the ellipsis argument is a need
as in the above
examples, the function argument requirements will only be satisfied if at least
one unnamed argument matches. If it is instead a want
, the
ellipsis argument will yield an empty list in the case that no unnamed arguments
match. In any case, it is guaranteed that the ellipsis argument yields a list.
func party {
need $day: Str
want $people: Str...
if $people.empty
say("No one RSVP'd for $day; we'll have to reschedule")
else
say("$people.length people are coming to our party $day")
}
party("Friday") # satisfies the function, with $people empty list []
Passing the ellipsis argument as a list is also possible, but to prevent unexpected results when working with lists, the argument name must be explicit:
$list = ["Frank", "Monica", "Fiona", "Jimmy", "Kev", "Veronica"]
party("Friday", people: $list) # ok
party("Friday", $list) # NOT ok (type mismatch List != Str)
Tokenized as OP_ELLIP
.
!
Calls a function with no arguments.
someFunction!
# equivalent to
someFunction()
Tokenized as OP_CALL
.
See also the factorial operator.
&&
True if two or more values evaluate to boolean true.
$true = true && 1
$false = true && true && false
Tokenized as OP_AND
.
||
True if at least one of two or more values evaluates to boolean true.
$true = false || 1
$false = false || undefined || 2.odd
Tokenized as OP_OR
.
!
Negates a value to its boolean opposite.
$false = !true
Tokenized as OP_NOT
.
The absolute order of math operation precedence is as follows:
- Positivity
+
- Negativity
-
- Range
..
- Power
^
- Modulus
%
- Multiplication
*
- Division
/
- Subtraction
-
- Addition
+
+
Adds values.
$three = 2 + 1
Tokenized as OP_ADD
.
+
Indicates that a value is positive.
$one = +1
Tokenized as OP_SADD
.
-
Subtracts values.
$five = 6 - 1
Tokenized as OP_SUB
.
-
Indicates that a value is negative.
$negativeOne = -1
Tokenized as OP_SSUB
.
*
Multiplies values.
$ten = 5 * 2
Tokenized as OP_MUL
.
/
Divides values.
$twenty = 100 / 5
Tokenized as OP_DIV
.
^
Takes a value to the power of another.
$eight = 2 ^ 3
Tokenized as OP_POW
.
+=
Alters a value by adding a value to it. At its left must be an assignable variable, property, index, or other type of lvalue.
$x = 1
$x += 4
# $x is now five
Tokenized as OP_ADD_A
.
-=
Alters a value by subtracting a value from it. At its left must be an assignable variable, property, index, or other type of lvalue.
$x = 5
$x -= 1
# $x is now four
Tokenized as OP_SUB_A
.
*=
Alters a value by multiplying it by a value. At its left must be an assignable variable, property, index, or other type of lvalue.
$x = 4
$x *= 5
# $x is now 20
Tokenized as OP_MUL_A
.
/=
Alters a value by dividing it by a value. At its left must be an assignable variable, property, index, or other type of lvalue.
$x = 100
$x /= 4
# $x is now 25
Tokenized as OP_DIV_A
.
%
Returns the remainder from the division of two values.
47 % 7 # 0
17 % 2 # 1
Tokenized as OP_MOD
.
..
Returns a list representing a range from a value to a value. If the first value is larger than the second, the items in the set will be in descending order.
$nums = 1..5 # [1, 2, 3, 4, 5]
$nums = 5..1 # [5, 4, 3, 2, 1]
Tokenized as OP_RANGE
.
!
Returns the factorial of the integer before it.
This is not truly a math operator but rather the
zero-argument call operator. Calling a integer
returns its factorial. Calling a non-integer Number returns the factorial of its
.floor
.
$f = 4! # 24
$f = 4.9999! # also 24
Tokenized as OP_CALL
.
==
Tests the logical equivalence of two or more values.
10 == 10 # true
"hi" == "hi" # true
1 == 1.0 == 1.1 # false
Tokenized as OP_EQUAL
.
===
Tests the memory address equivalence of two or more values.
"hi" === "hi" # false
false === false # true
true === true === false # false
Tokenized as OP_EQUAL_I
.
=~
Tests the logical similarity of two or more values.
"hi" =~ /^h/ # true
"hi" =~ /k/ # false
Tokenized as OP_SIM
.
!=
Tests the logical inequivalence of two or more values.
1 != 2 # true
0 != 0 # false
Tokenized as OP_NEQUAL
.
!==
Tests the memory address inequivalence of two or more values.
false !== true # true
"hi" !== "hi" # true
true !== true # false
Tokenized as OP_NEQUAL_I
.
!~
Tests the logical dissimilarity of two or more values.
"hi" !~ /^h/ # false
"hi" !~ /k/ # true
Tokenized as OP_NSIM
.
<
Tests if the value of left operand is less than the value of right.
1 < 2 # true
6 < 5 # false
Tokenized as OP_LESS
.
<=
Tests if the value of left operand is less than or equal to the value of right.
1 <= 2 # true
1 <= 1 # true
6 <= 5 # false
Tokenized as OP_LESS_E
.
>
Tests if the value of left operand is greater than the value of right.
1 > 2 # false
6 > 5 # true
Tokenized as OP_GR8R
.
>=
Tests if the value of left operand is greater than or equal to the value of right.
1 >= 2 # false
1 >= 1 # true
6 >= 5 # true
Tokenized as OP_GR8R_E
.