# Forwarding optional function inputs

Hi, is there a way to nicely overload functions with optional inputs that call other functions with optional inputs (if that makes sense).

``````const DEFAULT_K = 10.0;
const DEFAULT_N = 10.0;

struct A
x::Float64
end

xtimesk(x::Float64, k::Float64 = DEFAULT_K) = x * k             # (0)
xtimesk(a::A, k::Float64)                   = xtimesk(a.x, k)   # (1)
xtimesk(a::A)                               = xtimesk(a.x)      # (2)

xtimesn(x::Float64, n::Float64 = DEFAULT_N) = x * n             # (3)
xtimesn(a::A, n::Float64 = DEFAULT_N)       = xtimesk(a.x, n)   # (4)

a = A(2.2)

@printf("%g\n%g\n%g\n%g\n", xtimesk(a), xtimesk(a, 5.0), xtimesn(a), xtimesn(a, 5.0))
``````

Iâ€™ve put together a small example of what Iâ€™m trying to achieve above, with `xtimesk()` giving me what I want with option to call it with or without k, but is there a way to define it in a single line?

I could do something along the lines of `xtimesn()` but that means defining the default input value twice which I would also like to prevent.

Is there another way to do this? Iâ€™m coming from Matlab and there I would do this as something like this:

``````classdef A
properties
x (1,1) double
end

methods
function this = A(inX)
this.x = inX;
end

function out = xtimesk(this, varargin)
out = xtimesk(this.x, varargin{:});
end
end
end

function out = xtimesk(x, k)
if nargin < 2
k = 10.0;
end
out = x * k;
end
``````

I assume thereâ€™s some similar solution like varargin in Julia? But was wondering if there is also a neater way to achieve this without obfuscating the code by use of something like varargin?

Thanks,
Titas

Maybe thereâ€™s a better way, but this is what i would do:

``````julia> valueof(x::Number) = x
valueof (generic function with 1 method)

julia> valueof(a::A) = a.x
valueof (generic function with 2 methods)

julia> xtimesk(x, k::Float64 = DEFAULT_K) = valueof(x) * k
xtimesk (generic function with 2 methods)

julia> xtimesn(x, n::Float64 = DEFAULT_N) = valueof(x) * n
xtimesn (generic function with 2 methods)

julia> a = A(2.2)
A(2.2)

julia> @show xtimesk(a) xtimesk(a, 5.0) xtimesn(a) xtimesn(a, 5.0);
xtimesk(a) = 22.0
xtimesk(a, 5.0) = 11.0
xtimesn(a) = 22.0
xtimesn(a, 5.0) = 11.0
``````

Perhaps it would make sense to define `*(a::A, b) = *(a.x, b); xtimesk(x, k=DEFAULTK) = x*k`. Or even go into promotion rules if `A` is a `Number` candidate.

1 Like

Thanks, good to know, but not exactly what Iâ€™m looking for. This seems to be equivalent to rewriting my example as:

``````xtimesk(x::Float64, k::Float64)         = x * k             # (0)
xtimesk(a::A, k::Float64 = DEFAULT_K)   = xtimesk(a.x, k)   # (1)
``````

And ideally the defaults would be defined at the lowest level - (0) in this case. Multiplication here was just a simple example to explain what I would like to achieve.

Thanks, didnâ€™t even think about doing it this way. This seems to do exactly what Iâ€™m looking for, however it adds a bit of indirection and if I write it like this:

``````struct B
x::Float64
end

valueof(x::Number) = x
valueof(b::B) = b.x
xtimesk2(x, k::Float64 = DEFAULT_K) = valueof(x) * k
xtimesn2(x, n::Float64 = DEFAULT_N) = valueof(x) * n

b = B(2.2)
@show xtimesk2(b) xtimesk2(b, 5.0) xtimesn2(b) xtimesn2(b, 5.0)
``````

I then lose the abilty to find xtimesk as a method available with A/B:

``````julia> methodswith(A)
[1] xtimesk(a::A) in Main at ...
[2] xtimesk(a::A, k::Float64) in Main at ...
[3] xtimesn(a::A) in Main at ...
[4] xtimesn(a::A, n::Float64) in Main at ...

julia> methodswith(B)
[1] valueof(b::B) in Main at ...
``````

Why is that ideal? Presumably the default is part of the API, so it seems reasonable to define it in public API methods.
You can mimic your MATLAB example like this:

``````xtimesk(x::Float64, k::Float64 = DEFAULT_K) = x * k
xtimesk(a::A, args...) = xtimesk(a.x, args...)
``````

but Iâ€™m not sure itâ€™s better than simply repeating ` = DEFAULT_K` in each method signature (as long as `DEFAULT_K` itself is only defined once).

1 Like

Thanks, this is the answer I was looking for (although was hoping there was a nicer way in Julia where you donâ€™t lose having named arguments).

Didnâ€™t mean ideal as an ideal way to do something like this, was more meant as â€śI would like to find a way to do it like thisâ€ť. Just looking to find ways to do things in Julia that I am used to in Matlab, so simply trying to replicate those and learn the language along the way.

Your example is not exactly the same, because my definition also allows `xtimesk(1.0)`, which I would imagine is the reason you would want the default to be defined â€śat a lower levelâ€ť. In general it is considered good Julia to add as few type annotations as possible.