Iterations with FOLD<N>#

FOLD<N> macro makes it possible to implement operations on a list of values such as sum, filter, map, zip, exists, etc. The macro behaves like the fold or reduce function in other programming languages.

FOLD<N>(list, start, foldFunc)
Iterations with FOLD#

Parameter

Description

N

Maximum number of iterations, up to \(1000\).

list

List of values.

start

Initial value.

foldFunc

Combining function.

The combining function accepts two input parameters: the intermediate result and the next element of the list. Macro FOLD<N>(list, start, foldFunc) means:

  • Execute up to N iterations.

  • At each iteration: take the r-esult of the previous iteration (at the first iteration take the start value) and the next list item list, apply the foldFunc function to this pair.

  • Return the final result.

The value of N must be known in advance. If there are more elements in the list than specified in FOLD, the script fails. The complexity of FOLD<N> corresponds to the complexity of foldFunc multiplied by N plus extras. The FOLD<N> macro is a syntactic sugar; it is unwrapped by the compiler. Therefore, in particular, the size of the script increases linearly with N.

Sum#

func sum(accum: Int, next: Int) = accum + next
let arr = [1,2,3,4,5]
FOLD<5>(arr, 0, sum)    # Result: 15

The expression

FOLD<5>(arr, 0, sum)

after compiling and decompiling will look like this:

let $list = arr
let $size = size($list)
let $acc0 = 0
if (($size == 0))
 then $acc0
 else {
   let $acc1 = sum($acc0, $list[0])
   if (($size == 1))
     then $acc1
     else {
       let $acc2 = sum($acc1, $list[1])
       if (($size == 2))
         then $acc2
         else {
           let $acc3 = sum($acc2, $list[2])
           if (($size == 3))
           then $acc3
             else {
               let $acc4 = sum($acc3, $list[3])
               if (($size == 4))
                 then $acc4
                 else {
                   let $acc5 = sum($acc4, $list[4])
                   if (($size == 5))
                     then $acc5
                     else {
                       let $acc6 = sum($acc5, $list[5])
                       throw("List size exceed 5")
                     }
                 }
             }
         }
     }
 }

Product#

func mult(accum: Int, next: Int) = accum * next
let arr = [1,2,3,4,5]
FOLD<5>(arr, 1, mult)    # Result: 1204]

Filter#

The following code composes an array consisting only of even elements of the original array:

func filterEven(accum: List[Int], next: Int) =
 if (next % 2 == 0) then accum :+ next else accum
let arr = [1,2,3,4,5]
FOLD<5>(arr, [], filterEven)    # Result: [2, 4]

Map#

The following code inverts the array, reducing each element by \(1\):

func map(accum: List[Int], next: Int) = (next - 1) :: accum
let arr = [1, 2, 3, 4, 5]
FOLD<5>(arr, [], map)    # Result: [4, 3, 2, 1, 0]