Ideomatic way to write a function that works with a collection of any Number (any subtype of type)

186 views
Skip to first unread message

Andrei Zh

unread,
Jul 8, 2014, 5:01:54 PM7/8/14
to julia...@googlegroups.com
Here's another question about code style. Let's say I want to write function "inc()" that just adds 1 to its (typed) argument. For simple numbers I can force parameter to be of type Number:

  julia> function inc(x::Number) x + 1 end
  inc (generic function with 1 method)

  julia> inc(1)
  2

  julia> inc(1.)
  2.0

For parametrised collections, however, it doesn't work, since Julia's type parameters are invariant:

  julia> function inc(x::Vector{Number}) x + 1 end
  inc (generic function with 2 methods)

  julia> inc([1, 2])
  ERROR: no method inc(Array{Int64,1})

  julia> inc([1., 2.])
  ERROR: no method inc(Array{Float64,1})

As a workaround I use parametrized functions, which work just fine:

  julia> function inc{T <: Number}(x::Vector{T}) x + 1 end
  inc (generic function with 3 methods)

  julia> inc([1, 2])
  2-element Array{Int64,1}:
   2
   3

  julia> inc([1., 2.])
  2-element Array{Float64,1}:
   2.0
   3.0

But since operations on vectors of (any) numbers are so common, I would expect simpler / shorter way to write them. More generally, I wonder if there's a better way to write functions with collections parametrized by abstract classes.

Additional (but closely related) question: is there any run-time overhead for function arguments with abstract type parameters over several functions with concrete types? E.g. is writing "inc(x::Vector{Int})" and "inc(x::Vector{Float64})" faster than "function inc{T <: Number}(x::Vector{T})"?

John Myles White

unread,
Jul 8, 2014, 5:51:41 PM7/8/14
to julia...@googlegroups.com
What you're doing isn't a workaround: it's the correct way to do this in the current version of Julia. There may be shorthand in the future, but this is the right approach today.

-- John

Iain Dunning

unread,
Jul 8, 2014, 9:19:51 PM7/8/14
to julia...@googlegroups.com
For your "additional" question: no overhead for the abstract version versus the two specialized. Don't think of them as types like in C/C++ function definition, think of them as a filter. Julia will compile a new version for every type input you put in anyway that is specialized for the type parsed in.

Iain Dunning

unread,
Jul 8, 2014, 9:20:24 PM7/8/14
to julia...@googlegroups.com
(on a related note, for the same reason type assertions in a method definition don't actually improve performance)

Andrei Zh

unread,
Jul 9, 2014, 2:08:24 AM7/9/14
to julia...@googlegroups.com


(on a related note, for the same reason type assertions in a method definition don't actually improve performance)

On Tuesday, July 8, 2014 6:19:51 PM UTC-7, Iain Dunning wrote:
For your "additional" question: no overhead for the abstract version versus the two specialized. Don't think of them as types like in C/C++ function definition, think of them as a filter. Julia will compile a new version for every type input you put in anyway that is specialized for the type parsed in.

Does it mean that method dispatching, i.e. choice of concrete code to execute, always happens in run-time and never in compile time?  Is there relevant C code on GitHub that I can look at?

Tim Holy

unread,
Jul 9, 2014, 5:30:50 AM7/9/14
to julia...@googlegroups.com
inference.jl exists to infer your types at compile time. There are cases where
it can't do so successfully, in which case the type indeed has to be
determined at runtime. But this failure happens relatively rarely, and a "git
log --oneline | grep -i infer" will show you that a lot of work has gone into
making this work so well.

Play around with code_typed a bit to see this in action. A great source of
information is http://blog.leahhanson.us/julia-introspects.html

--Tim

Steven G. Johnson

unread,
Jul 9, 2014, 11:15:51 AM7/9/14
to julia...@googlegroups.com
On Tuesday, July 8, 2014 9:19:51 PM UTC-4, Iain Dunning wrote:
For your "additional" question: no overhead for the abstract version versus the two specialized. Don't think of them as types like in C/C++ function definition, think of them as a filter. Julia will compile a new version for every type input you put in anyway that is specialized for the type parsed in.

I like this description of Julia function argument types as filters.   It would be good to use this language in the manual somewhere.
Reply all
Reply to author
Forward
0 new messages