zero_functional

A library providing zero-cost chaining for functional abstractions in Nim


Keywords
functional, dsl, chaining, seq
License
MIT
Install
nimble install zero_functional

Documentation

zero-functional

Build Status

A library providing (almost) zero-cost chaining for functional abstractions in Nim.

var n = zip(a, b) -->
            map(f(it[0], it[1])).
            filter(it mod 4 > 1).
            map(it * 2).
            all(it > 4)

is expanded on compile time to the equivalent of

(proc (): auto =
  var minHigh134598 = min([high(a), high(b)])
  var empty = true
  for z in low(a) .. minHigh134598:
    var it0 = (a[z], b[z])
    var it1 = f(it0[0], it0[1])
    if it1 mod 4 > 1:
      var it2 = it1
      var it3 = it2 * 2
      result = true
      if not(it3 > 4):
        return false)()

compared to

import sequtils

var n = zip(a, b).
            mapIt(f(it[0], it[1])).
            filterIt(it mod 4 > 1).
            mapIt(it * 2).
            allIt(it > 4)

which is roughly equivalent to

var m = min(a.len, b.len)
var result0: seq[(int, int)]
newSeq(result0, m)
for i in 0 .. <m:
  result0[i] = (m[i], m[i])
var result1: seq[int]
let t0 = result0
var i0 = 0
result1 = newSeq[int](result0.len)
for it in t0:
  result1[i0] = f(it[0], it[1])
  i0 += 1
var result2 = newSeq[int]()
for it in items(result1):
  if it mod 4 > 1:
    result.add(it)
var result3: seq[int]
let t1 = result1
var i1 = 0
result3 = newSeq[int](result2.len)
for it in t1:
  result3[i1] = it * 2
result = true
for it in items(result3):
  if not (it > 4):
    return false

rationale

Functional style handling of sequences is awesome, and nim is supposed to be fast and smart. Allocating new sequences on each method in chains can be extremely wasteful and there are not a lot of technical reasons to punish functional style like that.

This library can expand functional chains to simple loops fuzing the method bodies one after another. it's still very experimental, but it shows such an purely metaprogramming approach can be used to optimize functional Nim code

install

It should work on the C and the JS backend as well

nimble install zero_functional

or

zero_functional >= 0.0.3`

Supported methods

Those are not exactly the functions from sequtils, they have the some naming and almost the same behavior

The macro works as

sequence --> map(..).any(..)

or

zip(a, b, c) --> map(..).any(..)

You can also use

connect(sequence, map(..), any(..))

The methods work with auto it variable

map

sequence --> map(..)

filter

sequence --> filter(..)

zip

zip is more special, it can be for now only in the begining, and it can work with n sequences

any

any can be used only finally

sequence --> map(..).any(..)

all

all can be used only finally

sequence --> map(..).all(..)

indexedMap

Generates a tuple (position, it)

var n = zip(a, b, c) -->
            indexedMap(f(it[0], it[1])).
            filter(it[0] < 10 and it[1] mod 4 > 1).
            map(it[1] * 2).
            all(it > 4)

fold

Currently a left fold (as easier to combine with my technique)

the sequtils a is a, b is it

var n = zip(a, b) --> map(it[0] + it[1]).fold(0, a + it)

LICENSE

MIT, Alexander Ivanov