1
votes

I have a script foo.jl with a function that can take 4 arguments, 2 of which are optional. I can do this easily with

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

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

I can call this with arguments from the terminal with

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

But if I wanted to only specify the first two arguments a and b, with c=1 and d=2, I wouldn't be able to call the script with $:> julia foo.jl 1 2 since the script doesn't contain a function call with 2 arguments. A work around is to measure the length of ARGS in foo.jl and conditionally call 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

But this is a bit bulky when moving beyond 4 arguments. So I looked at using variable arguments, where I could call an arbitrary number of arguments with

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

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

calling this in multiple ways

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

But then I don't know how (or if I'm able) to set a default for x... if it's not provided in terminal. Something naive like function bar(a, b, x...=(1, 2)) does not work. A solution here would be to set the variables inside the function depending on the contents or size of x.... But I don't know if there is a better way to do this.

So I'm looking for a way to call a function using arguments from terminal, where a number (2 in this case) are required, while the rest are optional and set to a default.

1

1 Answers

2
votes

Perhaps you are looking for the following function:

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

This function will work with any number of params provided that there are at least two of them.

Let's test with the following data:

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

Let's see how it works:

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

Finally note that this is also 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...)

In that case by default (if not enough values are in args) a6 will be simply a one element Tuple with the only element being a Tuple ("6","7").