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?
>>
>

Reply via email to