Диспетчерские функции в Джулия версии v0.5+
Согласно списку изменений для Джулии 0.5,
Каждая функция и замыкание теперь имеют свой собственный тип.Означает ли это, что теперь можно предоставить более подробную информацию функции более высокого порядка, например
foo(bar :: Function{Float64}) = ..., в отличие от pre-0.5, где Тип bar не может быть более конкретным, чем Function?
Если да, то как это правильно сделать? Если нет, то каков фактический импорт этого изменения, помимо того, что компилятор может лучше оптимизировать сгенерированный код? ТИА.
1 ответ:
На самом деле нет. Я понимаю, к чему вы клоните, и мне это нравится, но это невозможно. (Конечно, не сейчас, а возможно, и никогда. Может, однажды, используя черты характера.)
Давайте рассмотрим пример:
fooиbarjulia> foo(x::String) = println(x) foo (generic function with 1 method) julia> foo(x::Int64) = println(x+1) foo (generic function with 2 methods) julia> bar(x...) = println(x) bar (generic function with 1 method)Какова иерархия типов для
foo?Таким образом, мы видим, что тип функцииjulia> typeof(foo) #foo julia> supertype(typeof(foo)) Function julia> supertype(supertype(typeof(foo))) Anyfooявляется#foo, который является подтипомFunction. Обратите внимание, что#означает, что это сгенерированное имя, вы не можете поместить хэш в имена, когда просто пишете код, но Джулия компилятор (используя термин свободно) может.Почему его супер-супертип не является более конкретным, чем просто функция? Что бы это могло быть?
Итак, давайте продолжим наш пример и посмотрим, что мы можем сделать:Function{Int64}илиFunction{String}? функции в julia, не имеют сигнатур типа, методы делают. Функция-это просто имя для множественной отправки, метод-это то, что на самом деле отправляется. Грубо говоря, имя функции говорит, в какой таблице я должен искать, а типы аргументов (т. е. это сигнатура типа) являются ключом для поиска, в эта таблица. Метод сам по себе является тем, что возвращается, используя этот ключ.Таким образом, мы успешно ограничилиjulia> dothing(f::typeof(foo)) = f(rand([randstring(), rand(Int64)])) dothing (generic function with 1 method) julia> dothing(foo) 3139374763834167054 julia> dothing(foo) Ed2kNGrd julia> dothing(bar) ERROR: MethodError: no method matching dothing(::#bar) Closest candidates are: dothing(::#foo) at REPL[11]:1dothing, чтобы только принять#fooв качестве аргумента. Смотрите, он выдает ошибку, когда вы даете ему#bar. Это не очень полезно, Так как функцияfooявляется единственной вещью типа#foo.Мы могли бы использовать
Unionхотя:julia> dootherthing(f::Union{typeof(foo),typeof(bar)}) = f(rand([randstring(), rand(Int64)])) dootherthing (generic function with 1 method) julia> dootherthing(foo) 9107791406050657562 julia> dootherthing(foo) SmB2Xmw8 julia> dootherthing(bar) ("1IpZIMnx",) julia> dootherthing(bar) (-6356894350805213697,) julia> dootherthing(str) ERROR: UndefVarError: str not defined julia> dootherthing(string) ERROR: MethodError: no method matching dootherthing(::Base.#string) Closest candidates are: dootherthing(::Union{#bar,#foo}) at REPL[19]:1Это имеет ограниченное применение, как белый список.
dootherthingпринимает a#fooили a#bar. Либо функция завод.