Funzione Varargs con argomenti opzionali

Aug 20 2020

Ho uno script foo.jlcon una funzione che può richiedere 4 argomenti, 2 dei quali sono opzionali. Posso farlo facilmente con

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

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

Posso chiamarlo con argomenti dal terminale con

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

Ma se volessi specificare solo i primi due argomenti ae b, con c=1e d=2, non sarei in grado di chiamare lo script con $:> julia foo.jl 1 2poiché lo script non contiene una chiamata di funzione con 2 argomenti. Una soluzione è misurare la lunghezza di ARGSin foo.jle chiamare in modo condizionale 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

Ma questo è un po 'ingombrante quando si va oltre i 4 argomenti. Quindi ho esaminato l'uso di argomenti variabili, dove potevo chiamare un numero arbitrario di argomenti con

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

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

chiamandolo in più modi

$:> 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"],)

Ma poi non so come (o se sono in grado) impostare un valore predefinito per x...se non è fornito nel terminale. Qualcosa di ingenuo come function bar(a, b, x...=(1, 2))non funziona. Una soluzione qui sarebbe impostare le variabili all'interno della funzione a seconda del contenuto o della dimensione di x.... Ma non so se c'è un modo migliore per farlo.

Quindi sto cercando un modo per chiamare una funzione utilizzando gli argomenti dal terminale, dove è richiesto un numero (2 in questo caso), mentre il resto è facoltativo e impostato su un valore predefinito.

Risposte

2 PrzemyslawSzufel Aug 20 2020 at 07:12

Forse stai cercando la seguente funzione:

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

Questa funzione funzionerà con un numero qualsiasi di parametri a condizione che ce ne siano almeno due.

Proviamo con i seguenti dati:

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

Vediamo come funziona:

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"))

Infine nota che anche questo va bene:

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...)

In tal caso, per impostazione predefinita (se non sono presenti valori sufficienti args) a6sarà semplicemente un elemento Tuplecon l'unico elemento a Tuple ("6","7").