2016-11-05 5 views
1

В Ruby, я могу потребовать аргумент как (1) появляются, и (2) имеют имя параметра:Может ли быть указан параметр Julia, который должен присутствовать?

>> def f(x:) 
>> x + 1 
>> end 

>> f() 
ArgumentError: missing keyword: x 
>> f(2) 
ArgumentError: wrong number of arguments (given 1, expected 0) 
>> f(x:7) 
=> 8 

То есть, я есть передать аргумент, и я есть, чтобы указать имя связанного параметра.

я могу сделать то же самое в Python:

>>> def f(*, x): 
... return x + 1 
... 
>>> f() 
TypeError: f() missing 1 required keyword-only argument: 'x' 
>>> f(3) 
TypeError: f() takes 0 positional arguments but 1 was given 
>>> f(x=7) 
8 

И для хорошей меры, даже Swift может сделать это:

1> func f(x: Int) -> Int {return x + 1} 
2> f() 
error: missing argument for parameter 'x' in call 
2> f(3) 
error: missing argument label 'x:' in call 
2> f(x:7) 
$R0: Int = 8 

Но я не могу понять, как сделать это в Julia. Кажется, что аргументы ключевого слова, поскольку они вызываются, должны принимать параметры по умолчанию. Это правильно, или есть способ имитировать примеры Ruby и Python выше?

ответ

5

Это правильно. В julia у вас не могут быть требуемые аргументы ключевых слов. Аргументы ключевого слова - это особый тип необязательного аргумента - тот, который задается по имени, а не положением.

(В связи с этим, вы не можете установить, не ключевое слово аргумент по имени - который вы можете сделать в Python и C#.)

Вы можете, как это было предложено @amrods обеспечить это во время выполнения.

Я хотел бы сделать это с

function f(; x = nothing) 
    x===nothing && error("x not set.") 
    #... 
end 

что проверка будет оптимизированными, если они типа x известно (вывод) на абонента, в типе компиляции.

, но он фактически не будет применяться до выполнения. Вы также можете использовать @Fengyang very elegant way to achieve the same.

Возможно, вы можете применить это во время компиляции, заменив вашу функцию сгенерированной функцией. Но это ужасный взлом.

+1

Вы имеете в виду 'ничего ' – amrods

+0

@amrods спасибо, исправлено. –

+0

Конечно, как Python, так и Ruby также обеспечивают правильность во время выполнения, как динамические языки. –

2

Будет ли это работать?

function f(; x = nothing) 
    x + 1 
end 

По существу вы предоставляете начальное значение по умолчанию.

Изменить: установить значение по умолчанию nothing.

6

Это возможно так же, как Ruby или Python. Фактически, это может быть так же просто, как

julia> f(x, y; z=error()) = 1 
f (generic function with 1 method) 

julia> f(1, 2) 
ERROR: 
in f(::Int64, ::Int64) at ./REPL[65]:1 

, но это сообщение об ошибке ужасно. Таким образом, мы можем бросить лучшую ошибку:

julia> f(x, y; z=throw(ArgumentError("z is required"))) = x + y + z 
f (generic function with 1 method) 

julia> f(1, 2) 
ERROR: ArgumentError: z is required 
in f(::Int64, ::Int64) at ./REPL[25]:1 

julia> f(1, 2, z=3) 
6 

Как oxinabox упоминалось, ошибка найдена во время выполнения, а не компиляции, но это то же самое с Python или Ruby.

Если это слишком многословным, это легко сделать макрос:

macro required(ex) 
    esc(Expr(:kw, ex, :(throw(ArgumentError("$($("$ex")) is required")))) 
end 

, то вы можете сделать

julia> foo(x, y; @required(z), @required(w), n=4) = x + y + z + w + n 
foo (generic function with 1 method) 

julia> foo(1, 2) 
ERROR: ArgumentError: z is required 
in foo(::Int64, ::Int64) at ./REPL[59]:1 

julia> foo(1, 2, z=3) 
ERROR: ArgumentError: w is required 
in (::#kw##foo)(::Array{Any,1}, ::#foo, ::Int64, ::Int64) at ./<missing>:0 

julia> foo(1, 2, z=3, w=4) 
14 

julia> foo(1, 2, z=3, w=4, n=5) 
15 

Причина это работает в том, что аргументы по умолчанию вычисляются, когда не передается аргумент , Предотвращая успешную оценку аргумента по умолчанию, для этого требуется, чтобы пользователь передал аргумент.

+0

Это очень умный способ использовать тот факт, что RHS аргумента по умолчанию оценивается, если значение по умолчанию не задано. –

+0

Очень умный. Таким образом, обновление, которое по умолчанию не оценивается до выполнения. Был сожжен еще давно, как и многие другие, с странными правилами Python для аргументов по умолчанию (например, эти изменчивые). Прекрасный макрос BTW. –

Смежные вопросы