ฟังก์ชัน 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เนื่องจากสคริปต์ไม่มีการเรียกใช้ฟังก์ชันที่มี 2 อาร์กิวเมนต์ รอบการทำงานคือการวัดความยาวของARGSใน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เดียวที่มีองค์ประกอบเดียวคือ a Tuple ("6","7").