# Inline functions with default parameters

I have a doubt about default arguments. In the Functions documentation it says that I can use optional arguments aswell as defining a function with a simplyfied syntax of
y(x)=x**2, but can’t I have such a function with optional parameters? For example this works

``````t=1:0.1:10
y(t,v_0=1,a=-9.8,y_0=0)=y_0+v_0*t+a/2*t^2

``````

If I call it with

``````
y_vec=y.(t)
``````

But not if I call it with

``````
y_vec=y.(t,v_0=10)
``````

You should include error messages:

``````julia> y.(t,v_0=10)
ERROR: MethodError: no method matching y(::Float64; v_0::Int64)

Closest candidates are:
y(::Any, ::Any, ::Any, ::Any) got unsupported keyword argument "v_0"
@ Main REPL[11]:1
y(::Any, ::Any, ::Any) got unsupported keyword argument "v_0"
@ Main REPL[11]:1
y(::Any, ::Any) got unsupported keyword argument "v_0"
@ Main REPL[11]:1
...

Stacktrace:
[4] getindex
[5] copy
[7] top-level scope
@ REPL[13]:1
Some type information was truncated. Use `show(err)` to see complete types.
``````

Your last argument is call is treating `v_0` as if it were a keyword argument, instead of a positional argument. You should just do `y.(t, 10)`, or change the function to use keyword arguments in the definition.

2 Likes

Oh I fell for that as well recently. though there is a `,` in `y_vec=y.(t,v_0=10)` the `v_0=` makes Julia start the “keyword section”, so what you wrote is the same as `y_vec=y.(t; v_0=10)`. I felt accepting a `,` here as well is maybe misleading.

As Daniel wrote all your arguments are positional (optional) and no keywords. Besides that I am not 100% sure how keywords work together with your broadcasting, but that is maybe a next point to check then.

1 Like

The keyword arguments are not broadcasted over, as far as I can tell:

``````julia> function f(x; v)
@show x, v
end
f (generic function with 2 methods)

julia> f.([1, 2, 3]; v = [1, 2, 3])
(x, v) = (1, [1, 2, 3])
(x, v) = (2, [1, 2, 3])
(x, v) = (3, [1, 2, 3])

julia> f.(1, v = [1, 2, 3])
(x, v) = (1, [1, 2, 3])
(1, [1, 2, 3])
``````

This is handled in `Base.broadcasted_kwsyntax`:

``````julia> Meta.@lower f.([1, 2, 3]; v = [1, 2, 3])
:(\$(Expr(:thunk, CodeInfo(
@ none within `top-level scope`
1 ─ %1 = Base.vect(1, 2, 3)
│   %3 = Core.tuple(:v)
│   %4 = Core.apply_type(Core.NamedTuple, %3)
│   %5 = Base.vect(1, 2, 3)
│   %6 = Core.tuple(%5)
│   %7 = (%4)(%6)
│   %8 = Core.kwcall(%7, %2, f, %1)
│   %9 = Base.materialize(%8)
└──      return %9
))))
``````
3 Likes

The NamedPositionals.jl package allows function calls closer to OP’s intent:

``````using NamedPositionals
y1 = (u->@np y(u, v_0=10;)).(t)
y2 = (u->@np y(u, v_0=5, a=-1.62;)).(t)
y3 = (u->@np y(u, v_0=1, a=-9.8, y_0=7.5;)).(t)
``````

I could not get broadcasting to work with the @np macro, hence the broadcasting of anonymous functions above.

But difficult to see the advantage of this compared to the simple calls:

``````v_0 = 10
y1b = y.(t, v_0)

v_0 = 0.1; a = -1.62
y2b = y.(t, v_0, a)

v_0 = 1; a = -9.8; y_0 = 7.5
y3b = y.(t, v_0, a, y_0)
``````
1 Like

An orthogonal point to consider - I often find that when I’m writing function signatures like that, it’s probably time to make a struct that encodes a bunch of those parameters

2 Likes
1 Like