## [Promotion](#Promotion)
Floating-point values are promoted to the largest of the floating-point argument types. Integer values are promoted to the largest of the integer argument types. If the types are the same size but differ in signedness, the unsigned type is chosen. Mixtures of integers and floating-point values are promoted to a floating-point type big enough to hold all the values. Integers mixed with rationals are promoted to rationals. Rationals mixed with floats are promoted to floats. Complex values mixed with real values are promoted to the appropriate kind of complex value.
That is really all there is to using promotions. The rest is just a matter of clever application, the most typical "clever" application being the definition of catch-all methods for numeric operations like the arithmetic operators `+`, `-`, `*` and `/`. Here are some of the catch-all method definitions given in [`promotion.jl`](https://github.com/JuliaLang/julia/blob/master/base/promotion.jl):
```julia
+(x::Number, y::Number) = +(promote(x,y)...)
-(x::Number, y::Number) = -(promote(x,y)...)
*(x::Number, y::Number) = *(promote(x,y)...)
/(x::Number, y::Number) = /(promote(x,y)...)
```


## [Promotion](#Promotion)
These method definitions say that in the absence of more specific rules for adding, subtracting, multiplying and dividing pairs of numeric values, promote the values to a common type and then try again. That's all there is to it: nowhere else does one ever need to worry about promotion to a common numeric type for arithmetic operations – it just happens automatically. There are definitions of catch-all promotion methods for a number of other arithmetic and mathematical functions in [`promotion.jl`](https://github.com/JuliaLang/julia/blob/master/base/promotion.jl), but beyond that, there are hardly any calls to `promote` required in Julia Base. The most common usages of `promote` occur in outer constructors methods, provided for convenience, to allow constructor calls with mixed types to delegate to an inner type with fields promoted to an appropriate common type. For example, recall that [`rational.jl`](https://github.com/JuliaLang/julia/blob/master/base/rational.jl) provides the following outer constructor method:
```julia
Rational(n::Integer, d::Integer) = Rational(promote(n,d)...)
```
This allows calls like the following to work:
```julia-repl
julia> x = Rational(Int8(15),Int32(-5))
-3//1

julia> typeof(x)
Rational{Int32}
```
For most user-defined types, it is better practice to require programmers to supply the expected types to constructor functions explicitly, but sometimes, especially for numeric problems, it can be convenient to do promotion automatically.


### [Defining Promotion Rules](#Defining-Promotion-Rules)
Although one could, in principle, define methods for the `promote` function directly, this would require many redundant definitions for all possible permutations of argument types. Instead, the behavior of `promote` is defined in terms of an auxiliary function called [`promote_rule`](../../base/base/#Base.promote_rule), which one can provide methods for. The `promote_rule` function takes a pair of type objects and returns another type object, such that instances of the argument types will be promoted to the returned type. Thus, by defining the rule:
```julia
import Base: promote_rule
promote_rule(::Type{Float64}, ::Type{Float32}) = Float64
```
one declares that when 64-bit and 32-bit floating-point values are promoted together, they should be promoted to 64-bit floating-point. The promotion type does not need to be one of the argument types. For example, the following promotion rules both occur in Julia Base:
```julia
promote_rule(::Type{BigInt}, ::Type{Float64}) = BigFloat
promote_rule(::Type{BigInt}, ::Type{Int8}) = BigInt
```
In the latter case, the result type is [`BigInt`](../../base/numbers/#Base.GMP.BigInt) since `BigInt` is the only type large enough to hold integers for arbitrary-precision integer arithmetic. Also note that one does not need to define both `promote_rule(::Type{A}, ::Type{B})` and `promote_rule(::Type{B}, ::Type{A})` – the symmetry is implied by the way `promote_rule` is used in the promotion process.


### [Defining Promotion Rules](#Defining-Promotion-Rules)
The `promote_rule` function is used as a building block to define a second function called [`promote_type`](../../base/base/#Base.promote_type), which, given any number of type objects, returns the common type to which those values, as arguments to `promote` should be promoted. Thus, if one wants to know, in absence of actual values, what type a collection of values of certain types would promote to, one can use `promote_type`:
```julia-repl
julia> promote_type(Int8, Int64)
Int64
```
Note that we do **not** overload `promote_type` directly: we overload `promote_rule` instead. `promote_type` uses `promote_rule`, and adds the symmetry. Overloading it directly can cause ambiguity errors. We overload `promote_rule` to define how things should be promoted, and we use `promote_type` to query that.
Internally, `promote_type` is used inside of `promote` to determine what type argument values should be converted to for promotion. The curious reader can read the code in [`promotion.jl`](https://github.com/JuliaLang/julia/blob/master/base/promotion.jl), which defines the complete promotion mechanism in about 35 lines.


### [Case Study: Rational Promotions](#Case-Study:-Rational-Promotions)
Finally, we finish off our ongoing case study of Julia's rational number type, which makes relatively sophisticated use of the promotion mechanism with the following promotion rules:
```julia
import Base: promote_rule
promote_rule(::Type{Rational{T}}, ::Type{S}) where {T<:Integer,S<:Integer} = Rational{promote_type(T,S)}
promote_rule(::Type{Rational{T}}, ::Type{Rational{S}}) where {T<:Integer,S<:Integer} = Rational{promote_type(T,S)}
promote_rule(::Type{Rational{T}}, ::Type{S}) where {T<:Integer,S<:AbstractFloat} = promote_type(T,S)
```
The first rule says that promoting a rational number with any other integer type promotes to a rational type whose numerator/denominator type is the result of promotion of its numerator/denominator type with the other integer type. The second rule applies the same logic to two different types of rational numbers, resulting in a rational of the promotion of their respective numerator/denominator types. The third and final rule dictates that promoting a rational with a float results in the same type as promoting the numerator/denominator type with the float.


### [Case Study: Rational Promotions](#Case-Study:-Rational-Promotions)
This small handful of promotion rules, together with the type's constructors and the default `convert` method for numbers, are sufficient to make rational numbers interoperate completely naturally with all of Julia's other numeric types – integers, floating-point numbers, and complex numbers. By providing appropriate conversion methods and promotion rules in the same manner, any user-defined numeric type can interoperate just as naturally with Julia's predefined numerics.
------------------------------------------------------------------------


# Interfaces · The Julia Language
Source: https://docs.julialang.org/en/v1/manual/interfaces/


# [Interfaces](#Interfaces)
A lot of the power and extensibility in Julia comes from a collection of informal interfaces. By extending a few specific methods to work for a custom type, objects of that type not only receive those functionalities, but they are also able to be used in other methods that are written to generically build upon those behaviors.


## [Iteration](#man-interface-iteration)
There are two methods that are always required:
| Required method                                         | Brief description                                                                                |
|:--------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------|
| [`iterate(iter)`](../../base/collections/#Base.iterate) | Returns either a tuple of the first item and initial state or [`nothing`](../../base/constants/#Core.nothing) if empty |
| `iterate(iter, state)`                                  | Returns either a tuple of the next item and next state or `nothing` if no items remain                                 |
There are several more methods that should be defined in some circumstances. Please note that you should always define at least one of `Base.IteratorSize(IterType)` and `length(iter)` because the default definition of `Base.IteratorSize(IterType)` is `Base.HasLength()`.


## [Iteration](#man-interface-iteration)
| Method                                                                         | When should this method be defined?                                         | Default definition | Brief description                                                                                |
|:-------------------------------------------------------------------------------|:----------------------------------------------------------------------------|:-------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [`Base.IteratorSize(IterType)`](../../base/collections/#Base.IteratorSize)     | If default is not appropriate                                               | `Base.HasLength()` | One of `Base.HasLength()`, `Base.HasShape{N}()`, `Base.IsInfinite()`, or `Base.SizeUnknown()` as appropriate                                                                                |
| [`length(iter)`](../../base/arrays/#Base.length-Tuple%7BAbstractArray%7D)      | If `Base.IteratorSize()` returns `Base.HasLength()` or `Base.HasShape{N}()` | (*undefined*)      | The number of items, if known                                                                                |
| [`size(iter, [dim])`](../../base/arrays/#Base.size)                            | If `Base.IteratorSize()` returns `Base.HasShape{N}()`                       | (*undefined*)      | The number of items in each dimension, if known                                                                                |
| [`Base.IteratorEltype(IterType)`](../../base/collections/#Base.IteratorEltype) | If default is not appropriate                                               | `Base.HasEltype()` | Either `Base.EltypeUnknown()` or `Base.HasEltype()` as appropriate                                                                                |
| [`eltype(IterType)`](../../base/collections/#Base.eltype)                      | If default is not appropriate                                               | `Any`              | The type of the first entry of the tuple returned by `iterate()`                                                                                |
| [`Base.isdone(iter, [state])`](../../base/collections/#Base.isdone)            | **Must** be defined if iterator is stateful                                 | `missing`          | Fast-path hint for iterator completion. If not defined for a stateful iterator then functions that check for done-ness, like `isempty()` and `zip()`, may mutate the iterator and cause buggy behaviour! |


## [Iteration](#man-interface-iteration)
Sequential iteration is implemented by the [`iterate`](../../base/collections/#Base.iterate) function. Instead of mutating objects as they are iterated over, Julia iterators may keep track of the iteration state externally from the object. The return value from iterate is always either a tuple of a value and a state, or `nothing` if no elements remain. The state object will be passed back to the iterate function on the next iteration and is generally considered an implementation detail private to the iterable object.
Any object that defines this function is iterable and can be used in the [many functions that rely upon iteration](../../base/collections/#lib-collections-iteration). It can also be used directly in a [`for`](../../base/base/#for) loop since the syntax:
```julia
for item in iter   # or  "for item = iter"
    # body
end
```
is translated into:
```julia
next = iterate(iter)
while next !== nothing
    (item, state) = next
    # body
    next = iterate(iter, state)
end
```
A simple example is an iterable sequence of square numbers with a defined length:
```julia-repl
julia> struct Squares
           count::Int
       end

julia> Base.iterate(S::Squares, state=1) = state > S.count ? nothing : (state*state, state+1)
```
With only [`iterate`](../../base/collections/#Base.iterate) definition, the `Squares` type is already pretty powerful. We can iterate over all the elements:
```julia-repl
julia> for item in Squares(7)
           println(item)
       end
1
4
9
16
25
36
49
```


## [Iteration](#man-interface-iteration)
We can use many of the builtin methods that work with iterables, like [`in`](../../base/collections/#Base.in) or [`sum`](../../base/collections/#Base.sum):
```julia-repl
julia> 25 in Squares(10)
true

julia> sum(Squares(100))
338350
```
There are a few more methods we can extend to give Julia more information about this iterable collection. We know that the elements in a `Squares` sequence will always be `Int`. By extending the [`eltype`](../../base/collections/#Base.eltype) method, we can give that information to Julia and help it make more specialized code in the more complicated methods. We also know the number of elements in our sequence, so we can extend [`length`](../../base/collections/#Base.length), too:
```julia-repl
julia> Base.eltype(::Type{Squares}) = Int # Note that this is defined for the type

julia> Base.length(S::Squares) = S.count
```
Now, when we ask Julia to [`collect`](../../base/collections/#Base.collect-Tuple%7BAny%7D) all the elements into an array it can preallocate a `Vector{Int}` of the right size instead of naively [`push!`](../../base/collections/#Base.push!)ing each element into a `Vector{Any}`:
```julia-repl
julia> collect(Squares(4))
4-element Vector{Int64}:
  1
  4
  9
 16
```
While we can rely upon generic implementations, we can also extend specific methods where we know there is a simpler algorithm. For example, there's a formula to compute the sum of squares, so we can override the generic iterative version with a more performant solution:


## [Iteration](#man-interface-iteration)
```julia-repl
julia> Base.sum(S::Squares) = (n = S.count; return n*(n+1)*(2n+1)÷6)

julia> sum(Squares(1803))
1955361914
```
This is a very common pattern throughout Julia Base: a small set of required methods define an informal interface that enable many fancier behaviors. In some cases, types will want to additionally specialize those extra behaviors when they know a more efficient algorithm can be used in their specific case.
It is also often useful to allow iteration over a collection in *reverse order* by iterating over [`Iterators.reverse(iterator)`](../../base/iterators/#Base.Iterators.reverse). To actually support reverse-order iteration, however, an iterator type `T` needs to implement `iterate` for `Iterators.Reverse{T}`. (Given `r::Iterators.Reverse{T}`, the underling iterator of type `T` is `r.itr`.) In our `Squares` example, we would implement `Iterators.Reverse{Squares}` methods:
```julia-repl
julia> Base.iterate(rS::Iterators.Reverse{Squares}, state=rS.itr.count) = state < 1 ? nothing : (state*state, state-1)

julia> collect(Iterators.reverse(Squares(4)))
4-element Vector{Int64}:
 16
  9
  4
  1
```


## [Indexing](#Indexing)
| Methods to implement | Brief description                                             |
|:---------------------|:--------------------------------------------------------------|
| `getindex(X, i)`     | `X[i]`, indexed access, non-scalar `i` should allocate a copy |
| `setindex!(X, v, i)` | `X[i] = v`, indexed assignment                                |
| `firstindex(X)`      | The first index, used in `X[begin]`                           |
| `lastindex(X)`       | The last index, used in `X[end]`                              |
For the `Squares` iterable above, we can easily compute the `i`th element of the sequence by squaring it. We can expose this as an indexing expression `S[i]`. To opt into this behavior, `Squares` simply needs to define [`getindex`](../../base/collections/#Base.getindex):
```julia-repl
julia> function Base.getindex(S::Squares, i::Int)
           1 <= i <= S.count || throw(BoundsError(S, i))
           return i*i
       end

julia> Squares(100)[23]
529
```
Additionally, to support the syntax `S[begin]` and `S[end]`, we must define [`firstindex`](../../base/collections/#Base.firstindex) and [`lastindex`](../../base/collections/#Base.lastindex) to specify the first and last valid indices, respectively:
```julia-repl
julia> Base.firstindex(S::Squares) = 1

julia> Base.lastindex(S::Squares) = length(S)

julia> Squares(23)[end]
529
```


## [Indexing](#Indexing)
For multi-dimensional `begin`/`end` indexing as in `a[3, begin, 7]`, for example, you should define `firstindex(a, dim)` and `lastindex(a, dim)` (which default to calling `first` and `last` on `axes(a, dim)`, respectively).
Note, though, that the above *only* defines [`getindex`](../../base/collections/#Base.getindex) with one integer index. Indexing with anything other than an `Int` will throw a [`MethodError`](../../base/base/#Core.MethodError) saying that there was no matching method. In order to support indexing with ranges or vectors of `Int`s, separate methods must be written:
```julia-repl
julia> Base.getindex(S::Squares, i::Number) = S[convert(Int, i)]

julia> Base.getindex(S::Squares, I) = [S[i] for i in I]

julia> Squares(10)[[3,4.,5]]
3-element Vector{Int64}:
  9
 16
 25
```
While this is starting to support more of the [indexing operations supported by some of the builtin types](../arrays/#man-array-indexing), there's still quite a number of behaviors missing. This `Squares` sequence is starting to look more and more like a vector as we've added behaviors to it. Instead of defining all these behaviors ourselves, we can officially define it as a subtype of an [`AbstractArray`](../../base/arrays/#Core.AbstractArray).


## [Abstract Arrays](#man-interface-array)
| Methods to implement                     |                                        | Brief description                                                                                |
|:-----------------------------------------|:---------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `size(A)`                                |                                        | Returns a tuple containing the dimensions of `A`                                                                                |
| `getindex(A, i::Int)`                    |                                        | (if `IndexLinear`) Linear scalar indexing                                                                                |
| `getindex(A, I::Vararg{Int, N})`         |                                        | (if `IndexCartesian`, where `N = ndims(A)`) N-dimensional scalar indexing                                                                                |
| **Optional methods**                     | **Default definition**                 | **Brief description**                                                                                |
| `IndexStyle(::Type)`                     | `IndexCartesian()`                     | Returns either `IndexLinear()` or `IndexCartesian()`. See the description below.                                                                                |
| `setindex!(A, v, i::Int)`                |                                        | (if `IndexLinear`) Scalar indexed assignment                                                                                |
| `setindex!(A, v, I::Vararg{Int, N})`     |                                        | (if `IndexCartesian`, where `N = ndims(A)`) N-dimensional scalar indexed assignment                                                                              |
| `getindex(A, I...)`                      | defined in terms of scalar `getindex`  | [Multidimensional and nonscalar indexing](../arrays/#man-array-indexing)                                                                                |
| `setindex!(A, X, I...)`                  | defined in terms of scalar `setindex!` | [Multidimensional and nonscalar indexed assignment](../arrays/#man-array-indexing)                                                                               |
| `iterate`                                | defined in terms of scalar `getindex`  | Iteration                                                                                |
| `length(A)`                              | `prod(size(A))`                        | Number of elements                                                                                |
| `similar(A)`                             | `similar(A, eltype(A), size(A))`       | Return a mutable array with the same shape and element type                                                                                |
| `similar(A, ::Type{S})`                  | `similar(A, S, size(A))`               | Return a mutable array with the same shape and the specified element type                                                                                |
| `similar(A, dims::Dims)`                 | `similar(A, eltype(A), dims)`          | Return a mutable array with the same element type and size *dims*                                                                                |
| `similar(A, ::Type{S}, dims::Dims)`      | `Array{S}(undef, dims)`                | Return a mutable array with the specified element type and size                                                                                |
| **Non-traditional indices**              | **Default definition**                 | **Brief description**                                                                                |
| `axes(A)`                                | `map(OneTo, size(A))`                  | Return a tuple of `AbstractUnitRange{<:Integer}` of valid indices. The axes should be their own axes, that is `axes.(axes(A),1) == axes(A)` should be satisfied. |
| `similar(A, ::Type{S}, inds)`            | `similar(A, S, Base.to_shape(inds))`   | Return a mutable array with the specified indices `inds` (see below)                                                                                |
| `similar(T::Union{Type,Function}, inds)` | `T(Base.to_shape(inds))`               | Return an array similar to `T` with the specified indices `inds` (see below)                                                                                |


## [Abstract Arrays](#man-interface-array)
If a type is defined as a subtype of `AbstractArray`, it inherits a very large set of rich behaviors including iteration and multidimensional indexing built on top of single-element access. See the [arrays manual page](../arrays/#man-multi-dim-arrays) and the [Julia Base section](../../base/arrays/#lib-arrays) for more supported methods.
A key part in defining an `AbstractArray` subtype is [`IndexStyle`](../../base/arrays/#Base.IndexStyle). Since indexing is such an important part of an array and often occurs in hot loops, it's important to make both indexing and indexed assignment as efficient as possible. Array data structures are typically defined in one of two ways: either it most efficiently accesses its elements using just one index (linear indexing) or it intrinsically accesses the elements with indices specified for every dimension. These two modalities are identified by Julia as `IndexLinear()` and `IndexCartesian()`. Converting a linear index to multiple indexing subscripts is typically very expensive, so this provides a traits-based mechanism to enable efficient generic code for all array types.


## [Abstract Arrays](#man-interface-array)
This distinction determines which scalar indexing methods the type must define. `IndexLinear()` arrays are simple: just define `getindex(A::ArrayType, i::Int)`. When the array is subsequently indexed with a multidimensional set of indices, the fallback `getindex(A::AbstractArray, I...)` efficiently converts the indices into one linear index and then calls the above method. `IndexCartesian()` arrays, on the other hand, require methods to be defined for each supported dimensionality with `ndims(A)` `Int` indices. For example, [`SparseMatrixCSC`](../../stdlib/SparseArrays/#SparseArrays.SparseMatrixCSC) from the `SparseArrays` standard library module, only supports two dimensions, so it just defines `getindex(A::SparseMatrixCSC, i::Int, j::Int)`. The same holds for [`setindex!`](../../base/collections/#Base.setindex!).
Returning to the sequence of squares from above, we could instead define it as a subtype of an `AbstractArray{Int, 1}`:
```julia-repl
julia> struct SquaresVector <: AbstractArray{Int, 1}
           count::Int
       end

julia> Base.size(S::SquaresVector) = (S.count,)

julia> Base.IndexStyle(::Type{<:SquaresVector}) = IndexLinear()

julia> Base.getindex(S::SquaresVector, i::Int) = i*i
```


## [Abstract Arrays](#man-interface-array)
Note that it's very important to specify the two parameters of the `AbstractArray`; the first defines the [`eltype`](../../base/collections/#Base.eltype), and the second defines the [`ndims`](../../base/arrays/#Base.ndims). That supertype and those three methods are all it takes for `SquaresVector` to be an iterable, indexable, and completely functional array:
```julia-repl
julia> s = SquaresVector(4)
4-element SquaresVector:
  1
  4
  9
 16

julia> s[s .> 8]
2-element Vector{Int64}:
  9
 16

julia> s + s
4-element Vector{Int64}:
  2
  8
 18
 32

julia> sin.(s)
4-element Vector{Float64}:
  0.8414709848078965
 -0.7568024953079282
  0.4121184852417566
 -0.2879033166650653
```
As a more complicated example, let's define our own toy N-dimensional sparse-like array type built on top of [`Dict`](../../base/collections/#Base.Dict):
```julia-repl
julia> struct SparseArray{T,N} <: AbstractArray{T,N}
           data::Dict{NTuple{N,Int}, T}
           dims::NTuple{N,Int}
       end

julia> SparseArray(::Type{T}, dims::Int...) where {T} = SparseArray(T, dims);

julia> SparseArray(::Type{T}, dims::NTuple{N,Int}) where {T,N} = SparseArray{T,N}(Dict{NTuple{N,Int}, T}(), dims);

julia> Base.size(A::SparseArray) = A.dims

julia> Base.similar(A::SparseArray, ::Type{T}, dims::Dims) where {T} = SparseArray(T, dims)

julia> Base.getindex(A::SparseArray{T,N}, I::Vararg{Int,N}) where {T,N} = get(A.data, I, zero(T))

julia> Base.setindex!(A::SparseArray{T,N}, v, I::Vararg{Int,N}) where {T,N} = (A.data[I] = v)
```


## [Abstract Arrays](#man-interface-array)
Notice that this is an `IndexCartesian` array, so we must manually define [`getindex`](../../base/collections/#Base.getindex) and [`setindex!`](../../base/collections/#Base.setindex!) at the dimensionality of the array. Unlike the `SquaresVector`, we are able to define [`setindex!`](../../base/collections/#Base.setindex!), and so we can mutate the array:
```julia-repl
julia> A = SparseArray(Float64, 3, 3)
3×3 SparseArray{Float64, 2}:
 0.0  0.0  0.0
 0.0  0.0  0.0
 0.0  0.0  0.0

julia> fill!(A, 2)
3×3 SparseArray{Float64, 2}:
 2.0  2.0  2.0
 2.0  2.0  2.0
 2.0  2.0  2.0

julia> A[:] = 1:length(A); A
3×3 SparseArray{Float64, 2}:
 1.0  4.0  7.0
 2.0  5.0  8.0
 3.0  6.0  9.0
```
The result of indexing an `AbstractArray` can itself be an array (for instance when indexing by an `AbstractRange`). The `AbstractArray` fallback methods use [`similar`](../../base/arrays/#Base.similar) to allocate an `Array` of the appropriate size and element type, which is filled in using the basic indexing method described above. However, when implementing an array wrapper you often want the result to be wrapped as well:
```julia-repl
julia> A[1:2,:]
2×3 SparseArray{Float64, 2}:
 1.0  4.0  7.0
 2.0  5.0  8.0
```


## [Abstract Arrays](#man-interface-array)
In this example it is accomplished by defining `Base.similar(A::SparseArray, ::Type{T}, dims::Dims) where T` to create the appropriate wrapped array. (Note that while `similar` supports 1- and 2-argument forms, in most case you only need to specialize the 3-argument form.) For this to work it's important that `SparseArray` is mutable (supports `setindex!`). Defining `similar`, `getindex` and `setindex!` for `SparseArray` also makes it possible to [`copy`](../../base/base/#Base.copy) the array:
```julia-repl
julia> copy(A)
3×3 SparseArray{Float64, 2}:
 1.0  4.0  7.0
 2.0  5.0  8.0
 3.0  6.0  9.0
```
In addition to all the iterable and indexable methods from above, these types can also interact with each other and use most of the methods defined in Julia Base for `AbstractArrays`:
```julia-repl
julia> A[SquaresVector(3)]
3-element SparseArray{Float64, 1}:
 1.0
 4.0
 9.0

julia> sum(A)
45.0
```
If you are defining an array type that allows non-traditional indexing (indices that start at something other than 1), you should specialize [`axes`](../../base/arrays/#Base.axes-Tuple%7BAny%7D). You should also specialize [`similar`](../../base/arrays/#Base.similar) so that the `dims` argument (ordinarily a `Dims` size-tuple) can accept `AbstractUnitRange` objects, perhaps range-types `Ind` of your own design. For more information, see [Arrays with custom indices](../../devdocs/offset-arrays/#man-custom-indices).


## [Strided Arrays](#man-interface-strided-arrays)
| Methods to implement                     |                        | Brief description                                                                                |
|:-----------------------------------------|:-----------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `strides(A)`                             |                        | Return the distance in memory (in number of elements) between adjacent elements in each dimension as a tuple. If `A` is an `AbstractArray{T,0}`, this should return an empty tuple. |
| `Base.unsafe_convert(::Type{Ptr{T}}, A)` |                        | Return the native address of an array.                                                                                |
| `Base.elsize(::Type{<:A})`               |                        | Return the stride between consecutive elements in the array.                                                                                |
| **Optional methods**                     | **Default definition** | **Brief description**                                                                                |
| `stride(A, i::Int)`                      | `strides(A)[i]`        | Return the distance in memory (in number of elements) between adjacent elements in dimension k.                                                                                |


## [Strided Arrays](#man-interface-strided-arrays)
A strided array is a subtype of `AbstractArray` whose entries are stored in memory with fixed strides. Provided the element type of the array is compatible with BLAS, a strided array can utilize BLAS and LAPACK routines for more efficient linear algebra routines. A typical example of a user-defined strided array is one that wraps a standard `Array` with additional structure.
Warning: do not implement these methods if the underlying storage is not actually strided, as it may lead to incorrect results or segmentation faults.
Here are some examples to demonstrate which type of arrays are strided and which are not:
```julia
1:5   # not strided (there is no storage associated with this array.)
Vector(1:5)  # is strided with strides (1,)
A = [1 5; 2 6; 3 7; 4 8]  # is strided with strides (1,4)
V = view(A, 1:2, :)   # is strided with strides (1,4)
V = view(A, 1:2:3, 1:2)   # is strided with strides (2,4)
V = view(A, [1,2,4], :)   # is not strided, as the spacing between rows is not fixed.
```


## [Customizing broadcasting](#man-interfaces-broadcasting)
| Methods to implement                                       | Brief description                                                                                |
|:-----------------------------------------------------------|:----------------------------------------------------------------------------------------------------|
| `Base.BroadcastStyle(::Type{SrcType}) = SrcStyle()`        | Broadcasting behavior of `SrcType`                                                                  |
| `Base.similar(bc::Broadcasted{DestStyle}, ::Type{ElType})` | Allocation of output container                                                                      |
| **Optional methods**                                       |                                                                                |
| `Base.BroadcastStyle(::Style1, ::Style2) = Style12()`      | Precedence rules for mixing styles                                                                  |
| `Base.axes(x)`                                             | Declaration of the indices of `x`, as per [`axes(x)`](../../base/arrays/#Base.axes-Tuple%7BAny%7D). |
| `Base.broadcastable(x)`                                    | Convert `x` to an object that has `axes` and supports indexing                                      |
| **Bypassing default machinery**                            |                                                                                |
| `Base.copy(bc::Broadcasted{DestStyle})`                    | Custom implementation of `broadcast`                                                                |
| `Base.copyto!(dest, bc::Broadcasted{DestStyle})`           | Custom implementation of `broadcast!`, specializing on `DestStyle`                                  |
| `Base.copyto!(dest::DestType, bc::Broadcasted{Nothing})`   | Custom implementation of `broadcast!`, specializing on `DestType`                                   |
| `Base.Broadcast.broadcasted(f, args...)`                   | Override the default lazy behavior within a fused expression                                        |
| `Base.Broadcast.instantiate(bc::Broadcasted{DestStyle})`   | Override the computation of the lazy broadcast's axes                                               |


## [Customizing broadcasting](#man-interfaces-broadcasting)
[Broadcasting](../arrays/#Broadcasting) is triggered by an explicit call to `broadcast` or `broadcast!`, or implicitly by "dot" operations like `A .+ b` or `f.(x, y)`. Any object that has [`axes`](../../base/arrays/#Base.axes-Tuple%7BAny%7D) and supports indexing can participate as an argument in broadcasting, and by default the result is stored in an `Array`. This basic framework is extensible in three major ways:
-   Ensuring that all arguments support broadcast
-   Selecting an appropriate output array for the given set of arguments
-   Selecting an efficient implementation for the given set of arguments
Not all types support `axes` and indexing, but many are convenient to allow in broadcast. The [`Base.broadcastable`](../../base/arrays/#Base.Broadcast.broadcastable) function is called on each argument to broadcast, allowing it to return something different that supports `axes` and indexing. By default, this is the identity function for all `AbstractArray`s and `Number`s — they already support `axes` and indexing.
If a type is intended to act like a "0-dimensional scalar" (a single object) rather than as a container for broadcasting, then the following method should be defined:
```julia
Base.broadcastable(o::MyType) = Ref(o)
```


## [Customizing broadcasting](#man-interfaces-broadcasting)
that returns the argument wrapped in a 0-dimensional [`Ref`](../../base/c/#Core.Ref) container. For example, such a wrapper method is defined for types themselves, functions, special singletons like [`missing`](../missing/#missing) and [`nothing`](../../base/constants/#Core.nothing), and dates.
Custom array-like types can specialize `Base.broadcastable` to define their shape, but they should follow the convention that `collect(Base.broadcastable(x)) == collect(x)`. A notable exception is `AbstractString`; strings are special-cased to behave as scalars for the purposes of broadcast even though they are iterable collections of their characters (see [Strings](../../devdocs/ast/#Strings) for more).
The next two steps (selecting the output array and implementation) are dependent upon determining a single answer for a given set of arguments. Broadcast must take all the varied types of its arguments and collapse them down to just one output array and one implementation. Broadcast calls this single answer a "style". Every broadcastable object each has its own preferred style, and a promotion-like system is used to combine these styles into a single answer — the "destination style".


### [Broadcast Styles](#Broadcast-Styles)
`Base.BroadcastStyle` is the abstract type from which all broadcast styles are derived. When used as a function it has two possible forms, unary (single-argument) and binary. The unary variant states that you intend to implement specific broadcasting behavior and/or output type, and do not wish to rely on the default fallback [`Broadcast.DefaultArrayStyle`](../../base/arrays/#Base.Broadcast.DefaultArrayStyle).
To override these defaults, you can define a custom `BroadcastStyle` for your object:
```julia
struct MyStyle <: Broadcast.BroadcastStyle end
Base.BroadcastStyle(::Type{<:MyType}) = MyStyle()
```
In some cases it might be convenient not to have to define `MyStyle`, in which case you can leverage one of the general broadcast wrappers:
-   `Base.BroadcastStyle(::Type{<:MyType}) = Broadcast.Style{MyType}()` can be used for arbitrary types.
-   `Base.BroadcastStyle(::Type{<:MyType}) = Broadcast.ArrayStyle{MyType}()` is preferred if `MyType` is an `AbstractArray`.
-   For `AbstractArrays` that only support a certain dimensionality, create a subtype of `Broadcast.AbstractArrayStyle{N}` (see below).
When your broadcast operation involves several arguments, individual argument styles get combined to determine a single `DestStyle` that controls the type of the output container. For more details, see [below](#writing-binary-broadcasting-rules).


### [Selecting an appropriate output array](#Selecting-an-appropriate-output-array)
The broadcast style is computed for every broadcasting operation to allow for dispatch and specialization. The actual allocation of the result array is handled by `similar`, using the Broadcasted object as its first argument.
```julia
Base.similar(bc::Broadcasted{DestStyle}, ::Type{ElType})
```
The fallback definition is
```julia
similar(bc::Broadcasted{DefaultArrayStyle{N}}, ::Type{ElType}) where {N,ElType} =
    similar(Array{ElType}, axes(bc))
```
However, if needed you can specialize on any or all of these arguments. The final argument `bc` is a lazy representation of a (potentially fused) broadcast operation, a `Broadcasted` object. For these purposes, the most important fields of the wrapper are `f` and `args`, describing the function and argument list, respectively. Note that the argument list can — and often does — include other nested `Broadcasted` wrappers.
For a complete example, let's say you have created a type, `ArrayAndChar`, that stores an array and a single character:
```julia
struct ArrayAndChar{T,N} <: AbstractArray{T,N}
    data::Array{T,N}
    char::Char
end
Base.size(A::ArrayAndChar) = size(A.data)
Base.getindex(A::ArrayAndChar{T,N}, inds::Vararg{Int,N}) where {T,N} = A.data[inds...]
Base.setindex!(A::ArrayAndChar{T,N}, val, inds::Vararg{Int,N}) where {T,N} = A.data[inds...] = val
Base.showarg(io::IO, A::ArrayAndChar, toplevel) = print(io, typeof(A), " with char '", A.char, "'")
```
You might want broadcasting to preserve the `char` "metadata". First we define


### [Selecting an appropriate output array](#Selecting-an-appropriate-output-array)
```julia
Base.BroadcastStyle(::Type{<:ArrayAndChar}) = Broadcast.ArrayStyle{ArrayAndChar}()
```
This means we must also define a corresponding `similar` method:
```julia
function Base.similar(bc::Broadcast.Broadcasted{Broadcast.ArrayStyle{ArrayAndChar}}, ::Type{ElType}) where ElType
    # Scan the inputs for the ArrayAndChar:
    A = find_aac(bc)
    # Use the char field of A to create the output
    ArrayAndChar(similar(Array{ElType}, axes(bc)), A.char)
end

"`A = find_aac(As)` returns the first ArrayAndChar among the arguments."
find_aac(bc::Base.Broadcast.Broadcasted) = find_aac(bc.args)
find_aac(args::Tuple) = find_aac(find_aac(args[1]), Base.tail(args))
find_aac(x) = x
find_aac(::Tuple{}) = nothing
find_aac(a::ArrayAndChar, rest) = a
find_aac(::Any, rest) = find_aac(rest)
```
From these definitions, one obtains the following behavior:
```julia-repl
julia> a = ArrayAndChar([1 2; 3 4], 'x')
2×2 ArrayAndChar{Int64, 2} with char 'x':
 1  2
 3  4

julia> a .+ 1
2×2 ArrayAndChar{Int64, 2} with char 'x':
 2  3
 4  5

julia> a .+ [5,10]
2×2 ArrayAndChar{Int64, 2} with char 'x':
  6   7
 13  14
```


### [Extending broadcast with custom implementations](#extending-in-place-broadcast)
In general, a broadcast operation is represented by a lazy `Broadcasted` container that holds onto the function to be applied alongside its arguments. Those arguments may themselves be more nested `Broadcasted` containers, forming a large expression tree to be evaluated. A nested tree of `Broadcasted` containers is directly constructed by the implicit dot syntax; `5 .+ 2.*x` is transiently represented by `Broadcasted(+, 5, Broadcasted(*, 2, x))`, for example. This is invisible to users as it is immediately realized through a call to `copy`, but it is this container that provides the basis for broadcast's extensibility for authors of custom types. The built-in broadcast machinery will then determine the result type and size based upon the arguments, allocate it, and then finally copy the realization of the `Broadcasted` object into it with a default `copyto!(::AbstractArray, ::Broadcasted)` method. The built-in fallback `broadcast` and `broadcast!` methods similarly construct a transient `Broadcasted` representation of the operation so they can follow the same codepath. This allows custom array implementations to provide their own `copyto!` specialization to customize and optimize broadcasting. This is again determined by the computed broadcast style. This is such an important part of the operation that it is stored as the first type parameter of the `Broadcasted` type, allowing for dispatch and specialization.


### [Extending broadcast with custom implementations](#extending-in-place-broadcast)
For some types, the machinery to "fuse" operations across nested levels of broadcasting is not available or could be done more efficiently incrementally. In such cases, you may need or want to evaluate `x .* (x .+ 1)` as if it had been written `broadcast(*, x, broadcast(+, x, 1))`, where the inner operation is evaluated before tackling the outer operation. This sort of eager operation is directly supported by a bit of indirection; instead of directly constructing `Broadcasted` objects, Julia lowers the fused expression `x .* (x .+ 1)` to `Broadcast.broadcasted(*, x, Broadcast.broadcasted(+, x, 1))`. Now, by default, `broadcasted` just calls the `Broadcasted` constructor to create the lazy representation of the fused expression tree, but you can choose to override it for a particular combination of function and arguments.
As an example, the builtin `AbstractRange` objects use this machinery to optimize pieces of broadcasted expressions that can be eagerly evaluated purely in terms of the start, step, and length (or stop) instead of computing every single element. Just like all the other machinery, `broadcasted` also computes and exposes the combined broadcast style of its arguments, so instead of specializing on `broadcasted(f, args...)`, you can specialize on `broadcasted(::DestStyle, f, args...)` for any combination of style, function, and arguments.
For example, the following definition supports the negation of ranges:


### [Extending broadcast with custom implementations](#extending-in-place-broadcast)
```julia
broadcasted(::DefaultArrayStyle{1}, ::typeof(-), r::OrdinalRange) = range(-first(r), step=-step(r), length=length(r))
```


### [Extending in-place broadcasting](#extending-in-place-broadcast-2)
In-place broadcasting can be supported by defining the appropriate `copyto!(dest, bc::Broadcasted)` method. Because you might want to specialize either on `dest` or the specific subtype of `bc`, to avoid ambiguities between packages we recommend the following convention.
If you wish to specialize on a particular style `DestStyle`, define a method for
```julia
copyto!(dest, bc::Broadcasted{DestStyle})
```
Optionally, with this form you can also specialize on the type of `dest`.
If instead you want to specialize on the destination type `DestType` without specializing on `DestStyle`, then you should define a method with the following signature:
```julia
copyto!(dest::DestType, bc::Broadcasted{Nothing})
```
This leverages a fallback implementation of `copyto!` that converts the wrapper into a `Broadcasted{Nothing}`. Consequently, specializing on `DestType` has lower precedence than methods that specialize on `DestStyle`.
Similarly, you can completely override out-of-place broadcasting with a `copy(::Broadcasted)` method.


#### [Working with Broadcasted objects](#Working-with-Broadcasted-objects)
In order to implement such a `copy` or `copyto!`, method, of course, you must work with the `Broadcasted` wrapper to compute each element. There are two main ways of doing so:
-   `Broadcast.flatten` recomputes the potentially nested operation into a single function and flat list of arguments. You are responsible for implementing the broadcasting shape rules yourself, but this may be helpful in limited situations.
-   Iterating over the `CartesianIndices` of the `axes(::Broadcasted)` and using indexing with the resulting `CartesianIndex` object to compute the result.


### [Writing binary broadcasting rules](#writing-binary-broadcasting-rules)
The precedence rules are defined by binary `BroadcastStyle` calls:
```julia
Base.BroadcastStyle(::Style1, ::Style2) = Style12()
```
where `Style12` is the `BroadcastStyle` you want to choose for outputs involving arguments of `Style1` and `Style2`. For example,
```julia
Base.BroadcastStyle(::Broadcast.Style{Tuple}, ::Broadcast.AbstractArrayStyle{0}) = Broadcast.Style{Tuple}()
```
indicates that `Tuple` "wins" over zero-dimensional arrays (the output container will be a tuple). It is worth noting that you do not need to (and should not) define both argument orders of this call; defining one is sufficient no matter what order the user supplies the arguments in.
For `AbstractArray` types, defining a `BroadcastStyle` supersedes the fallback choice, [`Broadcast.DefaultArrayStyle`](../../base/arrays/#Base.Broadcast.DefaultArrayStyle). `DefaultArrayStyle` and the abstract supertype, `AbstractArrayStyle`, store the dimensionality as a type parameter to support specialized array types that have fixed dimensionality requirements.
`DefaultArrayStyle` "loses" to any other `AbstractArrayStyle` that has been defined because of the following methods:
```julia
BroadcastStyle(a::AbstractArrayStyle{Any}, ::DefaultArrayStyle) = a
BroadcastStyle(a::AbstractArrayStyle{N}, ::DefaultArrayStyle{N}) where N = a
BroadcastStyle(a::AbstractArrayStyle{M}, ::DefaultArrayStyle{N}) where {M,N} =
    typeof(a)(Val(max(M, N)))
```


### [Writing binary broadcasting rules](#writing-binary-broadcasting-rules)
You do not need to write binary `BroadcastStyle` rules unless you want to establish precedence for two or more non-`DefaultArrayStyle` types.
If your array type does have fixed dimensionality requirements, then you should subtype `AbstractArrayStyle`. For example, the sparse array code has the following definitions:
```julia
struct SparseVecStyle <: Broadcast.AbstractArrayStyle{1} end
struct SparseMatStyle <: Broadcast.AbstractArrayStyle{2} end
Base.BroadcastStyle(::Type{<:SparseVector}) = SparseVecStyle()
Base.BroadcastStyle(::Type{<:SparseMatrixCSC}) = SparseMatStyle()
```
Whenever you subtype `AbstractArrayStyle`, you also need to define rules for combining dimensionalities, by creating a constructor for your style that takes a `Val(N)` argument. For example:
```julia
SparseVecStyle(::Val{0}) = SparseVecStyle()
SparseVecStyle(::Val{1}) = SparseVecStyle()
SparseVecStyle(::Val{2}) = SparseMatStyle()
SparseVecStyle(::Val{N}) where N = Broadcast.DefaultArrayStyle{N}()
```
These rules indicate that the combination of a `SparseVecStyle` with 0- or 1-dimensional arrays yields another `SparseVecStyle`, that its combination with a 2-dimensional array yields a `SparseMatStyle`, and anything of higher dimensionality falls back to the dense arbitrary-dimensional framework. These rules allow broadcasting to keep the sparse representation for operations that result in one or two dimensional outputs, but produce an `Array` for any other dimensionality.


## [Instance Properties](#man-instance-properties)
| Methods to implement                             | Default definition      | Brief description                                                                                |
|:-------------------------------------------------|:------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------|
| `propertynames(x::ObjType, private::Bool=false)` | `fieldnames(typeof(x))` | Return a tuple of the properties (`x.property`) of an object `x`. If `private=true`, also return property names intended to be kept as private |
| `getproperty(x::ObjType, s::Symbol)`             | `getfield(x, s)`        | Return property `s` of `x`. `x.s` calls `getproperty(x, :s)`.                                                                                |
| `setproperty!(x::ObjType, s::Symbol, v)`         | `setfield!(x, s, v)`    | Set property `s` of `x` to `v`. `x.s = v` calls `setproperty!(x, :s, v)`. Should return `v`.                                                   |
Sometimes, it is desirable to change how the end-user interacts with the fields of an object. Instead of granting direct access to type fields, an extra layer of abstraction between the user and the code can be provided by overloading `object.field`. Properties are what the user *sees of* the object, fields what the object *actually is*.


## [Instance Properties](#man-instance-properties)
By default, properties and fields are the same. However, this behavior can be changed. For example, take this representation of a point in a plane in [polar coordinates](https://en.wikipedia.org/wiki/Polar_coordinate_system):
```julia-repl
julia> mutable struct Point
           r::Float64
           ϕ::Float64
       end

julia> p = Point(7.0, pi/4)
Point(7.0, 0.7853981633974483)
```
As described in the table above dot access `p.r` is the same as `getproperty(p, :r)` which is by default the same as `getfield(p, :r)`:
```julia-repl
julia> propertynames(p)
(:r, :ϕ)

julia> getproperty(p, :r), getproperty(p, :ϕ)
(7.0, 0.7853981633974483)

julia> p.r, p.ϕ
(7.0, 0.7853981633974483)

julia> getfield(p, :r), getproperty(p, :ϕ)
(7.0, 0.7853981633974483)
```
However, we may want users to be unaware that `Point` stores the coordinates as `r` and `ϕ` (fields), and instead interact with `x` and `y` (properties). The methods in the first column can be defined to add new functionality:


## [Instance Properties](#man-instance-properties)
```julia-repl
julia> Base.propertynames(::Point, private::Bool=false) = private ? (:x, :y, :r, :ϕ) : (:x, :y)

julia> function Base.getproperty(p::Point, s::Symbol)
           if s === :x
               return getfield(p, :r) * cos(getfield(p, :ϕ))
           elseif s === :y
               return getfield(p, :r) * sin(getfield(p, :ϕ))
           else
               # This allows accessing fields with p.r and p.ϕ
               return getfield(p, s)
           end
       end

julia> function Base.setproperty!(p::Point, s::Symbol, f)
           if s === :x
               y = p.y
               setfield!(p, :r, sqrt(f^2 + y^2))
               setfield!(p, :ϕ, atan(y, f))
               return f
           elseif s === :y
               x = p.x
               setfield!(p, :r, sqrt(x^2 + f^2))
               setfield!(p, :ϕ, atan(f, x))
               return f
           else
               # This allow modifying fields with p.r and p.ϕ
               return setfield!(p, s, f)
           end
       end
```
It is important that `getfield` and `setfield` are used inside `getproperty` and `setproperty!` instead of the dot syntax, since the dot syntax would make the functions recursive which can lead to type inference issues. We can now try out the new functionality:
```julia-repl
julia> propertynames(p)
(:x, :y)

julia> p.x
4.949747468305833

julia> p.y = 4.0
4.0

julia> p.r
6.363961030678928
```


## [Instance Properties](#man-instance-properties)
Finally, it is worth noting that adding instance properties like this is quite rarely done in Julia and should in general only be done if there is a good reason for doing so.


## [Rounding](#man-rounding-interface)
| Methods to implement                          | Default definition        | Brief description                                                                                |
|:----------------------------------------------|:--------------------------|:----------------------------------------------------------------------------------------------------|
| `round(x::ObjType, r::RoundingMode)`          | none                      | Round `x` and return the result. If possible, round should return an object of the same type as `x` |
| `round(T::Type, x::ObjType, r::RoundingMode)` | `convert(T, round(x, r))` | Round `x`, returning the result as a `T`                                                            |
To support rounding on a new type it is typically sufficient to define the single method `round(x::ObjType, r::RoundingMode)`. The passed rounding mode determines in which direction the value should be rounded. The most commonly used rounding modes are `RoundNearest`, `RoundToZero`, `RoundDown`, and `RoundUp`, as these rounding modes are used in the definitions of the one argument `round`, method, and `trunc`, `floor`, and `ceil`, respectively.


## [Rounding](#man-rounding-interface)
In some cases, it is possible to define a three-argument `round` method that is more accurate or performant than the two-argument method followed by conversion. In this case it is acceptable to define the three argument method in addition to the two argument method. If it is impossible to represent the rounded result as an object of the type `T`, then the three argument method should throw an `InexactError`.
For example, if we have an `Interval` type which represents a range of possible values similar to https://github.com/JuliaPhysics/Measurements.jl, we may define rounding on that type with the following
```julia-repl
julia> struct Interval{T}
           min::T
           max::T
       end

julia> Base.round(x::Interval, r::RoundingMode) = Interval(round(x.min, r), round(x.max, r))

julia> x = Interval(1.7, 2.2)
Interval{Float64}(1.7, 2.2)

julia> round(x)
Interval{Float64}(2.0, 2.0)

julia> floor(x)
Interval{Float64}(1.0, 2.0)

julia> ceil(x)
Interval{Float64}(2.0, 3.0)

julia> trunc(x)
Interval{Float64}(1.0, 2.0)
```
------------------------------------------------------------------------


# Modules · The Julia Language
Source: https://docs.julialang.org/en/v1/manual/modules/


# [Modules](#modules)
Modules in Julia help organize code into coherent units. They are delimited syntactically inside `module NameOfModule ... end`, and have the following features:
1.  Modules are separate namespaces, each introducing a new global scope. This is useful, because it allows the same name to be used for different functions or global variables without conflict, as long as they are in separate modules.
2.  Modules have facilities for detailed namespace management: each defines a set of names it `export`s and marks as `public`, and can import names from other modules with `using` and `import` (we explain these below).
3.  Modules can be precompiled for faster loading, and may contain code for runtime initialization.
Typically, in larger Julia packages you will see module code organized into files, eg
```julia
module SomeModule

# export, public, using, import statements are usually here; we discuss these below

include("file1.jl")
include("file2.jl")

end
```
Files and file names are mostly unrelated to modules; modules are associated only with module expressions. One can have multiple files per module, and multiple modules per file. `include` behaves as if the contents of the source file were evaluated in the global scope of the including module. In this chapter, we use short and simplified examples, so we won't use `include`.


# [Modules](#modules)
The recommended style is not to indent the body of the module, since that would typically lead to whole files being indented. Also, it is common to use `UpperCamelCase` for module names (just like types), and use the plural form if applicable, especially if the module contains a similarly named identifier, to avoid name clashes. For example,
```julia
module FastThings

struct FastThing
    ...
end

end
```


## [Namespace management](#namespace-management)
Namespace management refers to the facilities the language offers for making names in a module available in other modules. We discuss the related concepts and functionality below in detail.


### [Qualified names](#Qualified-names)
Names for functions, variables and types in the global scope like `sin`, `ARGS`, and `UnitRange` always belong to a module, called the *parent module*, which can be found interactively with [`parentmodule`](../../base/base/#Base.parentmodule), for example
```julia-repl
julia> parentmodule(UnitRange)
Base
```
One can also refer to these names outside their parent module by prefixing them with their module, eg `Base.UnitRange`. This is called a *qualified name*. The parent module may be accessible using a chain of submodules like `Base.Math.sin`, where `Base.Math` is called the *module path*. Due to syntactic ambiguities, qualifying a name that contains only symbols, such as an operator, requires inserting a colon, e.g. `Base.:+`. A small number of operators additionally require parentheses, e.g. `Base.:(==)`.
If a name is qualified, then it is always *accessible*, and in case of a function, it can also have methods added to it by using the qualified name as the function name.
Within a module, a variable name can be “reserved” without assigning to it by declaring it as `global x`. This prevents name conflicts for globals initialized after load time. The syntax `M.x = y` does not work to assign a global in another module; global assignment is always module-local.


### [Export lists](#Export-lists)
Names (referring to functions, types, global variables, and constants) can be added to the *export list* of a module with `export`: these are the symbols that are imported when `using` the module. Typically, they are at or near the top of the module definition so that readers of the source code can find them easily, as in
```julia-repl
julia> module NiceStuff
       export nice, DOG
       struct Dog end      # singleton type, not exported
       const DOG = Dog()   # named instance, exported
       nice(x) = "nice $x" # function, exported
       end;
```
but this is just a style suggestion — a module can have multiple `export` statements in arbitrary locations.
It is common to export names which form part of the API (application programming interface). In the above code, the export list suggests that users should use `nice` and `DOG`. However, since qualified names always make identifiers accessible, this is just an option for organizing APIs: unlike other languages, Julia has no facilities for truly hiding module internals.
Also, some modules don't export names at all. This is usually done if they use common words, such as `derivative`, in their API, which could easily clash with the export lists of other modules. We will see how to manage name clashes below.


### [Export lists](#Export-lists)
To mark a name as public without exporting it into the namespace of folks who call `using NiceStuff`, one can use `public` instead of `export`. This marks the public name(s) as part of the public API, but does not have any namespace implications. The `public` keyword is only available in Julia 1.11 and above. To maintain compatibility with Julia 1.10 and below, use the `@compat` macro from the [Compat](https://github.com/JuliaLang/Compat.jl) package.


### [Standalone using and import](#Standalone-using-and-import)
For interactive use, the most common way of loading a module is `using ModuleName`. This [loads](../code-loading/#code-loading) the code associated with `ModuleName`, and brings
1.  the module name
2.  and the elements of the export list into the surrounding global namespace.
Technically, the statement `using ModuleName` means that a module called `ModuleName` will be available for resolving names as needed. When a global variable is encountered that has no definition in the current module, the system will search for it among variables exported by `ModuleName` and use it if it is found there. This means that all uses of that global within the current module will resolve to the definition of that variable in `ModuleName`.
To load a module from a package, the statement `using ModuleName` can be used. To load a module from a locally defined module, a dot needs to be added before the module name like `using .ModuleName`.
To continue with our example,
```julia-repl
julia> using .NiceStuff
```
would load the above code, making `NiceStuff` (the module name), `DOG` and `nice` available. `Dog` is not on the export list, but it can be accessed if the name is qualified with the module path (which here is just the module name) as `NiceStuff.Dog`.
Importantly, **`using ModuleName` is the only form for which export lists matter at all**.
In contrast,
```julia-repl
julia> import .NiceStuff
```


### [Standalone using and import](#Standalone-using-and-import)
brings *only* the module name into scope. Users would need to use `NiceStuff.DOG`, `NiceStuff.Dog`, and `NiceStuff.nice` to access its contents. Usually, `import ModuleName` is used in contexts when the user wants to keep the namespace clean. As we will see in the next section `import .NiceStuff` is equivalent to `using .NiceStuff: NiceStuff`.
You can combine multiple `using` and `import` statements of the same kind in a comma-separated expression, e.g.
```julia-repl
julia> using LinearAlgebra, Random
```


### [using and import with specific identifiers, and adding methods](#using-and-import-with-specific-identifiers,-and-adding-methods)
When `using ModuleName:` or `import ModuleName:` is followed by a comma-separated list of names, the module is loaded, but *only those specific names are brought into the namespace* by the statement. For example,
```julia-repl
julia> using .NiceStuff: nice, DOG
```
will import the names `nice` and `DOG`.
Importantly, the module name `NiceStuff` will *not* be in the namespace. If you want to make it accessible, you have to list it explicitly, as
```julia-repl
julia> using .NiceStuff: nice, DOG, NiceStuff
```
When two or more packages/modules export a name and that name does not refer to the same thing in each of the packages, and the packages are loaded via `using` without an explicit list of names, it is an error to reference that name without qualification. It is thus recommended that code intended to be forward-compatible with future versions of its dependencies and of Julia, e.g., code in released packages, list the names it uses from each loaded package, e.g., `using Foo: Foo, f` rather than `using Foo`.
Julia has two forms for seemingly the same thing because only `import ModuleName: f` allows adding methods to `f` *without a module path*. That is to say, the following example will give an error:


### [using and import with specific identifiers, and adding methods](#using-and-import-with-specific-identifiers,-and-adding-methods)
```julia-repl
julia> using .NiceStuff: nice

julia> struct Cat end

julia> nice(::Cat) = "nice 😸"
ERROR: invalid method definition in Main: function NiceStuff.nice must be explicitly imported to be extended
Stacktrace:
 [1] top-level scope
   @ none:0
 [2] top-level scope
   @ none:1
```
This error prevents accidentally adding methods to functions in other modules that you only intended to use.
There are two ways to deal with this. You can always qualify function names with a module path:
```julia-repl
julia> using .NiceStuff

julia> struct Cat end

julia> NiceStuff.nice(::Cat) = "nice 😸"
```
Alternatively, you can `import` the specific function name:
```julia-repl
julia> import .NiceStuff: nice

julia> struct Cat end

julia> nice(::Cat) = "nice 😸"
nice (generic function with 2 methods)
```
Which one you choose is a matter of style. The first form makes it clear that you are adding a method to a function in another module (remember, that the imports and the method definition may be in separate files), while the second one is shorter, which is especially convenient if you are defining multiple methods.
Once a variable is made visible via `using` or `import`, a module may not create its own variable with the same name. Imported variables are read-only; assigning to a global variable always affects a variable owned by the current module, or else raises an error.


### [Renaming with as](#Renaming-with-as)
An identifier brought into scope by `import` or `using` can be renamed with the keyword `as`. This is useful for working around name conflicts as well as for shortening names. For example, `Base` exports the function name `read`, but the CSV.jl package also provides `CSV.read`. If we are going to invoke CSV reading many times, it would be convenient to drop the `CSV.` qualifier. But then it is ambiguous whether we are referring to `Base.read` or `CSV.read`:
```julia-repl
julia> read;

julia> import CSV: read
WARNING: ignoring conflicting import of CSV.read into Main
```
Renaming provides a solution:
```julia-repl
julia> import CSV: read as rd
```
Imported packages themselves can also be renamed:
```julia
import BenchmarkTools as BT
```
`as` works with `using` only when a single identifier is brought into scope. For example `using CSV: read as rd` works, but `using CSV as C` does not, since it operates on all of the exported names in `CSV`.


### [Mixing multiple using and import statements](#Mixing-multiple-using-and-import-statements)
When multiple `using` or `import` statements of any of the forms above are used, their effect is combined in the order they appear. For example,
```julia-repl
julia> using .NiceStuff         # exported names and the module name

julia> import .NiceStuff: nice  # allows adding methods to unqualified functions
```
would bring all the exported names of `NiceStuff` and the module name itself into scope, and also allow adding methods to `nice` without prefixing it with a module name.


### [Handling name conflicts](#Handling-name-conflicts)
Consider the situation where two (or more) packages export the same name, as in
```julia-repl
julia> module A
       export f
       f() = 1
       end
A
julia> module B
       export f
       f() = 2
       end
B
```
The statement `using .A, .B` works, but when you try to call `f`, you get an error with a hint
```julia-repl
julia> using .A, .B

julia> f
ERROR: UndefVarError: `f` not defined in `Main`
Hint: It looks like two or more modules export different bindings with this name, resulting in ambiguity. Try explicitly importing it from a particular module, or qualifying the name with the module it should come from.
```
Here, Julia cannot decide which `f` you are referring to, so you have to make a choice. The following solutions are commonly used:
1.  Simply proceed with qualified names like `A.f` and `B.f`. This makes the context clear to the reader of your code, especially if `f` just happens to coincide but has different meaning in various packages. For example, `degree` has various uses in mathematics, the natural sciences, and in everyday life, and these meanings should be kept separate.
2.  Use the `as` keyword above to rename one or both identifiers, eg
    ```julia-repl
    julia> using .A: f as f

    julia> using .B: f as g
    ```
    would make `B.f` available as `g`. Here, we are assuming that you did not use `using A` before, which would have brought `f` into the namespace.


### [Handling name conflicts](#Handling-name-conflicts)
3.  When the names in question *do* share a meaning, it is common for one module to import it from another, or have a lightweight “base” package with the sole function of defining an interface like this, which can be used by other packages. It is conventional to have such package names end in `...Base` (which has nothing to do with Julia's `Base` module).


### [Default top-level definitions and bare modules](#Default-top-level-definitions-and-bare-modules)
Modules automatically contain `using Core`, `using Base`, and definitions of the [`eval`](../../base/base/#eval) and [`include`](../../base/base/#include) functions, which evaluate expressions/files within the global scope of that module.
If these default definitions are not wanted, modules can be defined using the keyword [`baremodule`](../../base/base/#baremodule) instead (note: `Core` is still imported). In terms of `baremodule`, a standard `module` looks like this:
```julia
baremodule Mod

using Base

eval(x) = Core.eval(Mod, x)
include(p) = Base.include(Mod, p)

...

end
```
If even `Core` is not wanted, a module that imports nothing and defines no names at all can be defined with `Module(:YourNameHere, false, false)` and code can be evaluated into it with [`@eval`](../../base/base/#Base.@eval) or [`Core.eval`](../../devdocs/init/#Core.eval):
```julia-repl
julia> arithmetic = Module(:arithmetic, false, false)
Main.arithmetic

julia> @eval arithmetic add(x, y) = $(+)(x, y)
add (generic function with 1 method)

julia> arithmetic.add(12, 13)
25
```


### [Standard modules](#Standard-modules)
There are three important standard modules:
-   [`Core`](../../base/base/#Core) contains all functionality "built into" the language.
-   [`Base`](../../base/base/#Base) contains basic functionality that is useful in almost all cases.
-   [`Main`](../../base/base/#Main) is the top-level module and the current module, when Julia is started.
By default Julia ships with some standard library modules. These behave like regular Julia packages except that you don't need to install them explicitly. For example, if you wanted to perform some unit testing, you could load the `Test` standard library as follows:
```julia
using Test
```


## [Submodules and relative paths](#Submodules-and-relative-paths)
Modules can contain *submodules*, nesting the same syntax `module ... end`. They can be used to introduce separate namespaces, which can be helpful for organizing complex codebases. Note that each `module` introduces its own [scope](../variables-and-scoping/#scope-of-variables), so submodules do not automatically “inherit” names from their parent.
It is recommended that submodules refer to other modules within the enclosing parent module (including the latter) using *relative module qualifiers* in `using` and `import` statements. A relative module qualifier starts with a period (`.`), which corresponds to the current module, and each successive `.` leads to the parent of the current module. This should be followed by modules if necessary, and eventually the actual name to access, all separated by `.`s.
Consider the following example, where the submodule `SubA` defines a function, which is then extended in its “sibling” module:
```julia-repl
julia> module ParentModule
       module SubA
       export add_D  # exported interface
       const D = 3
       add_D(x) = x + D
       end
       using .SubA  # brings `add_D` into the namespace
       export add_D # export it from ParentModule too
       module SubB
       import ..SubA: add_D # relative path for a “sibling” module
       struct Infinity end
       add_D(x::Infinity) = x
       end
       end;
```
You may see code in packages, which, in a similar situation, uses
```julia-repl
julia> import .ParentModule.SubA: add_D
```


## [Submodules and relative paths](#Submodules-and-relative-paths)
However, this operates through [code loading](../code-loading/#code-loading), and thus only works if `ParentModule` is in a package. It is better to use relative paths.
Note that the order of definitions also matters if you are evaluating values. Consider
```julia
module TestPackage

export x, y

x = 0

module Sub
using ..TestPackage
z = y # ERROR: UndefVarError: `y` not defined in `Main`
end

y = 1

end
```
where `Sub` is trying to use `TestPackage.y` before it was defined, so it does not have a value.
For similar reasons, you cannot use a cyclic ordering:
```julia
module A

module B
using ..C # ERROR: UndefVarError: `C` not defined in `Main.A`
end

module C
using ..B
end

end
```


## [Module initialization and precompilation](#Module-initialization-and-precompilation)
Large modules can take several seconds to load because executing all of the statements in a module often involves compiling a large amount of code. Julia creates precompiled caches of the module to reduce this time.
Precompiled module files (sometimes called "cache files") are created and used automatically when `import` or `using` loads a module. If the cache file(s) do not yet exist, the module will be compiled and saved for future reuse. You can also manually call [`Base.compilecache(Base.identify_package("modulename"))`](../../base/base/#Base.compilecache) to create these files without loading the module. The resulting cache files will be stored in the `compiled` subfolder of `DEPOT_PATH[1]`. If nothing about your system changes, such cache files will be used when you load the module with `import` or `using`.
Precompilation cache files store definitions of modules, types, methods, and constants. They may also store method specializations and the code generated for them, but this typically requires that the developer add explicit [`precompile`](../../base/base/#Base.precompile) directives or execute workloads that force compilation during the package build.


## [Module initialization and precompilation](#Module-initialization-and-precompilation)
However, if you update the module's dependencies or change its source code, the module is automatically recompiled upon `using` or `import`. Dependencies are modules it imports, the Julia build, files it includes, or explicit dependencies declared by [`include_dependency(path)`](../../base/base/#Base.include_dependency) in the module file(s).
For file dependencies loaded by `include`, a change is determined by examining whether the file size (`fsize`) or content (condensed into a hash) is unchanged. For file dependencies loaded by `include_dependency` a change is determined by examining whether the modification time (`mtime`) is unchanged, or equal to the modification time truncated to the nearest second (to accommodate systems that can't copy mtime with sub-second accuracy). It also takes into account whether the path to the file chosen by the search logic in `require` matches the path that had created the precompile file. It also takes into account the set of dependencies already loaded into the current process and won't recompile those modules, even if their files change or disappear, in order to avoid creating incompatibilities between the running system and the precompile cache. Finally, it takes account of changes in any [compile-time preferences](../code-loading/#preferences).


## [Module initialization and precompilation](#Module-initialization-and-precompilation)
If you know that a module is *not* safe to precompile (for example, for one of the reasons described below), you should put `__precompile__(false)` in the module file (typically placed at the top). This will cause `Base.compilecache` to throw an error, and will cause `using` / `import` to load it directly into the current process and skip the precompile and caching. This also thereby prevents the module from being imported by any other precompiled module.
You may need to be aware of certain behaviors inherent in the creation of incremental shared libraries which may require care when writing your module. For example, external state is not preserved. To accommodate this, explicitly separate any initialization steps that must occur at *runtime* from steps that can occur at *compile time*. For this purpose, Julia allows you to define an `__init__()` function in your module that executes any initialization steps that must occur at runtime. This function will not be called during compilation (`--output-*`). Effectively, you can assume it will be run exactly once in the lifetime of the code. You may, of course, call it manually if necessary, but the default is to assume this function deals with computing state for the local machine, which does not need to be – or even should not be – captured in the compiled image. It will be called after the module is loaded into a process, including if it is being loaded into an incremental compile (`--output-incremental=yes`), but not if it is being loaded into a full-compilation process.


## [Module initialization and precompilation](#Module-initialization-and-precompilation)
In particular, if you define a `function __init__()` in a module, then Julia will call `__init__()` immediately *after* the module is loaded (e.g., by `import`, `using`, or `require`) at runtime for the *first* time (i.e., `__init__` is only called once, and only after all statements in the module have been executed). Because it is called after the module is fully imported, any submodules or other imported modules have their `__init__` functions called *before* the `__init__` of the enclosing module.
Two typical uses of `__init__` are calling runtime initialization functions of external C libraries and initializing global constants that involve pointers returned by external libraries. For example, suppose that we are calling a C library `libfoo` that requires us to call a `foo_init()` initialization function at runtime. Suppose that we also want to define a global constant `foo_data_ptr` that holds the return value of a `void *foo_data()` function defined by `libfoo` – this constant must be initialized at runtime (not at compile time) because the pointer address will change from run to run. You could accomplish this by defining the following `__init__` function in your module:
```julia
const foo_data_ptr = Ref{Ptr{Cvoid}}(0)
function __init__()
    ccall((:foo_init, :libfoo), Cvoid, ())
    foo_data_ptr[] = ccall((:foo_data, :libfoo), Ptr{Cvoid}, ())
    nothing
end
```


## [Module initialization and precompilation](#Module-initialization-and-precompilation)
Notice that it is perfectly possible to define a global inside a function like `__init__`; this is one of the advantages of using a dynamic language. But by making it a constant at global scope, we can ensure that the type is known to the compiler and allow it to generate better optimized code. Obviously, any other globals in your module that depends on `foo_data_ptr` would also have to be initialized in `__init__`.
Constants involving most Julia objects that are not produced by [`ccall`](../../base/c/#ccall) do not need to be placed in `__init__`: their definitions can be precompiled and loaded from the cached module image. This includes complicated heap-allocated objects like arrays. However, any routine that returns a raw pointer value must be called at runtime for precompilation to work ([`Ptr`](../../base/c/#Core.Ptr) objects will turn into null pointers unless they are hidden inside an [`isbits`](../../base/base/#Base.isbits) object). This includes the return values of the Julia functions [`@cfunction`](../../base/c/#Base.@cfunction) and [`pointer`](../../base/c/#Base.pointer).


## [Module initialization and precompilation](#Module-initialization-and-precompilation)
Dictionary and set types, or in general anything that depends on the output of a `hash(key)` method, are a trickier case. In the common case where the keys are numbers, strings, symbols, ranges, `Expr`, or compositions of these types (via arrays, tuples, sets, pairs, etc.) they are safe to precompile. However, for a few other key types, such as `Function` or `DataType` and generic user-defined types where you haven't defined a `hash` method, the fallback `hash` method depends on the memory address of the object (via its `objectid`) and hence may change from run to run. If you have one of these key types, or if you aren't sure, to be safe you can initialize this dictionary from within your `__init__` function. Alternatively, you can use the [`IdDict`](../../base/collections/#Base.IdDict) dictionary type, which is specially handled by precompilation so that it is safe to initialize at compile-time.
When using precompilation, it is important to keep a clear sense of the distinction between the compilation phase and the execution phase. In this mode, it will often be much more clearly apparent that Julia is a compiler which allows execution of arbitrary Julia code, not a standalone interpreter that also generates compiled code.
Other known potential failure scenarios include:
1.  Global counters (for example, for attempting to uniquely identify objects). Consider the following code snippet:


## [Module initialization and precompilation](#Module-initialization-and-precompilation)
    ```julia
    mutable struct UniquedById
        myid::Int
        let counter = 0
            UniquedById() = new(counter += 1)
        end
    end
    ```
    while the intent of this code was to give every instance a unique id, the counter value is recorded at the end of compilation. All subsequent usages of this incrementally compiled module will start from that same counter value.
    Note that `objectid` (which works by hashing the memory pointer) has similar issues (see notes on `Dict` usage below).
    One alternative is to use a macro to capture [`@__MODULE__`](../../base/base/#Base.@__MODULE__) and store it alone with the current `counter` value, however, it may be better to redesign the code to not depend on this global state.
2.  Associative collections (such as `Dict` and `Set`) need to be re-hashed in `__init__`. (In the future, a mechanism may be provided to register an initializer function.)
3.  Depending on compile-time side-effects persisting through load-time. Example include: modifying arrays or other variables in other Julia modules; maintaining handles to open files or devices; storing pointers to other system resources (including memory);
4.  Creating accidental "copies" of global state from another module, by referencing it directly instead of via its lookup path. For example, (in global scope):


## [Module initialization and precompilation](#Module-initialization-and-precompilation)
    ```julia
    #mystdout = Base.stdout #= will not work correctly, since this will copy Base.stdout into this module =#
    # instead use accessor functions:
    getstdout() = Base.stdout #= best option =#
    # or move the assignment into the runtime:
    __init__() = global mystdout = Base.stdout #= also works =#
    ```
Several additional restrictions are placed on the operations that can be done while precompiling code to help the user avoid other wrong-behavior situations:
1.  Calling [`eval`](../../base/base/#eval) to cause a side-effect in another module. This will also cause a warning to be emitted when the incremental precompile flag is set.
2.  `global const` statements from local scope after `__init__()` has been started (see issue #12010 for plans to add an error for this)
3.  Replacing a module is a runtime error while doing an incremental precompile.
A few other points to be aware of:
1.  No code reload / cache invalidation is performed after changes are made to the source files themselves, (including by `Pkg.update`), and no cleanup is done after `Pkg.rm`
2.  The memory sharing behavior of a reshaped array is disregarded by precompilation (each view gets its own copy)


## [Module initialization and precompilation](#Module-initialization-and-precompilation)
3.  Expecting the filesystem to be unchanged between compile-time and runtime e.g. [`@__FILE__`](../../base/base/#Base.@__FILE__)/`source_path()` to find resources at runtime, or the BinDeps `@checked_lib` macro. Sometimes this is unavoidable. However, when possible, it can be good practice to copy resources into the module at compile-time so they won't need to be found at runtime.
4.  `WeakRef` objects and finalizers are not currently handled properly by the serializer (this will be fixed in an upcoming release).
5.  It is usually best to avoid capturing references to instances of internal metadata objects such as `Method`, `MethodInstance`, `MethodTable`, `TypeMapLevel`, `TypeMapEntry` and fields of those objects, as this can confuse the serializer and may not lead to the outcome you desire. It is not necessarily an error to do this, but you simply need to be prepared that the system will try to copy some of these and to create a single unique instance of others.


## [Module initialization and precompilation](#Module-initialization-and-precompilation)
It is sometimes helpful during module development to turn off incremental precompilation. The command line flag `--compiled-modules={yes|no|existing}` enables you to toggle module precompilation on and off. When Julia is started with `--compiled-modules=no` the serialized modules in the compile cache are ignored when loading modules and module dependencies. In some cases, you may want to load existing precompiled modules, but not create new ones. This can be done by starting Julia with `--compiled-modules=existing`. More fine-grained control is available with `--pkgimages={yes|no|existing}`, which only affects native-code storage during precompilation. `Base.compilecache` can still be called manually. The state of this command line flag is passed to `Pkg.build` to disable automatic precompilation triggering when installing, updating, and explicitly building packages.
You can also debug some precompilation failures with environment variables. Setting `JULIA_VERBOSE_LINKING=true` may help resolve failures in linking shared libraries of compiled native code. See the **Developer Documentation** part of the Julia manual, where you will find further details in the section documenting Julia's internals under "Package Images".
------------------------------------------------------------------------


# Documentation · The Julia Language
Source: https://docs.julialang.org/en/v1/manual/documentation/


# [Documentation](#man-documentation)


## [Accessing Documentation](#Accessing-Documentation)
Documentation can be accessed at the REPL or in [IJulia](https://github.com/JuliaLang/IJulia.jl) by typing `?` followed by the name of a function or macro, and pressing `Enter`. For example,
```julia
?cos
?@time
?r""
```
will show documentation for the relevant function, macro or string macro respectively. Most Julia environments provide a way to access documentation directly:
-   [VS Code](https://www.julia-vscode.org/) shows documentation when you hover over a function name. You can also use the Julia panel in the sidebar to search for documentation.
-   In [Pluto](https://github.com/fonsp/Pluto.jl), open the "Live Docs" panel on the bottom right.
-   In [Juno](https://junolab.org) using `Ctrl-J, Ctrl-D` will show the documentation for the object under the cursor.
`Docs.hasdoc(module, name)::Bool` tells whether a name has a docstring. `Docs.undocumented_names(module; all)` returns the undocumented names in a module.


## [Writing Documentation](#Writing-Documentation)
Julia enables package developers and users to document functions, types and other objects easily via a built-in documentation system.
The basic syntax is simple: any string appearing just before an object (function, macro, type or instance) will be interpreted as documenting it (these are called *docstrings*). Note that no blank lines or comments may intervene between a docstring and the documented object. Here is a basic example:
```julia
"Tell whether there are too foo items in the array."
foo(xs::Array) = ...
```
Documentation is interpreted as [Markdown](https://en.wikipedia.org/wiki/Markdown), so you can use indentation and code fences to delimit code examples from text. Technically, any object can be associated with any other as metadata; Markdown happens to be the default, but one can construct other string macros and pass them to the `@doc` macro just as well.
Markdown support is implemented in the `Markdown` standard library and for a full list of supported syntax see the [documentation](../../stdlib/Markdown/#markdown_stdlib).
Here is a more complex example, still using Markdown:
````julia
"""
    bar(x[, y])

Compute the Bar index between `x` and `y`.

If `y` is unspecified, compute the Bar index between all pairs of columns of `x`.

# Examples
```julia-repl
julia> bar([1, 2], [1, 2])
1
```
"""
function bar(x, y) ...
````
As in the example above, we recommend following some simple conventions when writing documentation:


## [Writing Documentation](#Writing-Documentation)
1.  Always show the signature of a function at the top of the documentation, with a four-space indent so that it is printed as Julia code.
    This can be identical to the signature present in the Julia code (like `mean(x::AbstractArray)`), or a simplified form. Optional arguments should be represented with their default values (i.e. `f(x, y=1)`) when possible, following the actual Julia syntax. Optional arguments which do not have a default value should be put in brackets (i.e. `f(x[, y])` and `f(x[, y[, z]])`). An alternative solution is to use several lines: one without optional arguments, the other(s) with them. This solution can also be used to document several related methods of a given function. When a function accepts many keyword arguments, only include a `<keyword arguments>` placeholder in the signature (i.e. `f(x; <keyword arguments>)`), and give the complete list under an `# Arguments` section (see point 4 below).
2.  Include a single one-line sentence describing what the function does or what the object represents after the simplified signature block. If needed, provide more details in a second paragraph, after a blank line.


## [Writing Documentation](#Writing-Documentation)
    The one-line sentence should use the imperative form ("Do this", "Return that") instead of the third person (do not write "Returns the length...") when documenting functions. It should end with a period. If the meaning of a function cannot be summarized easily, splitting it into separate composable parts could be beneficial (this should not be taken as an absolute requirement for every single case though).
3.  Do not repeat yourself.
    Since the function name is given by the signature, there is no need to start the documentation with "The function `bar`...": go straight to the point. Similarly, if the signature specifies the types of the arguments, mentioning them in the description is redundant.
4.  Only provide an argument list when really necessary.
    For simple functions, it is often clearer to mention the role of the arguments directly in the description of the function's purpose. An argument list would only repeat information already provided elsewhere. However, providing an argument list can be a good idea for complex functions with many arguments (in particular keyword arguments). In that case, insert it after the general description of the function, under an `# Arguments` header, with one `-` bullet for each argument. The list should mention the types and default values (if any) of the arguments:
    ```julia
    """
    ...
    # Arguments
    - `n::Integer`: the number of elements to compute.
    - `dim::Integer=1`: the dimensions along which to perform the computation.
    ...
    """
    ```


## [Writing Documentation](#Writing-Documentation)
5.  Provide hints to related functions.
    Sometimes there are functions of related functionality. To increase discoverability please provide a short list of these in a `See also` paragraph.
    ```julia
    See also [`bar!`](@ref), [`baz`](@ref), [`baaz`](@ref).
    ```
6.  Include any code examples in an `# Examples` section.
    Examples should, whenever possible, be written as *doctests*. A *doctest* is a fenced code block (see [Code blocks](../../stdlib/Markdown/#Code-blocks)) starting with ```````jldoctest ````and contains any number of `julia>` prompts together with inputs and expected outputs that mimic the Julia REPL.
    Doctests are enabled by [`Documenter.jl`](https://github.com/JuliaDocs/Documenter.jl). For more detailed documentation see Documenter's [manual](https://juliadocs.github.io/Documenter.jl/).
    For example in the following docstring a variable `a` is defined and the expected result, as printed in a Julia REPL, appears afterwards:
    ````julia
    """
    Some nice documentation here.

    # Examples
    ```jldoctest
    julia> a = [1 2; 3 4]
    2×2 Array{Int64,2}:
     1  2
     3  4
    ```
    """
    ````


## [Writing Documentation](#Writing-Documentation)
    Calling `rand` and other RNG-related functions should be avoided in doctests since they will not produce consistent outputs during different Julia sessions. If you would like to show some random number generation related functionality, one option is to explicitly construct and seed your own RNG object (see [`Random`](../../stdlib/Random/#Random-Numbers)) and pass it to the functions you are doctesting.
    Operating system word size ([`Int32`](../../base/numbers/#Core.Int32) or [`Int64`](../../base/numbers/#Core.Int64)) as well as path separator differences (`/` or `\`) will also affect the reproducibility of some doctests.
    Note that whitespace in your doctest is significant! The doctest will fail if you misalign the output of pretty-printing an array, for example.
    You can then run `make -C doc doctest=true` to run all the doctests in the Julia Manual and API documentation, which will ensure that your example works.
    To indicate that the output result is truncated, you may write `[...]` at the line where checking should stop. This is useful to hide a stacktrace (which contains non-permanent references to lines of julia code) when the doctest shows that an exception is thrown, for example:
    ````julia
    ```jldoctest
    julia> div(1, 0)
    ERROR: DivideError: integer division error
    [...]
    ```
    ````
    Examples that are untestable should be written within fenced code blocks starting with ```````julia ````so that they are highlighted correctly in the generated documentation.


## [Writing Documentation](#Writing-Documentation)
    Wherever possible examples should be **self-contained** and **runnable** so that readers are able to try them out without having to include any dependencies.
7.  Use backticks to identify code and equations.
    Julia identifiers and code excerpts should always appear between backticks `` ` `` to enable highlighting. Equations in the LaTeX syntax can be inserted between double backticks ````` ```. Use Unicode characters rather than their LaTeX escape sequence, i.e. `````α = 1`` ```rather than `````\\alpha = 1`` ```.
8.  Place the starting and ending `"""` characters on lines by themselves.
    That is, write:
    ```julia
    """
    ...

    ...
    """
    f(x, y) = ...
    ```
    rather than:
    ```julia
    """...

    ..."""
    f(x, y) = ...
    ```
    This makes it clearer where docstrings start and end.
9.  Respect the line length limit used in the surrounding code.
    Docstrings are edited using the same tools as code. Therefore, the same conventions should apply. It is recommended that lines are at most 92 characters wide.
10. Provide information allowing custom types to implement the function in an `# Implementation` section. These implementation details are intended for developers rather than users, explaining e.g. which functions should be overridden and which functions automatically use appropriate fallbacks. Such details are best kept separate from the main description of the function's behavior.


## [Writing Documentation](#Writing-Documentation)
11. For long docstrings, consider splitting the documentation with an `# Extended help` header. The typical help-mode will show only the material above the header; you can access the full help by adding a '?' at the beginning of the expression (i.e., "??foo" rather than "?foo").


## [Functions & Methods](#Functions-and-Methods)
Functions in Julia may have multiple implementations, known as methods. While it's good practice for generic functions to have a single purpose, Julia allows methods to be documented individually if necessary. In general, only the most generic method should be documented, or even the function itself (i.e. the object created without any methods by `function bar end`). Specific methods should only be documented if their behaviour differs from the more generic ones. In any case, they should not repeat the information provided elsewhere. For example:
```julia
"""
    *(x, y, z...)

Multiplication operator. `x * y * z *...` calls this function with multiple
arguments, i.e. `*(x, y, z...)`.
"""
function *(x, y, z...)
    # ... [implementation sold separately] ...
end

"""
    *(x::AbstractString, y::AbstractString, z::AbstractString...)

When applied to strings, concatenates them.
"""
function *(x::AbstractString, y::AbstractString, z::AbstractString...)
    # ... [insert secret sauce here] ...
end

help?> *
search: * .*

  *(x, y, z...)

  Multiplication operator. x * y * z *... calls this function with multiple
  arguments, i.e. *(x,y,z...).

  *(x::AbstractString, y::AbstractString, z::AbstractString...)

  When applied to strings, concatenates them.
```
When retrieving documentation for a generic function, the metadata for each method is concatenated with the `catdoc` function, which can of course be overridden for custom types.