Порядок определения метода дает разные результаты

#function #methods #julia

#функция #методы #юлия

Вопрос:

Почему порядок определения метода отличается в этом случае? На мой взгляд, это не имеет особого смысла.

 julia> f() = 1
f (generic function with 1 method)

julia> f(;arg) = 1
f (generic function with 1 method)

julia> f()
ERROR: UndefKeywordError: keyword argument arg not assigned
Stacktrace:
 [1] f() at ./REPL[2]:1
 [2] top-level scope at REPL[3]:1

julia> f() = 1
f (generic function with 1 method)

julia> f()
1

julia> f(arg=1)
1
 

Комментарии:

1. Вы сталкиваетесь с github.com/JuliaLang/julia/issues/9498 . Ожидаемое поведение здесь будет заключаться в том, что одно полностью перезаписывает другое, поэтому обычно это не должно происходить при неинтерактивном использовании

2. также смотрите docs.julialang.org/en/v1/devdocs/functions/#Keyword-arguments

3. Симеон, тебе, вероятно, следует добавить свой комментарий к ответу, поскольку это ответ. Это ошибка / особенность, зависящая от вашей перспективы, и может быть исправлена / изменена в версии 2.0, но вряд ли изменится в версии 1.x, потому что это потенциально может привести к поломке большого количества кода.

4. Я согласен, это ответ.

Ответ №1:

Порядок определения метода дает разные результаты из-за того, как функция с аргументами ключевого слова вписывается в механизм отправки метода в Julia 1.x.

Как указано в комментариях выше, короткий ответ: потому что второе определение полностью перезаписывает другое.

Но я думаю, что это не совсем точно, давайте посмотрим.

Случай 1: с порядком:

 julia> f() = 2
f (generic function with 1 method)

julia> f(;arg) = 1
f (generic function with 1 method)

julia> f()
ERROR: UndefKeywordError: keyword argument arg not assigned
 

Определенная пользователем функция f() переопределяется.

Случай 2: изменение порядка оба метода видны:

 julia> f(;arg) = 1
f (generic function with 1 method)

julia> f() = 2
f (generic function with 1 method)

julia> f()
2

julia> f(arg=3)
1
 

Когда f(;arg) значение опускается, компилятор создает метод f() без аргументов ключевого слова
для обработки случая, когда аргументы ключевого слова не передаются.

Это приводит к двум разным результатам:

  • Случай 1: созданный метод f() переопределяет определенный пользователем f() .
  • Случай 2: f() определенный пользователем переопределяет созданный метод f() , но f(;args) остается видимым.

Обратите внимание, что в обоих случаях кажется, что в качестве конечного результата мы получаем функцию f с 1 методом, но на самом деле во втором случае у нас фактически есть 2 функции с 1 методом каждая, одна из которых управляет определяемым пользователем f() , а другая управляет версией аргументов ключевого f(;arg) слова.

Полная информация о том, как опустить определение метода аргументов ключевого слова, подробно изложена в документах