How to skip arguments when using a function

Hi there!

Is there a way in Julia to skip arguments when using a function? I am looking for something like the tilde in MATLAB:

# MATLAB
MyFunction(a, ~, c)

Thanks in advance!

So are we assuming that the second argument has some default value, and you want this default value to be used, but you still want to set the third value? I don’t think this exists in julia, and would say that this seems like a case where you should either define additional method signatures for the call to dispatch to or you should use keywords arguments instead of arguments.

Do you have control over the function you want to call, or is it a function from some library?

From googling a little it seems this does not exist for using functions in matlab, only for defining functions. So I’m not sure if I misunderstood you question, or maybe google wronged me?

3 Likes

Ciao Giulio, you can “skip” an argument in a function call (if this is what you are looking for…) if this argument is provided by a default value in the function definition. For positional arguments only the last parameters can have a default value, so say, you can’t skip the second out of three arguments. However, you can set any keyword argument to have a default argument and hence you can “skip” it.

For example I can define the function foo(a,b=2,c=3;A=4,B,C=6) = a+10*b+100*c+1000*A+10000*B+100000*C and then call it with, at minimum, foo(1,B=5) to obtain 654321, or by using the whole set of arguments as foo(1,2,3,A=4,B=5,C=6).

When I develop an API indeed, I tend to use keyword argument mostly for parameters that I expect to be rarely used outside their default value, so most people will not bother to use them.

1 Like

Can you provide a complete working example in Matlab? It would help a lot to understand what you want and find the best solution in Julia.

(My guess is that you want to ignore the input in the function definition, which you can do using _ in Julia).

2 Likes

You can do the same thing using _ in Julia:

julia> f(x,_,y) = 5x + 2y
f (generic function with 1 method)

julia> f(2,3,10)
30
3 Likes

That works, but why would one want to do it? What’s the use case?

Hello, thanks for your reply!

Actually, I am defining a function with two methods:

# method 1
FDEsolver(F, tSpan, y0, β, par...)
method 2
FDEsolver(F, tSpan, y0, β, JacobF, par...)

But because they both accept a vararg as last positional parameter, the method with fewer parameters is getting overwritten by the second method. In other words, when I use method 1 with the vararg par..., instead of using method 1 it uses method 2 with JacobF in place of par....

So I thought maybe I could define Jacob in both methods and skip it when I want to use method 1. I hope it helps to understand a little bit.

Thanks for replying! So could I define two methods like this?

f(a, b,  c, d) = a + b + c + d
f(a, _, _, d) = a + d

I know it’s a dumb example and it would be easier to define one method with 2 arguments and another with 4, but that is giving me troubles because my two methods both can accept a vararg and the one with 3 args plus vararg gets overwritten by the second method with 4 args plus vararg when this does not have vararg.

Your second definition replaces the first (the names don’t matter, only the types so here in both cases you have “4 generic arguments”).

Here are some possibilities:

  1. Users can give nothing for JacobF:

    # method 1
    FDEsolver(F, tSpan, y0, β, ::Nothing, par...)
    # method 2
    FDEsolver(F, tSpan, y0, β, JacobF, par...)
    

    then users can write FDEsolver(F, tSpan, y0, β, nothing, ...) to get the first method.

  2. Make the second method more specific by giving a type for JacobF, for example:

    # method 1
    FDEsolver(F, tSpan, y0, β, par...)
    # method 2
    FDEsolver(F, tSpan, y0, β, JacobF::AbstractMatrix{<:Real}, par...)
    

    This works if the first par argument never has the same type as JacobF: then Julia can use the type of the 5th argument to decide which method to call.

  3. Get rid of the vararg. What are these parameters? maybe there’s a better way to pass them than using a vararg?

  4. Pass JacobF as an optional keyword argument:

    FDEsolver(F, tSpan, y0, β, par...; JacobF=nothing)
    

    Then in the definition of FDEsolver you can do if isnothing(JacobF) .... Or you can dispatch on its value like in option 1, but hidden from the user:

    # method 1 and 2
    FDEsolver(F, tSpan, y0, β, par...; JacobF=nothing) = _FDEsolver(F, tSpan, y0, β, JacobF, par...)
    
    # unexported methods
    _FDEsolver(F, tSpan, y0, β, ::Nothing, par...) = ...
    _FDEsolver(F, tSpan, y0, β, JacobF, par...) = ...
    
4 Likes

Hello! Thanks a lot for the help.

Solution 1 worked out and now I am trying to advance it to solution 4.

1 Like