[Bug 29426] New: add default parameters

https://www.w3.org/Bugs/Public/show_bug.cgi?id=29426

            Bug ID: 29426
           Summary: add default parameters
           Product: XPath / XQuery / XSLT
           Version: Candidate Recommendation
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P2
         Component: XQuery 3.1
          Assignee: jonathan.robie@gmail.com
          Reporter: benito@benibela.de
        QA Contact: public-qt-comments@w3.org
  Target Milestone: ---

It is straightforward to define default parameters for named functions:
        Param      ::=          "$" EQName TypeDeclaration?
becomes
        Param      ::=          "$" EQName TypeDeclaration? (":="
VarDefaultValue)?

(under the constraint that a param with default value must not be followed by a
param without)


A function declaration  
    declare function local:foobar($a, $b as xs:integer := 123, $c := "xyz")    
{ ... }

is then equivalent to 

    declare function local:foobar($a, $b as xs:integer, $c)     { ... };
    declare function local:foobar($a, $b)       { local:foobar($a, $b, "xyz")
};
    declare function local:foobar($a)   { local:foobar($a, 123, "xyz") };

This is very simple. Calling, partial application and # references work just as
they work with those three separate definitions.

However, it should be considered a single function (or a set of functions with
different arity), because it will lead to a definition of default parameters
for the harder case of anonymous functions.

With the same grammar modification as above we get

    let $foobar := function ($a, $b as xs:integer := 123, $c := "xyz")  { ... }

Calling it should work like the local:foobar above, i.e. $foobar(1) =
local:foobar(1); $foobar(1,2) = local:foobar(1,2); ...

The same holds for partial application, e.g. $foobar(?) or foobar(1,?) is just
the same as local:foobar(?) or local:foobar(1, ?).

We could even allow partial application with default parameters. E.g.
$foobar(?, ? as xs:integer := 123, ? := "xyz") which would turn a function
without default parameters to a function with default parameters.

The type of a such a function is also simple. The function can be called with
different arity, so it is a set of functions with different arity. Thus the
type of this set is the union type of the typse of all the functions in the
set. (although types could also be extended to a type function (item(),
xs:integer, xs:string := "foobar", xs:int := 123). A function of this target
type T could be called with 3 different arities, so a function F has type T, if
the minimal arity of F is at most the minimal arity of T, the maximal arity of
F is at least the maximal arity of T and for each arity in between the types
match as for a single arity function )


Function coercion always coerces to some target type, a type that has a fixed
arity or is function(*). So it just picks the function with that arity from the
set and ignores all the others. (if the target type also has default parameters
and thus multiple arities, it is a little more complicated. The value is a set
of functions F, with different arities. The target type has a set of arities
At. For each A in At, we take the function f with the smallest arity of the set
{ f in F | arity of f >= A}. If no such function exists, it is an error. If the
arity of f is greater than the maximal arity of T it is also an error. If the
arity of f is greater than A, the remaining parameters of f are filled with the
default parameters of T. This results in a function of arity A that calls
function f. (An other explanation: The coerced function has so many total and
default parameters as the target type, and calls the original function with its
original default parameters. The default parameters of the target type are only
used at the beginning, i.e. if there is a parameter that is optional with a
default value in the target type, but does not have a default value in the
original function)


The last non-obvious question is what fn:function-arity should return.
It is reasonable to return the maximum, so function-arity($foobar) = 3, as the
function can be used as function with arity 3. 
There is no need to know the different arities.
Although it could also be modified to return xs:integer+, i.e.
function-arity($foobar) == (1,2,3)







Now that default parameters are defined, we can finally come to the point of
all of this.
On their own these parameters are not really useful, since you can just define
multiple functions.
However, with default parameters on anonymous functions the array and map types
can be redefined.

In JSONiq you can write $map() to get all keys of a map and $array() to get the
content of the entire array.
This is very useful. It is even more useful than ?*, since you can get the map
values from the map keys, 
but not the other way around, so it is better to have an easy syntax for the
map keys.

Using the default parameters, the map (and array) become a function($key :=
<some implicit value that returns the keys/content>) { ... }.

Then $map() and $map(key) are well-defined for some map $map. (as well as
$array(), $array(index))

(you cannot expect people to rewrite all their JSONiq queries)

-- 
You are receiving this mail because:
You are the QA Contact for the bug.

Received on Sunday, 7 February 2016 12:19:35 UTC