Wed, 22 Dec 2021 11:14:38 +0200
Add metaprogramming tools and fast multidimensional loops.
################## # Metaprogramming ################## """ `module AlgTools.MetaProgramming` This module implements helpers for metaprogramming, used, e.g., by `Loops`. It includes the macros `@foldl`, `@all`, and `@map` and the metaprogramming functions `foldl_exprs`, `all_exprs`, `map_exprs`, `lift_exprs`, and `sequence_exprs`. """ module Metaprogramming ############## # Our exports ############## export @foldl, @all, @map, foldl_exprs, all_exprs, map_exprs, lift_exprs, sequence_exprs ########################################### # Support functions for macro construction ########################################### """" `foldl_exprs(f, a)` Does `foldl` on the `Expr`s in `a` with the `f`, a `Function` or another `Expr` representing a function. Returns new `Expr` with the expanded `foldl` operation. """ function foldl_exprs(f :: Expr, a) return foldl((b, c) -> :($f($b, $c)), a) end function foldl_exprs(f :: Function, a) return foldl((b, c) -> :($(f(b, c))), a) end """" `all_exprs(a...)` Does `all` on the `Expr`s in `a`. Returns new `Expr` with the expanded `all` operation. """ function all_exprs(a) return foldl((b, c) -> :( $b && $c ), a) end """" `map_exprs(f, a...)` Does `map` on the `Expr`s in `a` with the `f`, a `Function` or another `Expr` representing a function. Returns a new `NTuple` with `Expr`s for the result of applying a to all elements of `a`. """ function map_exprs(f :: Expr , a) return ([ :( $f($b) ) for b ∈ a ]...,) end function map_exprs(f :: Function , a) return ([ :( $(f(b)) ) for b ∈ a ]...,) end """" `lift_exprs(a)` Turns a `Tuple` `a` of `Expr`s into an `Expr` containing `Tuple`. """ function lift_exprs(a) return :( ($(a...),) ) end """ `sequence_exprs(a)` Turns a `Tuple` `a` of `Expr`s into an `Expr` with each original expr on its own line (separated by `;`). """ function sequence_exprs(a) return foldl_exprs((b, c) -> :( $b; $c ), a) end ######### # Macros ######### """" `@foldl(f, a...)` A basic macro version of `foldl`. """ macro foldl(f, a...) return foldl_exprs(f, a) end """" `@all(a...)` A macro version of `all`. """ macro all(a...) # Implementation based on @foldl: #return :( @foldl((b, c) -> b && c, $(a...)) ) # Direct implementation produces prettier generated code: return all_exprs(a) end """" `map(f, a...)` A macro version of `map`. """ macro map(f, a...) return lift_exprs(map_exprs(f, a)) end end # module