The need for this functionality come up recently in this topic:
Given an array of small functions (array length up to 200), each of them had to be computed for a large set of inputs. The problem was that dynamic dispatch took too long compared to the actual calculation.
FunctionWranglers.jl started as a solution of this issue. It uses template (meta)programming to unroll loops that call several functions, and to allow static dispatch/inlining on dinamically provided functions.
The following operations are implemented as of now:
smap!
maps a single set of arguments using all the functions into a preallocated array.sfindfirst
looks for the first function which returnstrue
for the given arguments, and returns its index.
sreduce
transforms a single value using the composite of the functions, and also allows you to provide extra “context” arguments to the functions.
The smap!
function can be used to solve the above issue:
| | |_| | | | (_| | | Version 1.5.2 (2020-09-23)
_/ |\__'_|_|_|\__'_| | Official https://julialang.org/ release
|__/
julia> using FunctionWranglers
julia> create_adder(value) = (x) -> x + value
create_adder (generic function with 1 method)
julia> adders = Function[create_adder(i) for i = 1:5]
5-element Array{Function,1}:
#3 (generic function with 1 method)
#3 (generic function with 1 method)
#3 (generic function with 1 method)
#3 (generic function with 1 method)
#3 (generic function with 1 method)
julia> w = FunctionWrangler(adders)
FunctionWrangler with 5 items: #3, #3, #3, #3, #3,
julia> result = zeros(Float64, length(adders))
5-element Array{Float64,1}:
0.0
0.0
0.0
0.0
0.0
julia> smap!(result, w, 10.0)
julia> result
5-element Array{Float64,1}:
11.0
12.0
13.0
14.0
15.0
julia> @btime smap!($result, $w, d) setup = (d = rand())
3.934 ns (0 allocations: 0 bytes)
sfindfirst
mimics DOM event handling, sreduce
is mostly a robust \circ. They can be used e.g. for inlining user provided callbacks.
Note that the s
prefix stays for “switched”, as the role of the functions and the data is reversed compared to the normal use (or for “static”, as the value of package is that it allows static dispatch).
A bit more info can be found in the readme.
I hope you find this helpful!