Функция Varargs с необязательными аргументами

Aug 20 2020

У меня есть сценарий foo.jlс функцией, которая может принимать 4 аргумента, 2 из которых являются необязательными. Я могу легко сделать это с

function bar(a, b, c=1, d=2)
    println(a, b, c, d)
end

bar(ARGS[1], ARGS[2], ARGS[3], ARGS[4])

Я могу вызвать это аргументами из терминала с помощью

$:> julia foo.jl 1 2 3 4
1234

Но если бы я хотел указать только первые два аргумента aи bс помощью c=1и d=2, я бы не смог вызвать сценарий с помощью, $:> julia foo.jl 1 2поскольку сценарий не содержит вызова функции с двумя аргументами. Обходной способ - измерить длину ARGSin foo.jlи условно вызвать bar:

if length(ARGS) == 2
    bar(ARGS[1], ARGS[2])
elseif length(ARGS) == 3
    bar(ARGS[1], ARGS[2], ARGS[3])
else
    bar(ARGS[1], ARGS[2], ARGS[3], ARGS[4])
end

Но если выйти за рамки 4 аргументов, это немного громоздко. Итак, я рассмотрел использование переменных аргументов, где я мог бы вызвать произвольное количество аргументов с помощью

function bar(a, b, x...)
    println(a, b, x)
end

bar(ARGS[1], ARGS[2], ARGS[3:end])

называя это несколькими способами

$:> julia foo.jl 1 2 12(String[],) $:> julia foo.jl 1 2 3 4
12(["3", "4"],)
$:> julia foo.jl 1 2 3 4 5 6
12(["3", "4", "5", "6"],)

Но тогда я не знаю, как (или могу) установить значение по умолчанию, x...если оно не предусмотрено в терминале. Что-то наивное вроде function bar(a, b, x...=(1, 2))не работает. Решением здесь было бы установить переменные внутри функции в зависимости от содержимого или размера x.... Но я не знаю, есть ли лучший способ сделать это.

Итак, я ищу способ вызвать функцию с использованием аргументов из терминала, где требуется число (в данном случае 2), а остальные являются необязательными и установлены по умолчанию.

Ответы

2 PrzemyslawSzufel Aug 20 2020 at 07:12

Возможно, вы ищете следующую функцию:

function flexiargs(a1,a2,a3="3",a4="4",a5="5",a6...)
    println((a1,a2,a3,a4,a5,a6))
end
flexiargs(args::AbstractVector)=flexiargs(args...)

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

Давайте протестируем со следующими данными:

args0=["one","two"]
args1=["one","two","three","four"];
args2=vcat(args,"five","six","seven") 

Посмотрим, как это работает:

julia> flexiargs(args0)
("one", "two", "3", "4", "5", ())

julia> flexiargs(args1)
("one", "two", "three", "four", "5", ())

julia> flexiargs(args2)
("one", "two", "three", "four", "five", ("six", "seven"))

Наконец, обратите внимание, что это тоже нормально:

function flexiargs(a1,a2,a3="3",a4="4",a5="5",a6...=("6","7"))
    println((a1,a2,a3,a4,a5,a6))
end
flexiargs(args::AbstractVector)=flexiargs(args...)

В этом случае по умолчанию (если в нем недостаточно значений args) a6будет просто один элемент Tupleс единственным элементом Tuple ("6","7").