Skip to content

Commit 936e84f

Browse files
authored
add basic overview of when to use type declarations (#39812)
1 parent a3eda19 commit 936e84f

File tree

1 file changed

+21
-0
lines changed

1 file changed

+21
-0
lines changed

doc/src/manual/functions.md

+21
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,23 @@ are identical to the passed values. Modifications to mutable values (such as `Ar
6363
a function will be visible to the caller. This is the same behavior found in Scheme, most Lisps,
6464
Python, Ruby and Perl, among other dynamic languages.
6565

66+
## Argument-type declarations
67+
68+
You can declare the types of function arguments by appending `::TypeName` to the argument name, as usual for [Type Declarations](@ref) in Julia.
69+
For example, the following function computes [Fibonacci numbers](https://en.wikipedia.org/wiki/Fibonacci_number) recursively:
70+
```
71+
fib(n::Integer) = n ≤ 2 ? one(n) : fib(n-1) + fib(n-2)
72+
```
73+
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.
74+
75+
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:
76+
77+
* **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's_formula) to extend it to non-integer values.
78+
* **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`.
79+
* **Clarity:** Type declarations can serve as a form of documentation about the expected arguments.
80+
81+
However, it is a **common mistake to overly restrict the argument types**, which can unnecessarily limit the applicability of the function and prevent it from being re-used in circumstances you did not anticipate. For example, the `fib(n::Integer)` function above works equally well for `Int` arguments (machine integers) and `BigInt` arbitrary-precision integers (see [BigFloats and BigInts](@ref)), which is especially useful because Fibonacci numbers grow exponentially rapidly and will quickly overflow any fixed-precision type like `Int` (see [Overflow behavior](@ref)). If we had declared our function as `fib(n::Int)`, however, the application to `BigInt` would have been prevented for no reason. In general, you should use the most general applicable abstract types for arguments, and **when in doubt, omit the argument types**. You can always add argument-type specifications later if they become necessary, and you don't sacrifice performance or functionality by omitting them.
82+
6683
## The `return` Keyword
6784

6885
The value returned by a function is the value of the last expression evaluated, which, by default,
@@ -146,6 +163,10 @@ Int8
146163
This function will always return an `Int8` regardless of the types of `x` and `y`.
147164
See [Type Declarations](@ref) for more on return types.
148165

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

151172
For functions that do not need to return a value (functions used only for some side effects),

0 commit comments

Comments
 (0)