Возникли проблемы с правилами конвертации Джулии - PullRequest
2 голосов
/ 01 октября 2019

В руководстве по документации Julia говорится следующее [1]:

Когда вызывается функция convert?

В следующих языках создаются вызовы функции convert:

  • Присвоение массиву преобразуется в тип элемента массива.

[1] https://docs.julialang.org/en/v1/manual/conversion-and-promotion/#When-is-convert-called?-1

Я определил следующий код:

julia> abstract type Element end

julia> abstract type Inline <: Element end

julia> struct Str <: Inline
           content::String
       end

julia> convert(::Type{Str}, e::String) = Str(e)
convert (generic function with 1 method)

julia> convert(::Type{Element}, e::String) = convert(Str, e)
convert (generic function with 2 methods)

У меня convert определено для типа Джулия String. А преобразование в Element и преобразование в Str из экземпляра типа String работает, как и ожидалось. Тем не менее, следующее не удается:

julia> convert(Str, "hi")
Str("hi")

julia> convert(Element, "hi")
Str("hi")

julia> arr = Element[]
0-element Array{Element,1}

julia> push!(arr, "hi")
ERROR: MethodError: Cannot `convert` an object of type String to an object of type Element
Closest candidates are:
  convert(::Type{T}, ::T) where T at essentials.jl:168
Stacktrace:
 [1] push!(::Array{Element,1}, ::String) at ./array.jl:866
 [2] top-level scope at REPL[25]:1

julia> arr = Str[]
0-element Array{Str,1}

julia> push!(arr, "hi")
ERROR: MethodError: Cannot `convert` an object of type String to an object of type Str
Closest candidates are:
  convert(::Type{T}, ::T) where T at essentials.jl:168
  Str(::String) at REPL[19]:2
  Str(::Any) at REPL[19]:2
Stacktrace:
 [1] push!(::Array{Str,1}, ::String) at ./array.jl:866
 [2] top-level scope at REPL[27]:1

julia>

Может кто-нибудь объяснить, почему вышеперечисленное не удается? И как, если это возможно, предотвратить его сбой?

1 Ответ

3 голосов
/ 01 октября 2019

основной подсказкой вашего кода была эта строка: convert (универсальная функция с 1 методом), которая означает, что функция convert имеет только одно определение (ваше определение), поэтому что-то было не так. когда Джулия использует convert, на самом деле она вызывает Base.convert. Итак, перегрузка правильного метода:

Base.convert(::Type{Str}, e::String) = Str(e)
Base.convert(::Type{Element}, e::String) = convert(Str, e)

с вашим кодом работала как положено. Короче говоря, ваш код был прав, вы просто перегружали неправильное преобразование (всегда добавляйте Base.method при работе с основными функциями Julia)

...