> > 'Traditional' Julia: you can pass a function f as an argument to another > function g. > > Rafael's functors: instead you create new type F whose constructor is f, > and then you make g a parametric function with a parameter F instead of an > argument f. >
A typo here, the constructor of type F is F, and that's the point: F is both a type and a "callable". > And the point of this technique is that you can potentially boost > performance because the compiler can in-line the implicit call to f > inherent in g{F}(...), whereas the call to f in g(f,...) cannot be inlined. > Yes (but I think it is planned to make the compiler be able to inline normal functions... maybe by being desugared to functors ;-) ). The declaration of g must be like g{F}(::Type{F}, ...) to enable inlining, and simply g(F, ...) or g(F::DataType, ...) otherwise (AFAIU, g would then have only one specialization for all F::DataType, as typeof(F)==DataType). Have I got it? Are there other advantages to Rafael's functors (simplified > code, better error-checking...) compared to 'traditional' Julia? > One application is using the inheritance machinery (type constraints...), eg to take Stefan's example from https://github.com/JuliaLang/julia/issues/1470: abstract BinaryOperator function call{op<:BinaryOperator}(::Type{op}, v::Vector, w::Vector) # implement generic vectorized operation in terms of functor op end function call{op<:BinaryOperator}(::Type{op}, v::Vector, x) # implement generic op(vector, scalar) end type plus <: BinaryOperator end plus(a::Number, b::Number) = a+b plus(args...) = call(plus, args...) # delegate everything else to super types This is less ideal than what is proposed in issue 1470, as one has to write the delegating code (last line above) for each new sub-type of BinaryOperator, however only one generic such line is necessary (and can be macroized :) ).