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.
E.g. https://github.com/JuliaLang/julia/pull/18931#issuecomment-256487526
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):
do
blocks)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.
- Key
- 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.
Most helpful comment
I propose the following priority order (highest priority listed first):
do
blocks)Exception: first argument to
convert
is always the type.This is an interesting case:
I think
collect
is ok; shown for comparison purposes. There may be no hope forsimilar
except to switch it to all keyword arguments.