Это работает:

type Dude
    say_something::Function
    # constructor
    function Dude()
        dude = new()

        dude.say_something = function(what::AbstractString)
            print(what)
        end
        return dude
    end
end

dude = Dude()
dude.say_something("hi")

Но мне нужен аргумент по умолчанию для what. Однако этот код:

type Dude
    say_something::Function
    # constructor
    function Dude()
        dude = new()

        dude.say_something = function(what::AbstractString="hi")
            print(what)
        end
        return dude
    end
end

dude = Dude()
dude.say_something("hello")

Дает ошибку:

ERROR: LoadError: syntax: expected "(" in function definition in include at ./boot.jl:261 in include_from_node1 at ./loading.jl:304 in process_options at ./client.jl:280 in _start at ./client.jl:378

Допускаются ли аргументы по умолчанию или аргументы ключевого слова в атрибуте Function типа?

3
Cokes 17 Мар 2016 в 21:52

2 ответа

Лучший ответ

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

julia> function(what=1); what; end
ERROR: syntax: expected "(" in function definition

julia> (what=1) -> what
ERROR: syntax: "what=1" is not a valid function argument name

Это ограничение связано с тем, что в Julia 0.4 анонимные функции не являются универсальными - вы не можете добавить несколько методов к анонимной функции. Значения по умолчанию - это просто сокращение для определения нескольких методов с различным количеством аргументов. В версии 0.5 все функции являются универсальными, так что это должно работать там после его выпуска.

На данный момент вы можете обойти это, используя именованную функцию или просто разрешив любое количество аргументов и заполнив значение по умолчанию в себе. Но обратите внимание, что хранение функций-членов в таких объектах, как этот, часто является запахом кода, который вы пытаетесь внедрить в Julia, используя Python-подобные методы объектно-ориентированного программирования. Функции Джулии обычно определяются внешне из типов и используют множественную отправку . Это изменение стиля, но я настоятельно рекомендую принять его.

dude.say_something = function(whats::AbstractString...)
    length(whats) < 2 || error("too many arguments")
    what = isempty(whats) ? "hi" : whats[1]
    print(what)
end
5
Matt B. 17 Мар 2016 в 19:49

Следующее работает, по крайней мере, на v0.5:

julia> type Dude
           say_something::Function
           # constructor
           Dude() = new((what::AbstractString="hi")->(print(what)))
       end

julia> y = Dude()
Dude(#1)

julia> y.say_something()
hi

Вы также можете (в v0.4.3) сделать следующее:

julia> type Dude
           say_something::Function
           # constructor
           function Dude()
               function ss(what::AbstractString="hi")
                   print(what)
               end
               new(ss)
           end
       end

julia> y = Dude()
Dude(ss)
julia> y.say_something()
hi

Я думаю, что проблема (в v0.4.x) заключается в синтаксисе анонимной функции, который был исправлен в v0.5.

2
Scott Jones 17 Мар 2016 в 20:03