Varargs berfungsi dengan argumen opsional

Aug 20 2020

Saya memiliki skrip foo.jldengan fungsi yang dapat mengambil 4 argumen, 2 di antaranya opsional. Saya bisa melakukan ini dengan mudah

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

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

Saya dapat menyebutnya dengan argumen dari terminal dengan

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

Tetapi jika saya hanya ingin menentukan dua argumen pertama adan b, dengan c=1dan d=2, saya tidak akan dapat memanggil skrip dengan $:> julia foo.jl 1 2karena skrip tidak berisi pemanggilan fungsi dengan 2 argumen. Solusinya adalah mengukur panjang ARGSin foo.jldan panggilan bersyarat 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

Tapi ini agak berlebihan saat melampaui 4 argumen. Jadi saya melihat menggunakan argumen variabel, di mana saya dapat memanggil sejumlah argumen dengan

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

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

menyebut ini dengan berbagai cara

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

Tapi kemudian saya tidak tahu bagaimana (atau apakah saya bisa) untuk mengatur default x...jika tidak tersedia di terminal. Sesuatu yang naif function bar(a, b, x...=(1, 2))tidak akan berhasil. Solusi di sini adalah dengan mengatur variabel di dalam fungsi tergantung pada konten atau ukuran x.... Tapi saya tidak tahu apakah ada cara yang lebih baik untuk melakukan ini.

Jadi saya mencari cara untuk memanggil fungsi menggunakan argumen dari terminal, di mana angka (2 dalam hal ini) diperlukan, sedangkan sisanya opsional dan disetel ke default.

Jawaban

2 PrzemyslawSzufel Aug 20 2020 at 07:12

Mungkin Anda mencari fungsi berikut:

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

Fungsi ini akan bekerja dengan sejumlah parameter asalkan ada setidaknya dua di antaranya.

Mari kita uji dengan data berikut:

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

Mari kita lihat cara kerjanya:

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

Akhirnya perhatikan bahwa ini juga OK:

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

Dalam hal ini secara default (jika tidak ada cukup nilai args) a6akan menjadi satu elemen Tupledengan satu-satunya elemen menjadi a Tuple ("6","7").