This may have been brought up already, but it would be nice to have a compact syntax for making a data structure that is a mixture of positional and keyword arguments.
As an analogy to the function syntax f(1, 2; x=2, y=3), I would propose the syntax:
(1, 2; x=2, y=3)
which could get lowered to:
((1, 2), (x=2, y=3))
or some other data structure storing the positional and named arguments.
I find that it is a common code pattern to carry around a data structure with a Tuple of positional arguments and a NamedTuple of named arguments, which will eventually get passed to a function as positional and keyword arguments.
I would find interesting to have a structure for which f(positionals_and_keywords...) worked as f(positionals...; keywords...), but is there so much gain in having them together instead of separate? There could be a @splat macro that makes f(x) into f(x.positionals...; x.keywords...) no?
The difference in literal seems very small (just add two pairs or parenthesis), and not sure it merit even a macro, as it would save at most one character?
To me the main concern is the readability of the code, not the amount of typing. I often use verbose names for functions and variables with the goal of having the code readable long into the future with minimal reference to documentation, but I’m also of the opinion that simple things should have simple syntax.
It seems like fundamentally the question is, if we have that syntax for functions, why not for this as well (unless there is a better alternative proposal for the meaning of that syntax, which would be a good argument against it)? Obviously people like the function syntax and no would argue we should type f((1, 2), (x=2, y=3)) everywhere.
Of course we could make a macro or data structure for this but it is nicer to avoid that when possible (which is why I like using built-in types like Tuple and NamedTuple whenever I can).
Though I agree it would be nice to be able to splat whatever data structure you get into a function like f((1, 2; x=2, y=3)...). You could of course make that work by defining a version of your function f(args::Tuple, kwargs::NamedTuple) = f(args...; kwargs...), which is what we often do.
Thanks! Exactly what I had in mind. Maybe an intermediate solution would be a macro that turns everything of the form (1, 2; x=2, y=3) into a FrankenTuple in a code block but of course it would be nicer if the syntax was built-in.
That is a nice workaround I did not think about, but it makes necessary to add new methods to every function. This could be automated with macros but in the end you would need to do this in advance at the global scope for every function you want to have this syntax. Also, I think you meant:
If this syntax does not clash with anything, maybe it would be an interesting addition. However, if splat and slurp are to work over it, then it would yet either break the symmetry of splatting, or be a breaking change. This is: f(x...) = typeof(x) should print what? If this should print FrankenTuple, then adding the new FrankenTuple would be a breaking change; if it should print Tuple then the slurp and splat operators are not symmetric anymore, because f(frankentuple...) would splat both positional and keyword arguments, while f(x...) = ... only captures one set of them (i.e., new syntax would be necessary to capture a frankentuple).