Разъяснение функции подписи и диспетчерского поведения в юлии - PullRequest
8 голосов
/ 14 января 2020

Я пробовал кое-что в REPL Джулии (1.2) и сосредоточился на том, чего не понимаю в диспетчеризации.


Сначала я попробовал эту вещь, которая работает так, как надо Я ожидал:

f(a::T) where {T <: Int} = "Test"

  • Вызов f (3) работает с Int <: Int == true

  • Вызов f (" Привет ") приводит к ошибке" MethodError: нет соответствия метода ", поскольку String <: Int == false


Затем я попробовал этот метод, и я не понимаю, почему его вызов работает в некоторых случаях:

f(a::T, b::U) where {T, U <: T} = "Another Test"

  • Вызов f (3, 3) работает (как я и ожидал)

  • НО f (3, «Hello») также работает и не выдает «MethodError: нет соответствия метода» ???

Я думал, что (поскольку T становится Int, а U - строкой) String <: Int == false ???


Я предполагаю, что здесь упускаю что-то довольно простое но я не могу найти это ... Так что это мой вопрос, почему f (3, "Hello") работает ???


Более того, я попробовал этот фрагмент кода (я пытался воссоздать сигнатуру второго метода), и он корректно завершился ошибкой, как я и ожидал:

Test = Tuple{T, U} where {T, U <: T}

Test{Int, String} (это терпит неудачу, как я и ожидал, с "TypeError: in Type, в U, ожидаемый U <: Int64, получил Type {String}") </p>

Ответы [ 2 ]

4 голосов
/ 14 января 2020

Здесь происходит то, что T может быть типом данных, а U может быть любым супертипом строки. Эти условия выполнены. То, что сбивало вас с толку строкой, не являющейся подтипом типа int, - это красная сельдь, поскольку ни один конкретный тип не является подтипом любого другого.

3 голосов
/ 14 января 2020

Хорошо, благодаря laborg кажется, я теперь понимаю, что происходит. Если мы возьмем этот метод:

f(a::T, b::U) where {T, U <: T} = "Another Test"

  • 'T' - это "UnionAll" или "Повторный союз" всех возможных типов 'a'.
  • «U» - это «UnionAll» или «Повторный союз» всех возможных типов «b», которые являются подтипами «T»

  • То, что я неправильно понял, было тот факт, что если (пример) a :: Int, то T может принимать родительский абстрактный тип typeof (a). Поскольку Int <: Any, то T = Any является допустимым решением для отправки. </p>

  • То же самое для U = Any, так как String <: Any. </li>

Итак, теперь мы есть U <: T, который разрешается в Any <: Any == true, и метод вызывается! </p>

Надеюсь, я его получу :)

...