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

results matching ""

    No results matching ""