# @match type?

I’m utterly confused why the following code doesn’t produce identical results (i.e. selecting on type with @match (Match.jl) or if…elseif…end). With @match (get_fmt1) regardless of the actual type, always an integer type is matched…? More insight much appreciated.

``````using Match

function get_fmt1(a)
T = typeof(a)
S = supertype(T)
println("Ta, Sa = \$T, \$S")
fmt(a) = @match S begin
# Signed => "d"
Integer || Signed || Unsigned || Bool || BigInt => "d"
AbstractFloat                           => "f"
AbstractString                          => "s"
_,Any                                   => "s"
end
fmt(a)
end

function get_fmt2(a)
T = typeof(a)
S = supertype(T)
# println("Ta, Sa = \$T, \$S")
if S in [Integer Signed Unsigned Bool BigInt ] return "d"
elseif S == AbstractFloat   return "f"
elseif S == AbstractString  return "s"
else return "o"
end
end

trials = [ 1 1.0 "Foo" Inf ]

println("FMT 1")
for a in  trials
Ta = typeof(a)
Sa = supertype(Ta)
println("a, Ta, Sa = \$a, \$Ta, \$Sa")
println("fmt a = ", get_fmt1(a))
end

println("FMT 2")
for a in  trials
Ta = typeof(a)
Sa = supertype(Ta)
println("a, Ta, Sa = \$a, \$Ta, \$Sa")
println("fmt a = ", get_fmt2(a))
end
``````

It seems that `@match` handles types not as values, and expressions like

``````julia>  macroexpand(:(@match S begin
AbstractFloat => "f"
Integer  => "d"
AbstractString => "s"
_ => "s"
end))
quote  # REPL[53], line 2:
"f"
end
``````

always return the first match. You may want open an issue on Github for the library, to see if this is intended or a bug.

In the meantime, you can work around the problem with

``````function type_letter(S)
@match S begin
_::Type{Integer} || _::Type{Signed} || _::Type{Unsigned} ||
_::Type{Bool} || _::Type{BigInt} => "d"
_::Type{AbstractFloat} => "f"
_::Type{AbstractString} => "s"
_ => "s"
end
end
``````

which works as

``````julia>  [type_letter(supertype(typeof(x))) for x in [1 1.0 "Foo" Inf]]
1×4 Array{String,2}:
"d"  "f"  "s"  "f"
``````

Finally, while your actual use case may differ from the MWE, I am not sure that pattern matching is the best way to approach this.

@Tamas_Papp The “Julia proper way” would be to dispatch `type_letter(S)` on `typeof(S)` (…you notice I’m coming from the Python world…), the match behavior still seems problematic to me – I have posted an issue to the Match.jl github repos.

I think that `type_letter` dispatches on a type, see the example below it. Depending on how you plan to extend this, consider something like

``````type_letter{T <: Integer}(::Type{T}) = "d"
type_letter(::Type{AbstractFloat}) = "f"
type_letter(::Type{AbstractString}) = "s"
type_letter(_) = "s"            # fallback

get_fmt{T}(a::T) = type_letter(supertype(T))
``````

Also, depending on your use case, consider

``````get_fmt{T <: AbstractFloat}(x::T) = "f"
get_fmt{T <: Integer}(x::T) = "d"
get_fmt{T <: AbstractString}(x::T) = "s"
get_fmt(x) = "s"                # fallback

get_fmt.([1 1.0 "Foo" Inf])
``````

@Tamas_Papp The true julian/dispatch (very un-pythonic/test) way. Thanks.