- From: <bugzilla@jessica.w3.org>
- Date: Fri, 18 Dec 2015 01:26:20 +0000
- To: public-qt-comments@w3.org
https://www.w3.org/Bugs/Public/show_bug.cgi?id=29346 Bug ID: 29346 Summary: [XP31] XPath-style currying, or the arrow operator, may require a bit more specification Product: XPath / XQuery / XSLT Version: Candidate Recommendation Hardware: PC OS: Windows NT Status: NEW Severity: normal Priority: P2 Component: XPath 3.1 Assignee: jonathan.robie@gmail.com Reporter: abel.braaksma@xs4all.nl QA Contact: public-qt-comments@w3.org Target Milestone: --- Today's discussion with Christian GrĂ¼n and Florent Georges (see https://lists.w3.org/Archives/Public/public-xsl-query/2015Dec/0028.html etc) led me to writing this bug, it seems that the production rules and their explanation of the current consensus, plus the text in this part of the spec are not entirely in line. This applies to 3.22 Arrow operator (=>) of the internal WD (CR). The production rules are as follows: ArrowExpr ::= UnaryExpr ( "=>" ArrowFunctionSpecifier ArgumentList )* ArrowFunctionSpecifier ::= EQName | VarRef | ParenthesizedExpr The mandatory part of the spec in this section says: <quote> [Definition: An arrow operator applies a function to the value of a primary expression, 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($s), and $s=>f($j) is equivalent to f($s, $j). </quote> The (possible) issues: ---------------------- 1) The text says "and f() is a function", but f() can never be a function. It can be a function call, or a function call evaluating to a function. Suggestion, something like: "if ArrowFunctionSpecifier is either a function, a variable reference bound to a function or an expression evaluating to a function" 2) We don't specify what happens if this goes wrong. Maybe we don't need to, but I wonder what a => (concat#3)("b") would return. The spec suggests this is equivalent to (concat#3)(a, "b") but this will raise XPTY0004 (wrong no of args). Should we emphasize this can happen? Or will the returned value be a new function, with one argument, as in (concat#3)(a, "b", ?)? 3) Bug #26889 has some discussion that suggests placeholder-syntax cannot be used as the rhs. However, I believe the production rules, and the accompanying text leave room for a => (concat('b', ?)) being valid. Should it not be? I think it makes sense it is valid, but if it isn't, we should probably say so. I believe it is valid because a) we allow ParenthesizedExpr b) the rhs translates to a function taking one argument c) the equivalence-rule applies, turning this effectively in (concat('b', ?))(a), which is still legal. 4) The example in (3) is notably different from a => concat('b', ?), which translates to concat('a', 'b', ?). Still valid (returning a function item), but this difference is hard to spot and very subtle. While people have grown used to using parentheses to remove ambiguity of the comma operator, the difference between concat('b', ?) and (concat('b', ?)) is almost indiscernible. If my interpretation is correct, perhaps we could mention this as a Note? I believe this is valid because: a) the prod rules above use ArgumentList b) which allows for Argument between the "," c) which allows for either an ArgumentPlaceHolder or a SingleExpr 5) We don't mention the possible occurrence of the rhs. Considering the equivalence rules, it stands to reason that a) if rhs is empty sequence, an error is raised (cannot have empty seq. as target of a function call, XPTY0004) b) if rhs has more-than-one, an error is raised (cannot have more-than-one as target of a function call, XPTY0004) Though I wouldn't mind allowing something other than exactly-one, that's probably too much a change at CR stage (besides other idiosyncrasies this may raise) Not sure this point requires a change, other than perhaps pointing out that the same errors apply as for a (dynamic) function call, whichever applies. 6) The text calls upon the equivalence with normal function calls, but we don't allow NamedFunctionRef as an alternative in ArrowFunctionSpecifier, though with "normal" function calls it is allowed. For consistency, it seems appropriate to allow it (currently, it is allowed, but requires parentheses). This would make (a, b) => string-join#1() legal. Perhaps not a big win, but at least consistent and a small change. It is strange that (a, b) => (string-join#1)() is a required rewrite to make this expression valid. PS: I used "currying" in the title not because it is the same as currying in other functional languages (it is not), but because it does allow to return a partial applied function as the result of the arrow expression, which is "kind of" currying (except that, if you chain an operation that way using arrows, you need parentheses). -- You are receiving this mail because: You are the QA Contact for the bug.
Received on Friday, 18 December 2015 01:26:34 UTC