# Convert() vs constructors

**URL:** <https://discourse.julialang.org/t/convert-vs-constructors/4159>\
**Category:** General Usage\
**Tags:** convert, constructors\
**Created:** [June 8, 2017, 2:26am UTC](https://discourse.julialang.org/t/convert-vs-constructors/4159 "2017-06-08T02:26:54Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)\
**Post date:** [June 8, 2017, 2:26am UTC](https://discourse.julialang.org/t/convert-vs-constructors/4159/1 "2017-06-08T02:26:54Z")

</div>

Could someone please explain how to best define a concrete type conversion tree? Also what is the role of `convert` and `promote_type` in converting from one concrete type to another?

Thanks.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [June 8, 2017, 2:47am UTC](https://discourse.julialang.org/t/convert-vs-constructors/4159/2 "2017-06-08T02:47:01Z")

</div>

`convert` happens automatically on assignment so don’t define a `convert` that will cause surprise if it gets called. Constructors are always explicit.  
`promote_type` has no direct relation with convertion (i.e. defining it does not affect convertions at all). It’s result is expected to be used to call `convert` on by the caller, this includes lots of arithmetic functions.

---

<div class="post-metadata">

**Author:** ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)\
**Post date:** [June 8, 2017, 2:51am UTC](https://discourse.julialang.org/t/convert-vs-constructors/4159/3 "2017-06-08T02:51:28Z")

</div>

So when I write promote(1,2.), is there a convert(::Type{Float64}, 1) being called after realizing that Float64 is the result of promote\_type(typeof(1), typeof(2.))? So does conversion happen when promoting?

---

<div class="post-metadata">

**Author:** ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)\
**Post date:** [June 8, 2017, 2:54am UTC](https://discourse.julialang.org/t/convert-vs-constructors/4159/4 "2017-06-08T02:54:41Z")

</div>

I think I found my answer in Julia Base

```julia
function promote(x, y, z)
    @_inline_meta
    (convert(promote_typeof(x,y,z), x),
     convert(promote_typeof(x,y,z), y),
     convert(promote_typeof(x,y,z), z))
end

```

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [June 8, 2017, 3:02am UTC](https://discourse.julialang.org/t/convert-vs-constructors/4159/5 "2017-06-08T03:02:32Z")

</div>

> [@mohamed82008](#):
>
> So when I write promote(1,2.), is there a convert(::Type{Float64}, 1) being called after realizing that Float64 is the result of promote\_type(typeof(1), typeof(2.))?

Correct.

> [@mohamed82008](#):
>
> So does conversion happen when promoting?

Yes. Promotion generally uses convert after figuring out the type (at least that’s what the user of the promotion system is supposed to do). It does not affect convertion. (well, unless you somehow defined a convert method that uses promotion explicitly…)

---

<div class="post-metadata">

**Author:** ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)\
**Post date:** [June 8, 2017, 3:05am UTC](https://discourse.julialang.org/t/convert-vs-constructors/4159/6 "2017-06-08T03:05:46Z")

</div>

The gist is I have to use constructors. I was hoping that convert could replace it to be able to use a type parameter and combine a number of constructors with a certain pattern in their definitions. But then I guess that’s a good reason to start metaprogramming. Thanks anyways!

---

<div class="post-metadata">

**Author:** ![gdkrmr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdkrmr/32/2791_2.png) [@gdkrmr](https://discourse.julialang.org/u/gdkrmr)\
**Post date:** [June 8, 2017, 11:16am UTC](https://discourse.julialang.org/t/convert-vs-constructors/4159/7 "2017-06-08T11:16:56Z")

</div>

is there a difference between calling `T(x)` and `convert(T, x)`? I tend to use the former, because it looks nicer, especially if I want to convert arrays, then `T.(x)` is much shorter and more legible than `convert(Array{T}, x)`.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [June 8, 2017, 12:44pm UTC](https://discourse.julialang.org/t/convert-vs-constructors/4159/8 "2017-06-08T12:44:44Z")

</div>

> [@gdkrmr](#):
>
> is there a difference between calling T(x) and convert(T, x)

Yes, they are two different functions. And I’ve already explained the difference [Convert() vs constructors - #2 by yuyichao](https://discourse.julialang.org/t/convert-vs-constructors/4159/2)

---

<div class="post-metadata">

**Author:** ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)\
**Post date:** [June 8, 2017, 1:42pm UTC](https://discourse.julialang.org/t/convert-vs-constructors/4159/9 "2017-06-08T13:42:10Z")

</div>

However,

```julia
Float64(1)

```

does call `convert(Float64, 1)`, doesn’t it?

```julia

```

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [June 8, 2017, 1:52pm UTC](https://discourse.julialang.org/t/convert-vs-constructors/4159/10 "2017-06-08T13:52:40Z")

</div>

Yes. So?

---

<div class="post-metadata">

**Author:** ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)\
**Post date:** [June 8, 2017, 2:04pm UTC](https://discourse.julialang.org/t/convert-vs-constructors/4159/11 "2017-06-08T14:04:41Z")

</div>

So there is no difference (in terms of code generated) between calling `Float64(1)` and `convert(Float64, 1)`, which I suspect was the origin of this particular question.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [June 8, 2017, 2:29pm UTC](https://discourse.julialang.org/t/convert-vs-constructors/4159/12 "2017-06-08T14:29:32Z")

</div>

If the type didn’t define any constructor sure. The question didn’t specify a specific type so yes there’s difference. The two are not magically linked together.

---

<div class="post-metadata">

**Author:** ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)\
**Post date:** [June 8, 2017, 5:29pm UTC](https://discourse.julialang.org/t/convert-vs-constructors/4159/13 "2017-06-08T17:29:14Z")

</div>

So are there (other) cases with custom made types where the default inner constructor automatically calls convert like the Float64(1) case? I guess another way to ask this question is: is it explicitly defined that Float64(a::Int) = convert(Float64, a), and then convert is defined separately?

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [June 8, 2017, 5:57pm UTC](https://discourse.julialang.org/t/convert-vs-constructors/4159/14 "2017-06-08T17:57:04Z")

</div>

> [@mohamed82008](#):
>
> is it explicitly defined that `Float64(a::Int) = convert(Float64, a)`, and then `convert` is defined separately?

For any type `T`, the default meaning of `T(x)` is `convert(T, x)`, unless you have explicitly defined a constructor function. See [https://docs.julialang.org/en/latest/manual/constructors/#constructors-and-conversion-1](https://docs.julialang.org/en/latest/manual/constructors/#constructors-and-conversion-1)

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [June 8, 2017, 5:58pm UTC](https://discourse.julialang.org/t/convert-vs-constructors/4159/15 "2017-06-08T17:58:20Z")

</div>

Though since it is not the default inner constructor it’ll be overwrite by the inner constructor.

---

<div class="post-metadata">

**Author:** ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)\
**Post date:** [June 8, 2017, 6:16pm UTC](https://discourse.julialang.org/t/convert-vs-constructors/4159/16 "2017-06-08T18:16:48Z")

</div>

So unless I define an explicit inner constructor, the default convert-based one will be used?

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [June 8, 2017, 6:57pm UTC](https://discourse.julialang.org/t/convert-vs-constructors/4159/17 "2017-06-08T18:57:32Z")

</div>

No. Unless a single element inner/outer constructor is defined explicitly or implicitly the fallback one will call `convert`.

---

<div class="post-metadata">

**Author:** ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)\
**Post date:** [June 8, 2017, 7:13pm UTC](https://discourse.julialang.org/t/convert-vs-constructors/4159/18 "2017-06-08T19:13:18Z")

</div>

So if the type has only one field, and its inner constructor is not explicitly defined, it is still defined implicitly and it overwrites the default meaning of T(x), i.e. convert(T, x)?

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [June 8, 2017, 7:38pm UTC](https://discourse.julialang.org/t/convert-vs-constructors/4159/19 "2017-06-08T19:38:06Z")

</div>

Correct

---

<div class="post-metadata">

**Author:** ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)\
**Post date:** [June 8, 2017, 7:43pm UTC](https://discourse.julialang.org/t/convert-vs-constructors/4159/20 "2017-06-08T19:43:47Z")

</div>

And just to recap, convert functions are not defined by default under any circumstance. They have to be explicitly defined. A special of case is when the type T has one field only, yet convert(T, a) does not call T(a), sanity check:

```julia
julia> type T
           a
       end

julia> convert(T, 1)
ERROR: MethodError: Cannot `convert` an object of type Int64 to an object of type T
This may have arisen from a call to the constructor T(...), since type constructors fall back to convert methods.

```

[Next page](https://discourse.julialang.org/t/convert-vs-constructors/4159.md?page=2)
