Funkcja Varargs z opcjonalnymi argumentami
Mam skrypt foo.jlz funkcją, która może przyjmować 4 argumenty, z których 2 są opcjonalne. Z łatwością mogę to zrobić za pomocą
function bar(a, b, c=1, d=2)
println(a, b, c, d)
end
bar(ARGS[1], ARGS[2], ARGS[3], ARGS[4])
Mogę to nazwać argumentami z terminala za pomocą
$:> julia foo.jl 1 2 3 4
1234
Ale gdybym chciał podać tylko pierwsze dwa argumenty, aa za bpomocą c=1i d=2nie byłbym w stanie wywołać skryptu za pomocą, $:> julia foo.jl 1 2ponieważ skrypt nie zawiera wywołania funkcji z 2 argumentami. Wokół pracy jest pomiar długości ARGSw foo.jli warunkowo zadzwonić 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
Ale jest to trochę nieporęczne, gdy wykraczamy poza 4 argumenty. Więc przyjrzałem się użyciu zmiennych argumentów, w których mogłem wywołać dowolną liczbę argumentów za pomocą
function bar(a, b, x...)
println(a, b, x)
end
bar(ARGS[1], ARGS[2], ARGS[3:end])
nazywając to na wiele sposobów
$:> 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"],)
Ale potem nie wiem, jak (lub czy jestem w stanie) ustawić domyślne ustawienie, x...jeśli nie jest dostępne w terminalu. Coś naiwnego function bar(a, b, x...=(1, 2))nie działa. Rozwiązaniem byłoby tutaj ustawienie zmiennych wewnątrz funkcji w zależności od zawartości lub rozmiaru x.... Ale nie wiem, czy istnieje lepszy sposób, aby to zrobić.
Szukam więc sposobu na wywołanie funkcji za pomocą argumentów z terminala, gdzie liczba (w tym przypadku 2) jest wymagana, a reszta jest opcjonalna i ustawiona na wartość domyślną.
Odpowiedzi
Być może szukasz następującej funkcji:
function flexiargs(a1,a2,a3="3",a4="4",a5="5",a6...)
println((a1,a2,a3,a4,a5,a6))
end
flexiargs(args::AbstractVector)=flexiargs(args...)
Ta funkcja będzie działać z dowolną liczbą parametrów pod warunkiem, że są co najmniej dwa z nich.
Przetestujmy z następującymi danymi:
args0=["one","two"]
args1=["one","two","three","four"];
args2=vcat(args,"five","six","seven")
Zobaczmy, jak to działa:
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"))
Na koniec zwróć uwagę, że to również jest w porządku:
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...)
W takim przypadku domyślnie (jeśli nie ma wystarczającej liczby wartości args) a6będzie po prostu jednym elementem, Tuplea jedynym elementem będzie Tuple ("6","7").