Dict key=>value to array in comprehension

I’m trying to build a Cmd from the kwargs of a function. Basically, I want to turn eg foo("some_option"; opt1 = "thing", opt2="other_thing") into run(`my_cli some_option --opt1 thing --opt2 other_thing`). Cmd() can take a vector of strings, so I’m trying to use a comprehension to convert kwargs... into such a vector.

Basic function signature is

function foo(c1; kwargs...)
    c = ["my_cli", c1]
    append!(c, <something>)
    run(Cmd(c))
end

Where <something> is currently Iterators.flatten(("--" * string(k), string(v)) for (k,v) in pairs(kwargs))). So basically I’m making tuples of key=>value and then using Iterators.flatten to press them into a sequential vectorz. This works, but I was wondering if this is the best* approach? Other things I tried that didn’t work:

[("--" * string(k), string(v))... for (k,v) in pairs(kwargs)]
["--" * string(k), string(v) for (k,v) in pairs(kwargs)]

* I realize “best” is quite subjective, and perhaps I should be fine with the flatten approach, but it feels somehow more verbose than I was expecting. Then again, this is exactly what flatten is for, so…

It can be helpful to lean on command interpolation as much as possible instead of worrying about strings.

If you interpolate an iterable into a cmd, it’ll automatically “splat” out the contents with correct quoting and such:

julia> function foo(c1; kwargs...)
           args = Iterators.flatten((string("--", k), v) for (k,v) in pairs(kwargs))
           `$c1 $args`
       end
foo (generic function with 1 method)

julia> foo(`echo`; a = 1, b = 2)
`echo --a 1 --b 2`

Leaning on the pretty printing’s underlines can help you see that it’s putting quotes in the right places:

image

2 Likes

That answers a slightly different question, but nice to know! That wouldn’t have occurred to me. That said, my actual use-case is slightly more complicated, since, at least for the keys, I need replace _ with - since I can’t do eg foo(blah; my-opt = "bar"). But I can do this at least for the value :thinking:

   function foo(c1; kwargs...)
       args = Iterators.flatten((replace(string("--", k), '_'=>'-'), v) for (k,v) in pairs(kwargs))
       `$c1 $args`
   end
1 Like