Closures, Anonymous Procs and Functional Programming

19.1 Anonymous Procs and the => Sugar

import std/[sequtils, sugar]
let nums = @[1, 2, 3, 4]
echo nums.map(proc (x: int): int = x * x)
echo nums.map(x => x * x)
let add = (a, b: int) => a + b
let printer: proc (s: string) = (s: string) => echo s
proc apply(f: (int) -> int, x: int): int = f(x)    # `->` type sugar

19.2 Closures

Closures capture variables by reference into a heap environment. Use capture from std/sugar to capture loop variables by value:

proc makeCounter(): proc (): int =
  var count = 0
  result = proc (): int =
    inc count
    count
let c = makeCounter()
echo c(), c(), c()     # 1 2 3
var procs: seq[proc (): int]
for i in 0..2:
  capture i:
    procs.add(() => i)

19.3 Functional Patterns

map, filter, foldl, foldr, zip, concat, distribute, collect, dup (std/sugar: s.dup(sort)), and pipelines via UFCS:

func and {.noSideEffect.} for pure functions. let for immutability.

Packages: zero_functional (fusion of chained operations), iterutils.

let res = (1..10).toSeq.filterIt(it mod 2 == 0).mapIt(it * it).foldl(a + b)