The problem has been solved yesterday, but you seem to be interested in the motivation, so here we go (I’ll show one use case regarding the box element, but actually the problem and the solution are very general):
I have a function that creates (returns) a box. That function (among others) takes a width parameter. That parameter shall determine the box’s width.
However, the calling code may leave away the width parameter when calling the function. In that case, I don’t want to include the width property into the box properties as well. Rather, the “default” or “current” width value for boxes (as determined by typst itself, or by set or show rules) should be used.
This means that I don’t know in advance which entries the dictionary with the box properties has. This is the key point: The problem is not that I don’t know the box property values in advance. The problem is that I don’t know in advance whether or not a certain box property must be set at all.
Argument spreading is the right tool to solve this problem. Minimal example:
#let mybox(width: none) = {
let props = (:)
if (none != width) {
props.width = width
}
box(
..props,
[foo bar baz]
)
}
The code above behaves exactly as I need.
I am aware that I could have solved this general problem another way (without argument spreading) in this specific case, because the width property for a box can be set to auto, which achieves the same effect under normal circumstances:
#let mybox(width: none) = {
let w = auto
if (none != width) {
w = width
}
box(
width: w,
[foo bar baz]
)
}
However, there are two arguments against that approach:
First, it could conflict with other document-wide rules (e.g., show or set) that assign a default width to a box (e.g., 10mm). These other rules would be overridden by setting width: auto.
Second, there are other properties that are neither allowed to be set to auto,nor does another default value exist they can be set to. In such cases, the above code structure is not appropriate, and we need argument spreading. An example for such a property is inset.
In such situations, the only alternative I can think of would be to put the respective code into a context, to query the current value of the respective property in that context, and to use that value as the value for the respective dictionary entry when constructing the element in question.
The latter would be extremely unpleasant and cumbersome, though, and in addition would impose all the ugly problems that are associated with a context (e.g., that it is opaque and that its return value practically cannot be used in further programmatic processing). Plus, I suspect problems with that method if the respective property hasn’t been set explicitly (yet). I don’t plan to try that approach, because argument spreading is so much superior in such situations.