I have to do some investigating here. I thought we could do something like that but wasn't quite sure how it would look.
Check this out: This code using FastAnonymous optimizes to the very same code below it where functions have been manually injected: using FastAnonymous function function1(a, b, function2) if(a > b) c = a + b return function2(c) else # do anything # but return nothing end end z = 10 function2 = @anon c -> (c + z) a = 1 b = 2 @code_llvm function1(a, b, function2) @code_native function1(a, b, function2) Manually unrolled equivalent: function function1(a, b, z) if(a > b) c = a + b return function2(c, z) else # do anything # but return nothing end end function function2(c, z) return c + z end a = 1 b = 2 z = 10 @code_llvm function1(a, b, z) @code_native function1(a, b, z) However, this is a bit too simplistic. My program actually does this: # Test to see if multiple functions are created. They are. # We would only need to create a single function if we used julia anon, but its time inefficient. dict = Dict{Int, Any}() for z = 1:100 function2 = @anon c -> (c + z) dict[z] = function2 end a = 1 b = 2 function test() function1(a,b, dict[100]) function1(a,b, dict[50]) end @code_llvm test() @code_native test() So we end up creating multiple functions for each z value. We could use Julia's anon funs, which would only create a single function, however these lamdas are less performant than FastAnon. So its a space vs time tradeoff, I want the speed of FastAnon, without the spacial overhead of storing multiple functions. Can we be greedy? :) On Thursday, January 21, 2016 at 9:56:51 PM UTC-5, Cedric St-Jean wrote: > > Something like this? > > function function1(a, b, f) # Variable needed in callback fun injected. > if(a > b) > c = a + b > res = f(c) # Callback function has been injected. > return res + 1 > else > # do anything > # but return nothing > end > end > > type SomeCallBack > z::Int > end > Base.call(callback::SomeCallBack, c) = c + callback.z > > function1(2, 1, SomeCallBack(10)) > > Because of JIT, this is 100% equivalent to your "callback function has > been injected" example, performance-wise. My feeling is that .call > overloading is not to be abused in Julia, so I would favor using a regular > function call with a descriptive name instead of call overloading, but the > same performance guarantees apply. Does that answer your question? > > On Thursday, January 21, 2016 at 9:02:50 PM UTC-5, Bryan Rivera wrote: >> >> I think what I wrote above might be too complicated, as it is an attempt >> to solve this problem. >> >> In essence this is what I want: >> >> >> >> function function1(a, b, onGreaterThanCallback) >> if(a > b) >> c = a + b >> res = onGreaterThanCallback(c, z) >> return res + 1 >> else >> # do anything >> # but return nothing >> end >> end >> >> >> global onGreaterThanCallback = (c) -> c + z >> >> function1(a, b, onGreaterThanCallback) >> >> >> Problems: >> >> The global variable. >> >> The anonymous function which has performance impact (vs other >> approaches). We could use Tim Holy's @anon, but then the value of `z` is >> fixed at function definition, which we don't always want. >> >> I think that the ideal optimization would look like this: >> >> function function1(a, b, z) # Variable needed in callback fun >> injected. >> if(a > b) >> c = a + b >> res = c + z # Callback function has been injected. >> return res + 1 >> else >> # do anything >> # but return nothing >> end >> end >> >> >> function1(a, b, z) >> >> In OO languages we would be using an abstract class or its equivalent. >> But I've thought about it, and read the discussions on interfaces, and >> don't see those solutions optimizing the code out like I did above. >> >> Any ideas? >> >