Flow control
Move along in a continuous stream of decisions that should be made.
Fallback
Default or nullish coalescing operations, are defined with double question marks ??
and work the following way:
<maybeNullOrError> ?? <fallbackValue>
In case the left-hand side is not null
nor Error
, then it's used; otherwise, fallbackValue
is returned.
similarly you can use the nullish coalescing assign operator
??=
If
If
statements are defined with a question mark ?
, like so:
<condition> ? <response>
as there is no alternative
null
is returned if condition is not met
If-Else
If-Else
statements are defined with a question mark ?
followed by a colon :
, like so:
<condition> ? <response> : <alternativeResponse>
To use multiline If-Else
statements, wrap the response in curly brackets {...}
like so:
<condition> ? {
<response>
} : {
<alternativeResponse>
}
Cases
Cases
are defined with the thick arrow =>
and are automatically chained, creating an intuitive and streamlined syntax similar to a switch statement without the possibility of fall-through. This allows for unrelated conditions to be mixed together, ultimately resulting in a more concise "if-else-if-else" structure:
<condition1> => <responseFor1>
<condition2> => <responseFor2>
<condition3> => <responseFor3>
...
Example:
choose = (x) -> {
x == 1 => 'a'
x == 2 => 'b'
x == 3 => 'c'
}
choose(2) # 'b'
choose(8) # null
To provide a default value for your method, you can add a catch-all case using an underscore _
at the end of the sequence:
choose = (x) -> {
x == 1 => 'a'
x == 2 => 'b'
x == 3 => 'c'
_ => 'd'
}
choose(2) # 'b'
choose(8) # 'd'
For more complex scenarios, you can use blocks as outcomes for each case:
...
condition => {
# do something
'foo'
}
_ => {
# do something else
'bar'
}
...
Cases
must end in a catch-all case _
or end of block. The most effective use of Cases
is within methods at the bottom of the method body.
While it's possible to add nested Cases
, it's best to avoid overly complex constructions. This makes code harder to follow and likely misses the point of using this feature.
It may be more appropriate to extract that logic into a separate method. FatScript encourages developers to split logic into distinct methods, helping to prevent spaghetti code.
Switch
The Switch
operator is denoted by the double right arrow >>
symbol, which guides the flow of control based on the value's match against a series of cases:
Syntax:
<value> >> {
<caseValue1> => <responseFor1>
<caseValue2> => <responseFor2>
...
_ => <defaultResponse>
}
Each case in the Switch
block is evaluated in order until a match is found and the result of the matching case is returned:
choose = -> _ >> {
1 => 'one'
2 => 'two'
3 => 'three'
_ => 'other'
}
choose(2) # 'two'
choose(4) # 'other'
Switch
cases can also involve expressions, allowing for dynamic matching:
evaluate = (x, y) -> x >> {
y + 1 => 'just above y'
y - 1 => 'just below y'
_ => 'not directly around y'
}
evaluate(5, 4) # 'just above y'
evaluate(3, 4) # 'just below y'
evaluate(7, 4) # 'not directly around y'
Tap
The Tap
operator is denoted by the double left arrow <<
symbol, which facilitates the execution of side effects without altering the main result of an expression. It is designed to process values through specified methods (taps) that can perform side effects, while still returning the original value of the expression.
Syntax:
<result> << <tapMethod>
the right-hand side of a
tap
must always be a method
In this structure, <result>
is an expression whose value is passed to <tapMethod>
, which executes using <result>
as its input but does not affect the final value of the expression. Instead, <tapMethod>
is used purely for its side effects.
See how the tap
operator can be used:
console <- fat.console
increment = x -> x + 1
result = increment(4) << console.log
In this example, increment(4)
computes to 5
, which is then passed to console.log
and although console.log
returns null
, the final result assigned to result
is 5
.
Multiple side effects can be chained sequentially, each receiving the same initial result:
val = pure(in) << fx1 << fx2 << fx3