# Custom conversion routines

**URL:** <https://discourse.julialang.org/t/custom-conversion-routines/3439>\
**Category:** New to Julia\
**Created:** [April 30, 2017, 6:52am UTC](https://discourse.julialang.org/t/custom-conversion-routines/3439 "2017-04-30T06:52:55Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![purplishrock](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/purplishrock/32/13451_2.png) [@purplishrock](https://discourse.julialang.org/u/purplishrock)\
**Post date:** [April 30, 2017, 6:52am UTC](https://discourse.julialang.org/t/custom-conversion-routines/3439/1 "2017-04-30T06:52:55Z")

</div>

```julia
module A

import Base: convert

export Foo

type Foo
    a::Float64
    b::Float64
end

function convert(::Type{Foo}, a::Tuple{Float64,Float64})
    Foo(a[1], a[2])
end
end

module B
using A

export Bar

type Bar
    x1 :: Foo
    x2 :: Foo
    function Bar(a::Foo, b::Foo) new(a,b) end
end
end

```

The test code in a separated file

```julia
using B

b = Bar((1.0,2.0), (1.0,2.0))
println(b)

```

ERROR: LoadError: MethodError: no method matching B.Bar(::Tuple{Float64,Float64}, ::Tuple{Float64,Float64})  
Closest candidates are:  
B.Bar{T}(::Any) at sysimg.jl:53

When I remove the internal constructor everything works as expected.

I was hoping somebody could explain why that is.

I can fix it by creating an external constructor which matches on Tuples.

Thank you.

---

<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:** [April 30, 2017, 1:49pm UTC](https://discourse.julialang.org/t/custom-conversion-routines/3439/2 "2017-04-30T13:49:39Z")

</div>

The auto conversion is done only in `new` not for function dispatch. So basically if you declared a type

```julia
type Bar
   x::Foo
end

```

You can pass a `Tuple{Float64,Float64}` to it’s default constructor or `new` used in your own inner constructor and the conversion will be done automatically. However, if you have a function `foo(::Foo)` it’ll not be able to accept a `Tuple{Float64,Float64}` object, inner constructor included. If you want to accept a wider range of types and do conversion, then just specify that in the signature (i.e. remove the type constraint on it).

P.S. Auto conversion is also done on assignment to typed slot. Mentioning this mainly for completion and not directly related to this issue.

---

<div class="post-metadata">

**Author:** ![purplishrock](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/purplishrock/32/13451_2.png) [@purplishrock](https://discourse.julialang.org/u/purplishrock)\
**Post date:** [April 30, 2017, 4:12pm UTC](https://discourse.julialang.org/t/custom-conversion-routines/3439/3 "2017-04-30T16:12:59Z")

</div>

Thanks for you help.

I changed

```julia
function Bar(a::Foo, b::Foo) new(a,b) end

```

to

```julia
function Bar(a, b) new(a,b) end

```

and that works.

I guess I’m surprised that the type signature breaks it.

Why doesn’t the compiler look at the fact that it needs a Foo, got a tuple, and goes off and looks for a conversion/promotion ? Or maybe the problem is I need promote instead of convert ?

---

<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:** [April 30, 2017, 4:45pm UTC](https://discourse.julialang.org/t/custom-conversion-routines/3439/4 "2017-04-30T16:45:55Z")

</div>

> [@purplishrock](#):
>
> Why doesn’t the compiler look at the fact that it needs a Foo, got a tuple, and goes off and looks for a conversion/promotion ?

Because that’s not how dispatch works. Given the number of convertion methods defined, it’ll be extremely ambiguous in general which one should actually be called. (e.g. If you also have a convertion from `NTuple{2,Float64}` to `Bar` and have another method `Bar(::Bar, ::Bar)`, which one do you want to call?)

It’s probably not impossible to come up with a set of rules to determine what is ambiguous and what’s not but given the “non-locality” of the information (i.e. it’s stored both in the method table of the method you are calling as well as the whole set of convertion rules, possibly chained) it’ll likely be very hard to predict and will certainly be extremely hard to implement dynamically with any reasonable performance.
