From 0acfd170e92fed447acd315de6ceba0878cf02a4 Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Mon, 18 Dec 2017 16:03:12 -0800 Subject: [PATCH] Document a convention for argument precedence This documents Jeff's proposed convention in #19150 in the manual's style guide. Fixes #19150 [ci skip] --- doc/src/manual/style-guide.md | 56 +++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/doc/src/manual/style-guide.md b/doc/src/manual/style-guide.md index 9108bf3ef4d30f..6d9c2e1de4c741 100644 --- a/doc/src/manual/style-guide.md +++ b/doc/src/manual/style-guide.md @@ -164,6 +164,62 @@ uses (e.g. `a[i]::Int`) than to try to pack many alternatives into one type. If a function name requires multiple words, consider whether it might represent more than one concept and might be better split into pieces. +## Write functions that use similar argument precedence as Julia's `base/` + +As a general rule, the Base library uses the following order of arguments to functions, +as applicable: + +1. **Function argument**. + This permits the use of `do` blocks for passing multiline anonymous functions. + +2. **I/O stream**. + Specifying the `IO` object first permits passing the function to functions such as + [`sprint`](@ref), e.g. `sprint(show, x)`. + +3. **Input being mutated**. + In [`fill!(x, v)`](@ref fill!), `x` is the object being mutated, and it appears before + the value to be inserted into `x`. + +4. **Type**. + Passing a type typically means that the output will have the given type. + In [`read(io, String)`](@ref read), the `IO` argument appears before the type. + +5. **Input not being mutated**. + In `fill!(x, v)`, `v` is *not* being mutated and it comes after `x`. + +6. **Key**. + For associative collections, this is the key of the key-value pair(s). + For other indexed collections, this is the index. + +7. **Value**. + For associative collections, this is the value of the key-value pair(s). + In cases like `fill!(x, v)`, this is `v`. + +8. **Everything else**. + Any other arguments. + +9. **Varargs**. + This refers to arguments that can be listed indefinitely at the end of a function call. + For example, in `Matrix{T}(uninitialized, dims)`, the dimensions can be given as a + `Tuple`, e.g. `Vector{T}(uninitialized, (1,2))`, or as `Varargs`, e.g. + `Vector{T}(uninitialized, 1, 2)`. + +10. **Keyword arguments**. + In Julia keyword arguments have to come last anyway; they're listed here for the sake + of completeness. + +The vast majority of functions will not take every kind of argument listed above; the +numbers merely denote the precedence that should be used for any applicable the arguments +to a function. + +There are of course a few exceptions. +For example, in [`convert`](@ref), the type should always come first. +In [`setindex!`](@ref), the value comes before the indices so that the indices can be +provided as varargs. + +When designing APIs, adhering to this general order as much as possible is likely to give +users of your functions a more consistent experience. + ## Don't overuse try-catch It is better to avoid errors than to rely on catching them.