Skip to content

Commit b6b6821

Browse files
authored
add more on the difference between convert and construct (#25470)
also remove deprecated method from an example [ci skip]
1 parent fc3170f commit b6b6821

File tree

1 file changed

+32
-6
lines changed

1 file changed

+32
-6
lines changed

doc/src/manual/conversion-and-promotion.md

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -119,14 +119,40 @@ its methods are restricted to cases that are considered "safe" or "unsurprising"
119119
It is also usually lossless; converting a value to a different type and back again
120120
should result in the exact same value.
121121

122-
Notice that some constructors don't implement the concept of "conversion".
123-
For example, `Vector{Int}(5)` constructs a 5-element vector, which is not really a
124-
"conversion" from an integer to a vector.
122+
There are four general kinds of cases where constructors differ from `convert`:
125123

126-
Finally, `convert(T, x)` is expected to return the original `x` if `x` is already of type `T`.
124+
#### Constructors for types unrelated to their arguments
125+
126+
Some constructors don't implement the concept of "conversion".
127+
For example, `Timer(2)` creates a 2-second timer, which is not really a
128+
"conversion" from an integer to a timer.
129+
130+
#### Mutable collections
131+
132+
`convert(T, x)` is expected to return the original `x` if `x` is already of type `T`.
127133
In contrast, if `T` is a mutable collection type then `T(x)` should always make a new
128134
collection (copying elements from `x`).
129135

136+
#### Wrapper types
137+
138+
For some types which "wrap" other values, the constructor may wrap its argument inside
139+
a new object even if it is already of the requested type.
140+
For example `Some(x)` wraps `x` to indicate that a value is present (in a context
141+
where the result might be a `Some` or `nothing`).
142+
However, `x` itself might be the object `Some(y)`, in which case the result is
143+
`Some(Some(y))`, with two levels of wrapping.
144+
`convert(Some, x)`, on the other hand, would just return `x` since it is already
145+
a `Some`.
146+
147+
#### Constructors that don't return instances of their own type
148+
149+
In *very rare* cases it might make sense for the constructor `T(x)` to return
150+
an object not of type `T`.
151+
This could happen if a wrapper type is its own inverse (e.g. `Flip(Flip(x)) === x`),
152+
or to support an old calling syntax for backwards compatibility when a library is
153+
restructured.
154+
But `convert(T, x)` should always return a value of type `T`.
155+
130156
### Defining New Conversions
131157

132158
When defining a new type, initially all ways of creating it should be defined as
@@ -146,8 +172,8 @@ The type of the first argument of this method is a [singleton type](@ref man-sin
146172
when the first argument is the type value `MyType`. Notice the syntax used for the first
147173
argument: the argument name is omitted prior to the `::` symbol, and only the type is given.
148174
This is the syntax in Julia for a function argument whose type is specified but whose value
149-
is never used in the function body. In this example, since the type is a singleton, there
150-
would never be any reason to use its value within the body.
175+
does not need to be referenced by name. In this example, since the type is a singleton, we
176+
already know its value without referring to an argument name.
151177

152178
All instances of some abstract types are by default considered "sufficiently similar"
153179
that a universal `convert` definition is provided in Julia Base.

0 commit comments

Comments
 (0)