Re: Keyword arguments [was fn:slice]

On Sat, 2020-12-05 at 09:16 +0000, Michael Kay wrote:
> > 
> > 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.

I'm proposing
(1) that keyword arguments can be used for any function without having
to change tha function at all - you still have to supply all the
arguments for the function variant you want to call, and type-based
static dispatch still works;

(2) since keyword arguments introduce the possibility of optional
arguments, a syntax for that for user-defined functions;

(3) that expressions not be allowed to mix keyword and positional
arguments - i don't have strong feelings about this, maybe we'd need to
try it, but it feels like it'd cut down on user errors - maybe in a mix
all positional args must come before  any keyword parameters;

(4) to introduce a notation to refer to functions of variable arity - i
suggested qname:* but one could also perhaps have qname:5+ to mean 5 or
more (i don't think that makes for any ambiguities although if you use
an EQname as a map key i'm not certain)

As with any other keyword argument proposal, it would be necessary, or
at least prudent to review the names of arguments of existing
functions, as they suddenly become part of a public API. For example, i
see in F&O,
fn:sum($arg as xs:anyAtomicType*) as xs:anyAtomicType
so one would write sum(arg := (1, 2, 3))
and maybe that's OK.

For fn:transform() one could call the function as now, with a single
map argument; but it could be modified to accept optional parameters,
which would then make fn:transform#* be statically typesafe - that is,
all supplied parameters could be checked to the extent possible. I
mentioned this as it was one of your examples, and i think a good one.

Existing varadic functions would continue to work unaltered, based on
the parameters supplied, so date#5 would still work as before.

> 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. 

Unless they modified them,  though, that wouldn't be a problem.  They
would still be two different functions and you'd need to supply either
two or five parameters.

> This means that calls on user-defined functions wouldn't be able to
> use the new mechanism unless the function definition is changed;.
That's not what i am proposing.

> By contrast, the mechanism I have been proposing of assembling
> keyword arguments into a map requires no change to existing function
> signatures or implementations.
No, we are the same in this regard.

> 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.

This is interesting but doesn't show how the optionality is handled in
the body of the function - how do i write an expression that determines
that role was not supplied? Do i get the empty sequence? It's true the
syntax i propose does not have a way for functions defined in pure
XPath to have optional arguments.

Probing the difference between suggestions may at least help us to
understand what's proposed - thanks for replying!




-- 
Liam Quin, https://www.delightfulcomputing.com/
Available for XML/Document/Information Architecture/XSLT/
XSL/XQuery/Web/Text Processing/A11Y training, work & consulting.
Barefoot Web-slave, antique illustrations:  http://www.fromoldbooks.org

Received on Saturday, 5 December 2020 16:57:34 UTC