julia

Can I pass keyword args to do-blocks in julia?


Below is an example:

def(f::Function) = f

f1 = def() do x
    x
end

f2 = def() do x, y
    x, y
end

f3 = def() do x, y; z # this syntax is accepted
    x, y, z
end

f1(1)
f2(1, 2)
f3(1, 2, z=3) # ERROR: LoadError: function #13 does not accept keyword arguments

The example below is not my actual use case, but it illustrates the question. How should I handle kwargs in a do-block?


Solution

  • As far as I know this is not possible. If you look at /src/julia-parser.scm file you can find that parsing of a do block is defined in parse-do here. And you can see that do-block is rewritten to an anonymous function that can only accept positional arguments in doargs variable separated by commas.

    In this line you can see that ; explicitly terminates parsing of arguments of do-block. This means that:

    julia> z = "hello"
    "hello"
    
    julia> f3 = def() do x, y; println(z) # this syntax is accepted
               x, y, z
           end
    #24 (generic function with 1 method)
    
    julia> f3(100, 1000)
    hello
    (100, 1000, "hello")
    

    will work as the code past ; is treated as a part of do-block body.

    You could try to put ( and ) around the arguments like this:

    julia> f3 = def() do (x, y; z)
               x, y, z
           end
    ERROR: syntax: invalid assignment location "; z"
    
    julia> f3 = def() do (y; z)
               y, z
           end
    ERROR: syntax: "begin
        y
        # REPL[52], line 1
        z
    end" is not a valid function argument name
    

    This will go through parser, but then julia-syntax.scm will throw an error. This probably could be improved as:

    f3 = def(function(x, y; z)
        x, y, z
    end)
    

    works correctly (you can consider opening an issue for this on https://github.com/JuliaLang/julia/issues).

    Until this is fixed the only thing you can do is to use anonymous function definition approach I have given above (although it is not very clean).