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?

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.

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

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.