Re: Some thoughts on function bodies and <sequence>

All,

It would be better to avoid creating our own syntax if at all possible.
Between XML and XPath, we have a lot of grammar to choose from already 
without having to write our own parser.
Whether browser-based or java-based, sticking to XML and XPath would 
produce a much better chance that much of the processing can be expressed 
in terms of existing functionality.

Cheers,
John M. Boyer, Ph.D.
Distinguished Engineer, IBM Forms and Smarter Web Applications
IBM Canada Software Lab, Victoria
E-Mail: boyerj@ca.ibm.com 

Twitter: http://twitter.com/johnboyerphd
Blog: http://www.ibm.com/developerworks/blogs/page/JohnBoyer
Blog RSS feed: 
http://www.ibm.com/developerworks/blogs/rss/JohnBoyer?flavor=rssdw





From:   Erik Bruchez <erik@bruchez.org>
To:     public-forms@w3.org
Date:   14/03/2012 10:03 AM
Subject:        Some thoughts on function bodies and <sequence>
Sent by:        ebruchez@gmail.com



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:41:43 UTC