I’m looking into interfacing Julia to another language with different rules for identifiers. Specifically, e.g., “m.R” would be a valid identifier in this other language. In the past, I’ve worked with this problem for Python. In Python, suppose I define a function:
def my_func (** kwargs):
return kwarg
then I get the following behavior:
my_func (a=2, b=3)
leads to {’a’: 2, ’b’: 3}, and
D = {"a":2, "b": 3}
my_func(**D)
leads to {’a’: 2, ’b’: 3} .
Similarly, my_func(m.R = 8.31) crashes in Python – because “m.R” is an illegal identifier, while:
D = {"m.R":8.31}
my_func(**D)
gives the desired result: {'m.R':8.31}.
Thus: for those identifiers in this other language that are valid Python (or: Julia) identifiers, I can use keyword assignment when calling the function. For those identifiers that are invalid Python identifiers, I can resort to this “dirty” trick of specifying the identifiers as dictionary keys (where any string is valid).
You can get the *args, and ***kwargs in Julia by doing
function my_func(args... ; kwargs...)
end
which will fill kwargs with a dictionary like you would expect. I am not sure you can do the trick with the string keys as kwargs keys must be a Symbol so the dotted part is not legal. I am sure some macro tricks could get around this, but likely better to just use an underscore instead of a dot.
leads to my_func(a=1,b=2) returns a dictionary. Which I guess implies that internally, the kwargs are interpreted as a Dict. But I also need to alternatively use a Dict as an argument, and have it come through the call in the form of a Dict.
Perhaps I need to have two methods for this, and rely on dispatching?
Regarding symbols, and, e.g., “m.R”… my understanding is that the syntax:
:(expression) really means an unevaluated expression, and it is only in the case that “expression” equals a valid identifier that this is equal to a symbol. In other words… :(m.R) is not a symbol.
in general, Symbol(string) creates a symbol for anything within the string, e.g., Symbol(“m.R”) gives the symbol.
The equivalent to python’s foo(**D) in Julia is foo(;D...) in which D is a collection of Pairs (a Dict with Symbol keys will work, as will a vector of Pair{Symbol, whatever}. For example, on Julia v0.7 master:
julia> f(;kw...) = kw
f (generic function with 1 method)
julia> f(hello=1, world=2)
pairs(::NamedTuple) with 2 entries:
:hello => 1
:world => 2
julia> D = [:hello => 1, :world => 2]
2-element Array{Pair{Symbol,Int64},1}:
:hello => 1
:world => 2
julia> f(;D...)
pairs(::NamedTuple) with 2 entries:
:hello => 1
:world => 2
julia> D = Dict([:hello => 1, :world => 2])
Dict{Symbol,Int64} with 2 entries:
:hello => 1
:world => 2
julia> f(;D...)
pairs(::NamedTuple) with 2 entries:
:hello => 1
:world => 2
and using this syntax you can pass arguments with keys that are not valid identifiers:
How does named tuples work in v.0.7? (The same way as in v.0.6.2? Or a simpler way? Do one still have to use the NamedTuples package? And the same macro system to define the named tuples?)