Skip to content

Instantly share code, notes, and snippets.

@mratsim
Created April 13, 2017 07:29
Show Gist options
  • Select an option

  • Save mratsim/ff812504151908d527b5f950ec863501 to your computer and use it in GitHub Desktop.

Select an option

Save mratsim/ff812504151908d527b5f950ec863501 to your computer and use it in GitHub Desktop.
Nim functional programming
template scanr[T](s: seq[T], operation: untyped): untyped =
## Template to scan a sequence from right to left, returning the accumulation and intermediate values.
## This is a foldr with intermediate steps returned
## @[2, 2, 3, 5].scanr(a + b) = @[48, 24, 12, 4]
let len = s.len
assert len > 0, "Can't scan empty sequences"
var result = newSeq[T](len)
result[result.high] = s[s.high]
for i in countdown(len - 1, 1):
let
a {.inject.} = s[i-1]
b {.inject.} = result[i]
result[i-1] = operation
result
iterator zipWith[T1, T2, T3](f: proc(x: T1, y:T2):T3,
a: iterator():T1,
b: iterator():T2): iterator():T3 {.inline.}=
let a_it = a
let b_it = b
while true:
if finished(a_it) or finished(b_it):
break
let a_val = a_it()
let b_val = b_it()
yield f(a_val,b_val)
## Bug https://github.com/nim-lang/Nim/issues/5647 open.
## unfold proper type signature should have Option[(T, U)] instead of Option[(T, T)]
# proc unfoldr*[T, U](f: U -> Option[(T, U)], x:U): seq[T] {. inline .}=
proc unfoldr[T, U](f: T -> Option[(T, T)], x:U): seq[T] {. inline .}=
## Build a sequence from function f: T -> Option(T,T) and a seed of type T
result = @[]
var a: U = x
var b: T
var fa = f(a)
while fa.isSome():
(b, a) = fa.get()
result.add(b)
fa = f(a)
proc unfoldrIter[T, U](f: T -> Option[(T, T)], x:U): iterator():T =
## Build an iterator from function f: T -> Option(T,T) and a seed of type T
## Useful to consume infinite generators like power of 2 and fibonacci
result = iterator(): T {.closure.}=
var a: U = x
var b: T
var fa = f(a)
while fa.isSome():
(b, a) = fa.get()
yield b
fa = f(a)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment