This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 27537 - [XP31] Sequence on lhs of arrow operator
Summary: [XP31] Sequence on lhs of arrow operator
Status: RESOLVED FIXED
Alias: None
Product: XPath / XQuery / XSLT
Classification: Unclassified
Component: XPath 3.1 (show other bugs)
Version: Last Call drafts
Hardware: SGI All
: P2 normal
Target Milestone: ---
Assignee: Jonathan Robie
QA Contact: Mailing list for public feedback on specs from XSL and XML Query WGs
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-12-08 16:27 UTC by Michael Kay
Modified: 2015-07-07 16:05 UTC (History)
3 users (show)

See Also:


Attachments

Description Michael Kay 2014-12-08 16:27:46 UTC
Botond Biró raised this on public-qt-comments:

What is the expected behavior if the arrow postfix operator is applied to a sequence containing more than one item?

Does the semantic equivalence "$seq=>$f(…) is the same as $f( $seq, … )" also hold when count($seq) != 1?
ex, ( 1, 2, 3 ) => avg() or ()=>count()

In the last call working draft the wording for arrow postfix definition implies that a [single] item is expected, but don’t see why or if this restriction would be necessary.

“[Definition: An arrow operator is a postfix operator that applies a function to an item, using the item as the first argument to the function.] If $i is an item and f() is a function, then $i=>f() is equivalent to f($i), and $i=>f($j) is equivalent to f($i, $j).”

If the single restriction doesn't apply, then I suggest modifying the definition to reflect this. 

And a question related to operator precedence: currently it is not possible to use a node selection on the lhs of an arrow operator without wrapping it with extra parenthesis:
$DAYS//@From => max() - syntax error
($DAYS//@From) => max() - ok
is it planned for the arrow operator to be moved above the step expression(i.e. get lower precedence) so that one can use a node selection => without the need of the extra parenthesis?

MHK comment:

I don't think there was ever any intention to restrict the LHS to a single item. The definition should be:

[Definition: An arrow operator is a postfix operator that applies a function to an value, using the value as the first argument to the function.] If $s is a sequence and f() is a function, then $s=>f() is equivalent to f($i), and $s=>f($j) is equivalent to f($s, $j).

As regards the operator precedence, I can see the case for making 

/section/para => count()

mean count(/section/para)

One can also see a case for richer expressions on the right, e.g.

$input => $function-lib?cosine

For an example of a surprise coming from the current rules, consider

-1 => abs()

which returns -1.

There would seem to be a case for decoupling the arrow operator from the Postfix construct, and having

[95]   	CastExpr ::= ArrowExpr ( "cast" "as" SingleType )?
[NN]    ArrowExpr ::= UnaryExpr "==>" UnaryExpr
Comment 1 Michael Kay 2014-12-08 16:30:38 UTC
In the last line, s/==>/=>/
Comment 2 Jonathan Robie 2014-12-09 20:32:56 UTC
In today's call, we agreed to allow the left hand side to be a sequence, in which case the sequence is passed as the first argument to the function.

We did not have agreement to change precedence.
Comment 3 Michael Kay 2014-12-11 15:39:07 UTC
The minutes here differ from the updates made to Bugzilla. Therefore reopening. The minutes record a decision to leave the bug open until next week, and do not record the agreement (and lack of agreement) reported by Jonathan.
Comment 4 Michael Kay 2014-12-11 15:59:53 UTC
Note also:

(a) (editorial) the production for ArrowFunctionSpecifier should be included in section  3.2.3

(b) contrary to my comment #0, the syntax could probably become

[NN]    ArrowExpr ::= UnaryExpr "=>" ArrowFunctionSpecifier ArgumentList

The effect of the change would be to make unary +/-, !, and / on the left bind more tightly than =>, for example

-1 => abs()
//x => count()
a!tokenize()!upper-case() => distinct-values()

now work as one might expect. (Note, it's natural to put spaces around the lower-precedence operator).
Comment 5 Jonathan Robie 2014-12-14 23:14:33 UTC
(In reply to Michael Kay from comment #3)
> The minutes here differ from the updates made to Bugzilla. Therefore
> reopening. The minutes record a decision to leave the bug open until next
> week, and do not record the agreement (and lack of agreement) reported by
> Jonathan.

I believe the problem is in the minutes. I suggest we close this bug, which is filed against the specification and correct the minutes.
Comment 6 Michael Kay 2014-12-14 23:56:30 UTC
Jonathan, you may believe the minutes are wrong, but if there is a conflict between the minutes and the bug resolution then we should leave the bug open until the conflict is resolved.
Comment 7 Botond Biró 2014-12-18 09:50:35 UTC
(In reply to Michael Kay from comment #4)

> (b) contrary to my comment #0, the syntax could probably become
> 
> [NN]    ArrowExpr ::= UnaryExpr "=>" ArrowFunctionSpecifier ArgumentList

I think one would also need to change the occurrence of the part after the UnaryExpr:
-min occur zero- to fix parsing of simple unary expressions 
-max occur unbounded - to support chaining
So the EBNF should look sg. like:

[NN]    ArrowExpr ::= UnaryExpr ("=>" ArrowFunctionSpecifier ArgumentList)*
Comment 8 Michael Kay 2014-12-18 10:04:21 UTC
Thanks, yes, that problem was discovered when the WG reviewed this on Tuesday. The current state is that we're sympathetically inclined to the proposal, and looking in detail at the grammar implications and at further use csses.
Comment 9 Michael Dyck 2015-01-06 18:18:21 UTC
More explicitly, the productions:
    CastExpr    ::= UnaryExpr ( "cast" "as" SingleType )?
    ...
    PostfixExpr ::= PrimaryExpr ( ... | Lookup | ArrowPostfix )*

would become:
    CastExpr    ::= ArrowExpr ( "cast" "as" SingleType )?
    ArrowExpr   ::= UnaryExpr ( "=>" ArrowFunctionSpecifier ArgumentList )*
    ...
    PostfixExpr ::= PrimaryExpr ( ... | Lookup )*

I did a trial parser/applet build with these edits and they don't appear to
cause any problems (ambiguities or conflicts).

----

Here's the pertinent chunk of the XQuery/XPath 3.x expression hierarchy,
(where "v" can be read as "directly derives"), with the
current and proposed levels for ArrowExpr/ArrowPostfix.

    CastExpr
      v             <- proposed position of ArrowExpr
    UnaryExpr
      v
    ValueExpr
      v
    SimpleMapExpr
      v
    PathExpr
      v
    RelativePathExpr
      v
    StepExpr
      v
    PostfixExpr    <- current level of ArrowPostfix

----

Here are some example queries that will be treated differently under
the status quo vs the proposed change.

Mike's examples above [in support of the proposed change] correspond to
examples "UnaryExpr", "PathExpr 2", and "SimpleMapExpr 2".

Perhaps the strongest argument against the proposed change would be based
on the last three examples ("PostfixExpr N"), in which a query such as
    $a=>f()[1]
would become a syntax error. Instead, you would have to write
    ($a=>f())[1]
to get the effect that the former query currently has.

(Note that where an example uses a VarRef, any other PrimaryExpr would do,
e.g. a FunctionCall or a ContextItemExpr, which might make the example
more realistic.)

---------------------------------------------------------------------------
UnaryExpr:

                         - $x =>f()

currently: equiv to      - ($x =>f())

proposed:  equiv to      (- $x) =>f()

---------------------------------------------------------------------------
ValueExpr -> ValidateExpr:

                        validate {Expr} =>f()

currently: syntax error

proposed:  equiv to     (validate {Expr}) =>f()

---------------------------------------------------------------------------
ValueExpr -> ExtensionExpr:

                        (#pragma#) {Expr} =>f()

currently: syntax error

proposed:  equiv to     ((#pragma#) {Expr}) =>f()

---------------------------------------------------------------------------
SimpleMapExpr 1:

                        $a =>f() ! $b =>g()

currently: equiv to     ($a =>f()) ! ($b =>g())

proposed:  syntax error

---------------------------------------------------------------------------
SimpleMapExpr 2:

                        $a ! $b =>f()

currently: equiv to     $a ! ($b =>f())

proposed:  equiv to     ($a ! $b) =>f()

---------------------------------------------------------------------------
SimpleMapExpr 3:

                        a/b ! c/d =>f()

currently: syntax error

proposed:  equiv to     (a/b ! c/d) =>f()

---------------------------------------------------------------------------
PathExpr 1:

                        / $a =>f()

currently: equiv to     / ($a =>f())

proposed:  equiv to     (/ $a) =>f()

---------------------------------------------------------------------------
PathExpr 2:

                        / a =>f()

currently: syntax error

proposed:  equiv to     (/ a) =>f()

---------------------------------------------------------------------------
RelativePathExpr 1:

                        $a =>f() / $b =>g()

currently: equiv to     ($a =>f()) / ($b =>g())

proposed:  syntax error

---------------------------------------------------------------------------
RelativePathExpr 2:

                        $a / $b =>g()

currently: equiv to     $a / ($b =>g())

proposed:  equiv to     ($a / $b) =>g()

---------------------------------------------------------------------------
RelativePathExpr 3:

                        a / b =>g()

currently: syntax error

proposed:  equiv to     (a / b) =>g()

---------------------------------------------------------------------------
StepExpr -> AxisStep:

                        child:a[1] =>f()

currently: syntax error

proposed:  equiv to     (child:a[1]) =>f()

---------------------------------------------------------------------------
PostfixExpr 1:

                        $a =>f() [1]

currently: equiv to     ($a =>f()) [1]

proposed:  syntax error

---------------------------------------------------------------------------
PostfixExpr 2:

                        $a =>f() ("arg")

currently: equiv to     ($a =>f()) ("arg")

proposed:  syntax error

---------------------------------------------------------------------------
PostfixExpr 3:

                        $a =>f() ?key

currently: equiv to     ($a =>f()) ?key

proposed:  syntax error

---------------------------------------------------------------------------
Comment 10 Jonathan Robie 2015-01-13 16:52:11 UTC
The Working Group agreed to this change.
Comment 11 Michael Kay 2015-07-06 08:54:09 UTC
The change has not yet been applied to the specification.
Comment 12 Josh Spiegel 2015-07-07 16:05:31 UTC
I think it is now.