Do-block syntax with keyword arguments

Is is possible to use the do syntax with keyword arguments? MWE:

just_call(f, args...; kwargs...) = f(args...; kwargs...)

# lambda
just_call((x; z) -> @show(x, z), 1; z = 2)

# do
just_call(1; z = 2) do x; z
    @show x, z
end

but the latter fails with

ERROR: MethodError: no method matching (::var"#20#21")(::Int64; z::Int64)

Closest candidates are:
  (::var"#20#21")(::Any) got unsupported keyword argument "z"
   @ Main REPL[30]:1

The manual does not talk about this, and I could not find an open issue.

5 Likes

Opened an issue

Surprising that this has not crop up before, but now I think that most methods in Base (if not all) that have the first parameter as a function do not pass anything as keyword argument to them.

That can be tweaked functionally with closures

# let's define
_print_vec2d((x,y)) = println("vec2d($x,$y)")

# and repl these
_print_vec2d((1,2))
foreach(_print_vec2d, [(1,2), (3,4), (5,6)])
foreach([(1,2), (3,4), (5,6)]) do xy; _print_vec2d(xy) end

now one can augment it with kw args

import LinearAlgebra: norm2
withkws(f; kwargs...) = (args...) -> f(args...; kwargs...)

_printx_vec2d((x,y); dounit::Bool) = begin
    if dounit
        n2 = norm2((x,y))
        rnd3(v) = round(v, digits=3)
        (x,y) = (rnd3(x/n2), rnd3(y/n2))
    end
    println("vec2d($x,$y)")
end

# and repl these
_printx_vec2d((1,2); dounit=true)
foreach(withkws(_printx_vec2d; dounit=true), [(1,2), (3,4), (5,6)])
foreach([(1,2), (3,4), (5,6)]) do xy
    withkws(_printx_vec2d; dounit=true)(xy)
    # or
    # xy |> withkws(_printx_vec2d; dounit=true)
end

NB: impl of this at the syntaxic level may imply a special do form like this

foreach([(1,2), (3,4), (5,6)]) do xy; withkws(; dounit=true) do (xy; dounit)
    _printx_vec2d(xy; dounit)
end end

otherwise ‘;’ will be catched as a newline / instruction separator