- From: Erik Bruchez <erik@bruchez.org>
 - Date: Wed, 14 Mar 2012 10:01:21 -0700
 - To: public-forms@w3.org
 
All,
I dug up some emails and found Mike's reply in November 2009 on the topic:
"I would recommend, if you want to keep things simple, only allowing
xforms:sequence [as opposed to also supporting xforms:value-of]. Or
naming it xforms:return - that's what it was in XSLT until we
generalized it to allow sequence constructors, and in many ways I
regret changing it."
That sounds like a good suggestion to me, assuming we are going to
support an element to specify the result.
Now I am wondering if we can do away with nested elements altogether.
I would like to see things like this, based on the examples in [1]:
Example 1:
<function signature="my:sum($p as xs:integer, $q as xs:integer) as xs:integer">
    $p + $q
</function>
Or, using @value:
<function signature="my:sum($p as xs:integer, $q as xs:integer) as
xs:integer" value="$p + $q"/>
Example 2 (XPath 3):
<function signature="dollar-round($num as xs:decimal) as xs:string">
    let $num100str := string(round($num * 100)),
        $trunc := substring-before($num100str, '.'),
        $intpart = substring($trunc, 0, string-length($trunc)-2),
        $fracpart = substring($trunc, string-length($intpart), 2)
    return concat($intpart, '.', $fracpart)
</function>
(I am sure you can write that function better in XPath 2 or XPath 3 BTW!)
@value can also be used here, but it's a bit more clumsy visually.
Example 3:
<function signature="my:sumproduct($p as node()*, $q as node()*) as xs:double">
   sum(for $i in 1 to count($p) return $p[$i] * $q[$i])
</function>
or:
<function signature="my:sumproduct($p as node()*, $q as node()*) as xs:double"
    value="sum(for $i in 1 to count($p) return $p[$i] * $q[$i])"/>
This would work well for JavaScript too:
Example 1 (JavaScript):
<function signature="my:sum($p as xs:integer, $q as xs:integer) as
xs:integer" type="javascript>
    return p + q
</function>
<function signature="dollar-round($num as xs:decimal) as xs:string"
type="javascript>
    var num100str = ...
    var trunc = ...
    var intpart = ...
    var fracpart = ...
    return intpart + "." + fracpart
</function>
etc.
Now unfortunately in XPath 2 we can't use `let`, but maybe we can
still get away with the <sequence> or <return> element:
<function signature="dollar-round($num as xs:decimal) as xs:string">
    <var name="num100str" value="string(round($num * 100))"/>
    <var name="trunc" value="substring-before($num100str, '.')"/>
    <var name="intpart" value="substring($trunc, 0, string-length($trunc)-2)"/>
    <var name="fracpart" value="substring($trunc, string-length($intpart), 2)"/>
    concat($intpart, '.', $fracpart)
</function>
This allows functions that don't need variables in XPath 2 to keep the
return value as an expression within the body of the <function>
element, while still providing help to the poort XPath 2 or XPath 1
users that want to use variables.
Alternatively, we could completely get rid of the nested <var>
element. This would mostly impact XPath 1 and XPath 2 implementations,
with the idea that implementations would tend to migrate to XPath 3 as
soon as possible anyway.
So to summarize some ideas above:
1. We should consider using <return> instead of <sequence> if we do
decide to use an element for return values.
2. However, we should consider *not* using an element for return values at all.
3. We should consider allowing function bodies simply as the content
of <function>.
4. We should also support a shorthand with the @value attribute.
5. We might consider dropping support for nested <var> within
<function> (not so sure about this one).
Food for thoughts.
-Erik
[1] http://www.w3.org/MarkUp/Forms/wiki/Custom_XPath_functions
Received on Wednesday, 14 March 2012 17:02:14 UTC