Actually, looking at it again with fresh eyes - I can define a few new classes inhering from Ordering, and then define my own lt(o, x, [j-1]) for each. It looks like these predefined orderings and lt methods in the sorting api - ForwardOrdering, ReverseOrdering and so on are fast as their lt() methods are defined as:
lt(o::ForwardOrdering, a, b) = isless(a,b)lt(o::ReverseOrdering, a, b) = lt(o.fwd,b,a) Whereas with feeding in custom functions it builds a Lt Operdering type that contains a reference for the custom Lt function - which I believe is the slow version. On Wednesday, June 17, 2015 at 11:20:47 PM UTC+1, Ben Ward wrote: > > I guess for Base sort! passing a functior overriding call() as lt is > possible, if it accepts the three arguments passed to lt in lt(o, x, v[j-1 > ]) > > On Wednesday, June 17, 2015 at 9:11:22 PM UTC+1, Kristoffer Carlsson wrote: >> >> You could also use something called functors which basically are types >> that overload the call function. When you pass these as argument the >> compiler can specialize the function on the type of the functor and thus >> inline the call. See here for example for them being used effectively for >> performance increase: https://github.com/JuliaLang/julia/pull/11685 >> >> As an example I took the code for insertionsort and made it instead >> accept an argument f which will be the functor. I then create some functors >> to sort on the different type fields and show an example how sort is called. >> >> >> function sort!(v::AbstractVector, f, lo::Int=1, hi::Int=length(v)) >> @inbounds for i = lo+1:hi >> j = i >> x = v[i] >> while j > lo >> if f(x, v[j-1]) >> v[j] = v[j-1] >> j -= 1 >> continue >> end >> break >> end >> v[j] = x >> end >> return v >> end >> >> # Some type >> immutable CompType >> a::Int >> b::Int >> c::Int >> end >> >> >> b = [CompType(1,2,3), CompType(3,2,1), CompType(2,1,3)] >> >> # Functors >> immutable AFunc end >> call(::AFunc, x, y) = x.a < y.a >> immutable BFunc end >> call(::BFunc, x, y) = x.b < y.b >> immutable CFunc end >> call(::CFunc, x, y) = x.c < y.c >> >> # Can now sort with good performance >> sort!(b, AFunc()) >> println(b) >> sort!(b, BFunc()) >> println(b) >> sort!(b, CFunc()) >> println(b) >> >> >> Now, this is of course not optimal to rip code out of base. It would be >> better if we could pass a functor straight to Base.sort!. >> >> >> On Wednesday, June 17, 2015 at 8:13:41 PM UTC+2, Ben Ward wrote: >>> >>> Hi, I want to create a macro with which I can create a function with a >>> custom bit of code: >>> >>> In the repl I can do a toy example: >>> >>> >>> *name = :hi* >>> >>> >>> *vectype = Vector{Int}* >>> >>> >>> *quote** function ($name)(v::$vectype)* >>> >>> *println("hi")* >>> >>> *end* >>> >>> *end* >>> >>> However if I try to put this in a macro and use it I get an error: >>> >>> *macro customFun(vectype::DataType, name::Symbol)* >>> >>> >>> * quote** function ($name)(v::$vectype)* >>> >>> * println("hi World!")* >>> >>> * end* >>> >>> * end* >>> >>> >>> >>> *end* >>> >>> *@customFun(Vector{Int}, :hi)* >>> >>> What am I doing wrong? I'd like to use macro arguments to provide a >>> function's name, and the datatype of the argument. I haven't used macros to >>> define functions more complex than simple one liners. >>> >>> Thanks, >>> Ben. >>> >>
