const CompoundTuple{T} = Tuple{Compound{T}, T}
struct ChemEquation{T<:Number}
tuples::Vector{CompoundTuple{T}}
end
ChemEquation(tuples::Vector{CompoundTuple{T}}) where T = ChemEquation{T}(tuples)
ChemEquation{T}(str::AbstractString) where T = ChemEquation(compoundtuples(str, T))
ChemEquation(str::AbstractString) = ChemEquation{Int}(str)
produces this error
LoadError: LoadError: MethodError: ChemEquation{Int64}(::String) is ambiguous. Candidates:
(::Type{ChemEquation{T}})(tuples) where T<:Number in ChemEquations at C:\Users\mirav\Documents\dev\julia\ChemEquations.jl\src\chemequation.jl:22
(::Type{ChemEquation{T}})(str::AbstractString) where T in ChemEquations at C:\Users\mirav\Documents\dev\julia\ChemEquations.jl\src\chemequation.jl:45
Possible fix, define
(::Type{ChemEquation{T}})(::AbstractString) where T<:Number
with stacktrace pointing to the last line of my code.
Note: removing ChemEquation(tuples::Vector{CompoundTuple{T}}) where T = ChemEquation{T}(tuples) doesn’t change anything.
The proposed fix actually works, but I don’t understand why, since ChemEquation.tuples is definitely typed. What confuses the multiple dispatch system in this case, and why does the proposed fix work?
If you want to make the life easier for people who want to help you, you’re better off providing a complete code to play with. You don’t define Compound{T} and even if I add the line
struct Compound{T} end
I don’t get any error with your code because you just define functions. I assume you get an error when calling one of the constructors. Which one? How do you call it?
Changing Compound in CompoundTuple{T} = Tuple{Compound{T}, T} to Complex for example still produces the same error, so I don’t think Compound is the issue. I thought adding that code would bloat the question.
As I noted, the error appears when calling ChemEquation{Int}(str), also unrelated to Compound.
Compound is just another struct defined in similar manner, but it has two fields, so errors like this one don’t appear.
const ElementTuple{T} = Tuple{String, T}
struct Compound{T<:Number}
tuples::Vector{ElementTuple{T}}
charge::T
end
Compound(tuples::Vector{ElementTuple{T}}, charge::T) where T = Compound{T}(tuples, charge)
Compound{T}(str::AbstractString) where T = Compound(elementtuples(str, T), charge(str, T))
Compound(str::AbstractString) = Compound{Int}(str)
The source code is in https://github.com/zdroid/ChemEquations.jl, but it has hundreds of lines. I don’t think it contains any useful information, since I identified the error to be something else.
The problem here is that
struct ChemEquation{T<:Number}
tuples::Vector{CompoundTuple{T}}
end
produces a constructor without definitely typed tuples. One fix for that is this:
struct ChemEquation{T<:Number}
tuples::Vector{CompoundTuple{T}}
ChemEquation{T}(tuples::Vector{CompoundTuple{T}}) where T = new{T}(tuples)
end
But the explanation in Parametric constructors docs is unclear, so I’m asking here for that. Sorry if I wasn’t clear enough.
Please post a complete question with complete, minimal working code and example usage which demonstrates current input and output, and desired output – in other words, follow the advice that Mosè already posted by following the PSA document.
If you do that you are likely to get good and useful help. (And if you don’t, you aren’t.)
For this one, T <: Number matches the Int parameter in your call; the argument matches too (since it’s Any here).
For this one, the type of the argument matches the string type in the argument of your call and the parameter T matches too (since it’s unconstrained here).
So both match, and one matches narrowly with the type parameter and the other matches narrowly with the argument type; neither method is more specific than the other. So it’s ambiguous.
In which way the previous post doesn’t satisfy those conditions? Nevertheless, I’ve made a simplified example which produces the same error:
julia> struct Hey{T<:Number}
a::Vector{T}
end
julia> Hey{T}(str::AbstractString) where T = Hey{T}(T.(collect(str)))
julia> Hey(str::AbstractString) = Hey{Int}(str)
Hey
julia> Hey("123")
ERROR: MethodError: Hey{Int64}(::String) is ambiguous. Candidates:
(::Type{Hey{T}})(a) where T<:Number in Main at REPL[1]:2
(::Type{Hey{T}})(str::AbstractString) where T in Main at REPL[2]:1
Possible fix, define
(::Type{Hey{T}})(::AbstractString) where T<:Number
I understood that, but I’m asking is this desired behavior? It seems illogical, for a definitely typed struct field to accept any type, instead of any type under parametric conditions (i.e. T<:Number).
Ah, I hadn’t realized that was your question. I’m not sure; I tried
Hey{T}(str::AbstractString) where T = Hey{Int}(str)
to see if you could use this behavior to do a fallback method or something like that, but it errors (ERROR: TypeError: in Hey, in T, expected T<:Number, got Type{String}).