Keyword arguments [was fn:slice]

> So Mike's example is exactly what i was suggesting before in this
> regard, except i want the keywords to map to named arguments so there
> can be useful static type checking. We would need to allow optional
> arguments for transform() at least, though, and refer to it e.g. as
> fn:transform#*

My only problem with this proposal is whether it can be made backwards-compatible. I guess that in a strict sense, if a parameter has to be declared optional before it can be used in this way, then existing code that doesn't use optional parameters won't be affected. But at a usability level, if different functions follow different conventions, then it could make life difficult for users.

In the case of system-supplied functions, we've been very careful in the design to ensure, for example, that format-date#2 and format-date#5 have consistent syntax and semantics, so we could simply make the last three parameters optional and turn it into a single function, and a call with any number of supplied arguments could bind to format-date#5 without difficulty. For compatibility, dynamic references to format-date#2 and format-date#5 would still need to work, and for strict compatibility, function-arity(format-date#2) would still have to return 2, while function-arity(format-date#5) returns 5, so they would still be different functions.

For user-written functions, it's possible that users haven't followed the same conventions, and my:ftingle#2 might do something completely different from my#ftingle#5, so that my:ftingle#2 isn't equivalent to my:ftingle#5 with optional parameters. This means that calls on user-defined functions wouldn't be able to use the new mechanism unless the function definition is changed;. Some function libraries such as the EXPath file and binary libraries are unlikely to change in a hurry; and until they do, users would have to be aware that the new calling mechanism is available for some function libraries and not for others.

By contrast, the mechanism I have been proposing of assembling keyword arguments into a map requires no change to existing function signatures or implementations.

Another difference is that my proposal allows the set of accepted keywords to be dynamic and/or extensible. It's possible with a Record type definition in the signature to restrict the available keywords, but you don't have to. The specification of a function can make it extensible if it chooses (so an implementations might accept vendor-defined keywords, as in fn:serialize()) and it's also possible to design functions where the set of keywords is completely open-ended, for example one could design a function where the call

new-element('p') => with-attributes(class: "note", role: "footnote", date: current-date())

accepts any set of names for the attributes of a new element.

Michael Kay

Received on Saturday, 5 December 2020 09:16:37 UTC