Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: Clarify important points about parametric types #43891

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
2 changes: 1 addition & 1 deletion base/docs/basedocs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3209,7 +3209,7 @@ converted to type `T` by calling [`convert`](@ref).
In a method declaration, the syntax `function f(x)::T` causes any value returned by
the method to be converted to type `T`.

See the manual section on [Type Declarations](@ref).
See the manual section on [Type Annotations](@ref).

# Examples
```jldoctest
Expand Down
6 changes: 3 additions & 3 deletions doc/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,13 @@ The most significant departures of Julia from typical dynamic languages are:
* The core language imposes very little; Julia Base and the standard library are written in Julia itself, including
primitive operations like integer arithmetic
* A rich language of types for constructing and describing objects, that can also optionally be
used to make type declarations
used to write type annotations
* The ability to define function behavior across many combinations of argument types via [multiple dispatch](https://en.wikipedia.org/wiki/Multiple_dispatch)
* Automatic generation of efficient, specialized code for different argument types
* Good performance, approaching that of statically-compiled languages like C

Although one sometimes speaks of dynamic languages as being "typeless", they are definitely not.
Every object, whether primitive or user-defined, has a type. The lack of type declarations in
Although one sometimes speaks of dynamic languages as being "typeless", they are definitely not:
every object, whether primitive or user-defined, has a type. The lack of type annotations in
most dynamic languages, however, means that one cannot instruct the compiler about the types of
values, and often cannot explicitly talk about types at all. In static languages, on the other
hand, while one can -- and usually must -- annotate types for the compiler, types exist only at
Expand Down
2 changes: 1 addition & 1 deletion doc/src/manual/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ julia> twothreearr()
3
```

## Types, type declarations, and constructors
## Types, type annotations, and constructors

### [What does "type-stable" mean?](@id man-type-stability)

Expand Down
10 changes: 5 additions & 5 deletions doc/src/manual/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,16 +106,16 @@ the call site that at least one of the arguments (often the first one) is being
The behavior of a mutating function can be unexpected when a mutated argument shares memory with another argument, a situation known as aliasing (e.g. when one is a view of the other).
Unless the function docstring explicitly indicates that aliasing produces the expected result, it is the responsibility of the caller to ensure proper behavior on such inputs.

## Argument-type declarations
## Argument-type annotations

You can declare the types of function arguments by appending `::TypeName` to the argument name, as usual for [Type Declarations](@ref) in Julia.
You can declare the types of function arguments by appending `::TypeName` to the argument name, as usual for [Type Annotations](@ref) in Julia.
adigitoleo marked this conversation as resolved.
Show resolved Hide resolved
For example, the following function computes [Fibonacci numbers](https://en.wikipedia.org/wiki/Fibonacci_number) recursively:
```
fib(n::Integer) = n ≤ 2 ? one(n) : fib(n-1) + fib(n-2)
```
and the `::Integer` specification means that it will only be callable when `n` is a subtype of the [abstract](@ref man-abstract-types) `Integer` type.

Argument-type declarations **normally have no impact on performance**: regardless of what argument types (if any) are declared, Julia compiles a specialized version of the function for the actual argument types passed by the caller. For example, calling `fib(1)` will trigger the compilation of specialized version of `fib` optimized specifically for `Int` arguments, which is then re-used if `fib(7)` or `fib(15)` are called. (There are rare exceptions when an argument-type declaration can trigger additional compiler specializations; see: [Be aware of when Julia avoids specializing](@ref).) The most common reasons to declare argument types in Julia are, instead:
Argument-type declarations **normally have no impact on performance**: regardless of what argument types (if any) are declared, Julia compiles a specialized version of the function for the actual argument types passed by the caller. For example, calling `fib(1)` will trigger the compilation of specialized version of `fib` optimized specifically for `Int` arguments, which is then re-used if `fib(7)` or `fib(15)` are called. (There are rare exceptions when an argument-type declaration can trigger additional compiler specializations; see: [Be aware of when Julia avoids specializing](@ref).) The most common reasons to declare argument types in Julia are, instead:

* **Dispatch:** As explained in [Methods](@ref), you can have different versions ("methods") of a function for different argument types, in which case the argument types are used to determine which implementation is called for which arguments. For example, you might implement a completely different algorithm `fib(x::Number) = ...` that works for any `Number` type by using [Binet's formula](https://en.wikipedia.org/wiki/Fibonacci_number#Binet%27s_formula) to extend it to non-integer values.
* **Correctness:** Type declarations can be useful if your function only returns correct results for certain argument types. For example, if we omitted argument types and wrote `fib(n) = n ≤ 2 ? one(n) : fib(n-1) + fib(n-2)`, then `fib(1.5)` would silently give us the nonsensical answer `1.0`.
Expand Down Expand Up @@ -204,9 +204,9 @@ Int8
```

This function will always return an `Int8` regardless of the types of `x` and `y`.
See [Type Declarations](@ref) for more on return types.
See [Type Annotations](@ref) for more on return types.

Return type declarations are **rarely used** in Julia: in general, you should
Return type annotations are **rarely used** in Julia: in general, you should
instead write "type-stable" functions in which Julia's compiler can automatically
infer the return type. For more information, see the [Performance Tips](@ref man-performance-tips) chapter.

Expand Down
2 changes: 1 addition & 1 deletion doc/src/manual/methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ which shows that `f` has two methods, one taking two `Float64` arguments and one
of type `Number`. It also indicates the file and line number where the methods were defined: because
these methods were defined at the REPL, we get the apparent line number `none:1`.

In the absence of a type declaration with `::`, the type of a method parameter is `Any` by default,
In the absence of a type annotation with `::`, the type of a method parameter is `Any` by default,
meaning that it is unconstrained since all values in Julia are instances of the abstract type
`Any`. Thus, we can define a catch-all method for `f` like so:

Expand Down
7 changes: 7 additions & 0 deletions doc/src/manual/performance-tips.md
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,13 @@ better than `IdDict{Type, Vector}`

See also the discussion under [Parametric Types](@ref).

## Type annotations

In many languages with optional type annotations, adding such annotations is the principal way to
make code run faster. This is *not* the case in Julia. In Julia, the compiler generally knows
the types of all function arguments, local variables, and expressions. However, there are a few
specific instances where annotations are helpful.

### Avoid fields with abstract type

Types can be declared without specifying the types of their fields:
adigitoleo marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
Loading