-
Notifications
You must be signed in to change notification settings - Fork 5
Basic Constructs
a = 1
name = "Hello world"
vector = [1 2 3 "a" "b", "c"] // separators are optional
dictionary = [
1 => "a"
"b" => 2 , // separators are optional
3 => "c"
]
1 + 1 // evaluates to 2
a = 1 + b // assignment from expression
{1+1} // evaluates to 2
a = {1+b} // same as "a = 1+b"
a = {
printl("hello") // evaluates everything, and the final value...
1+b // ... is the result of the last evaluation.
}
a = 1
b = 2
{ // creates a scope
a = 100 // accesses outer a
my b = 101 // local view of b
c = 4 // creates c
my d = 5 // creates d locally
print(a, b, c, d) All variables are defined
}
// Outside the scope, a was overwritten and c is created anew.
print(a, b, c) // a=100, b=2, c=4, d is undefined.
All Falcon2 expressions are grammar sugar for an underlying function. They appear as a reflection form of the relative grammar construct, but actually the translation from the construct syntax into the functional form happens before the actual compilation step takes place.
Standard functions are in the standard namespace; this means they are directly accessible, as symbols visible from the outer program scope. For example, print
and printl
are standard functions to send textual output to the program standard output, and they can be accessed directly throughout the program. However, most functions have the same name as their grammar construct counterpart, (for example while
or if
); to identify them, the namespace accessor :
(colon) can be used.
For example, print
and :print
are equivalent, the second specifying that the print
symbol is to be accessed from the standard namespace.
While syntactic-equivalent functions, s
let
andrun
have no syntactic grammar construct masking their name, using the:
namespace indicator to identify them is considered good practice.
For example:
a = 1+1 // --> :let(a, :+(1,1))
{
print("hello")
print("world")
} // --> :run(print("hello"), print("world"))
inc = {(a) 1+a} // --> :let(inc, :expr(:params(a), :+(1,a))
function NAME {(p0, p1)[c0=0, c1=0]
c1 = c0+c1
c0 = p0+p1
}
// --> :let(NAME, :function(NAME, :params(p0,p1), :close(c0, c1),
// :run(:let(c1, :+(c0,c1) ), :let(c0, :+(p0,p1)))
// ))
The if
construct, and the relative :if
function conditionally evaluate an expression when a control expression (called check) evaluates as true. Optionally, an expression to be evaluated when the check is false can be provided.
if exprCheck
exprIfTrue
else
exprIfFalse
Which expands in the functional form: :if( &exprCheck, &exprIfTrue, &exprIfFalse={})
Multiple expressions can be evaluated using {}
/ :run()
:
if check {
printl("is true")
a = 0
}
else :run(
printl("is false")
a = 1
)
Notice that newline is considered a simple separator, so the
if
construct can be expressed asif exprCheck exprIfTrue else exprIfFalse
, orif exprCheckk, exprIfTrue, else exprIfFalse;
to avoid ambiguity.
The result of the if
expression/function is the result of the evaluation of the selected branch (or false
, if the check evaluates to false and the exprIfFalse
branch is not given).
For example:
a = 10; b = 20
printl(if a < b "A is greater" else "B is greater") // prints "B is greater"
The while construct repeats the evaluation of an expression as long as a check evaluates to true.
It is defined as while check expression
, or :while(&check, &expression)
.
For example:
a = 10
while a > 0 {
printl(a)
a -= 1
}
The break expr
statement (or :break(expr)
function) exits the loop, while the continue
statement (or :continue()
function) repeats the check.
The while
expression/function evaluates to false, or to the value of the break expression if the loop exits through a :break()
. For example:
ck = [5 3 2 6 9]
a = 5
printl( while a > 0 {
printl( ck[a] )
if ck[a] < 3 break "Limit reached"
a -= 1
})
To have a definite value out of the while expression, set the check as
true
and exit the loop usingbreak
only.
The for/in loop repeats a set of expressions while a seqExpr
expression produces a sequence. It's grammar form is:
for seqExpr
bodyExpr
forfirst ffExpr
formiddle fmExpr
forlast flExpr
and function form is :for(&seqExpr, &bodyExpr, &first={}, &last={}, &middle={})
.
The seqExpr
is an expression that should set local variables referenced by the other expressions in the for
evaluation. The seqExpr
will be repeatedly evaluated until yielding a final result. For example:
for a = nextItem()
printl(a)
The in
expression (or :in() function) iterates over a sequence:
for a in [1 2 3]
printl(a) // prints 1, 2 and 3
and the range(begin, end, step=0)
function provides a way to generate a sequence of integer numbers between begin
and end
with an optional step:
for a in :range(0, 10, 3)
printl(a) // prints 0, 3, 6 and 9
The ffExpr
(or first
parameter) if present, it's evaluated before the first body is processed. The fmExpr
(or middle
parameter) is evaluated after each bodyExpr
evaluation except for the last one, and flExpr
(or last
parameter) is evaluated after the last body evaluation. For example:
:for( a in :range(0,10,3),
print(a)
first: print("Numbers: ")
middle: print(", ")
last: printl(".")
)
// prints "Numbers: 0, 3, 6, 9."
The continue
expression/function will re-evaluate the seqExpr
, skipping the rest of the expressions to be evaluated (i.e. middle
or last
), while break
or :break(value)
will exit the loop immediately.
The value of the for expression/:for
function is the value of the last evaluation of seqExpr
, or the value set in :break(value)
if the loop is so terminated.