Julia: official conventional argument precedence

Created on 28 Oct 2016  路  11Comments  路  Source: JuliaLang/julia

We have a number of conventions about first arguments: functions, I/O objects, types (others?). We should document these conventions explicitly and assign them an official precedence since otherwise when there are conflicts, people tend to simply pick a random order.


16307 (finalizer argument order)

design doc

Most helpful comment

I propose the following priority order (highest priority listed first):

  1. Function argument (for HOFs accepting one function, or for use with do blocks)
  2. IO stream
  3. Thing being mutated (Edit: to hold the main result of the computation)
  4. Type
  5. Collection (not being mutated)
  6. Key
  7. Value
  8. Everything else

Exception: first argument to convert is always the type.

This is an interesting case:

julia> similar(Matrix{Int}, (2,3))
2脳3 Array{Int64,2}: ...

julia> similar(rand(2,3), Int)
2脳3 Array{Int64,2}: ...

julia> collect(Int, [1.0,2.0])
2-element Array{Int64,1}:

I think collect is ok; shown for comparison purposes. There may be no hope for similar except to switch it to all keyword arguments.

All 11 comments

Related topic: should mutated arguments for foo! style functions come first? We've mostly moved this way, but rand! continues to be an exception.

I propose the following priority order (highest priority listed first):

  1. Function argument (for HOFs accepting one function, or for use with do blocks)
  2. IO stream
  3. Thing being mutated (Edit: to hold the main result of the computation)
  4. Type
  5. Collection (not being mutated)
  6. Key
  7. Value
  8. Everything else

Exception: first argument to convert is always the type.

This is an interesting case:

julia> similar(Matrix{Int}, (2,3))
2脳3 Array{Int64,2}: ...

julia> similar(rand(2,3), Int)
2脳3 Array{Int64,2}: ...

julia> collect(Int, [1.0,2.0])
2-element Array{Int64,1}:

I think collect is ok; shown for comparison purposes. There may be no hope for similar except to switch it to all keyword arguments.

Using keyword args for similar would be nice and self-documenting.

:+1: With regards to the position of "things being mutated," one of the patterns I seem to fall into in my own code is a separation between outputs and caches/temporary workspace arguments; I tend to put outputs near the front but workspace variables towards the end. I'm not recommending this specific approach, but I bring it up in case the distinction is worth considering.

I think that's a fairly common distinction, @timholy 鈥撀營 believe that it comes from C APIs. I read about this recently, and can try to find a reference to it.

Regarding Jeff' comment above, this feels like a really principled ordering which would be pretty confusing to new and mid-level users like me.

Roughly, when I'm trying to remember the order of function arguments, I'm not thinking about IOStreams and Types and Collections: I'm thinking about required and optional arguments. And understandably, the current language is pretty inconsistent about whether optional arguments go first, last, or some combination thereof. Maybe that just means new users need to change their thinking - and it has e.g. become natural to think of functions going first for do blocks.

I raised similar concerns here in #20402.

print_with_color taking a color first instead of an IO (making it incompatible with sprint) should probably be looked at.

  1. Key
  2. Value

Would setindex! be another exception?

One could directly address this with a caveat saying "When one of these is varargs it can be moved to last place"

Is parse the same exception like convert? For me the (optional) type argument on 2nd place would be more natural.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

wilburtownsend picture wilburtownsend  路  3Comments

musm picture musm  路  3Comments

sbromberger picture sbromberger  路  3Comments

dpsanders picture dpsanders  路  3Comments

i-apellaniz picture i-apellaniz  路  3Comments