Hello Mark,<br><br>I've been thinking about this, on and off, for 5 days now, and I still<br>fail to see the benefits. Perhaps there are more convincing use cases<br>than those in your original mail?<br><br>Notice that the "for" scope now contains two kinds of bindings: one that<br>
is strictly local to for(...) (bi below) and another one that must be exported<br>such as the binding $s in<br><br> for( bi : BasketItem( customer == $c ); $s = sum( $bi.price); )<br><br>This will be confusing.<br><br><br>
I fail to see the usefulness of filter() in<br><br> for( $b2 : BasketItem( customer == $c ); filter( $b2, $b2.price > 100) )<br><br>where one can better (and perhaps even more efficiently) write<br><br> for( $b2 : BasketItem( customer == $c, price > 100) )<br>
<br>I don't understand what this construct should achieve:<br><br> $r = $bi | map( $, $.price * 2) | filter( $, $.price < 100);<br><br>Given that $bi iterates over BasketItem objects, the first map would create<br>
a numeric value by doubling $bi.price, so I suppose the next pipeline transmits<br>numbers so that filtering applies to - what? java.lang.Number? Then it can't be<br>$.price; it could be $.floatValue or similar. But again: the entire selection<br>
could be written as a constraint of the BaskerItem pattern. Creating a<br>collection just for determining a count isn't straightforward.<br><br>The idea of accumulate is to produce a scalar result from processing a<br>
collection of facts. It would indeed be useful to extend this so that a result<br>tuple can be constructed. But this could be achieved by a complex<br>accumulate function that returns an object with multiple fields;<br>in fact, min/max/count/avg/sum can be wrapped into a single function<br>
"stats" returning an object of class "Statistics" with appropriate fields.<br>Any filtering on the result can be written as a constraint on that<br>temporary fact pattern of type Statistics, e.g.:<br><br>
Statistics( $min: min, $max: max )<br> from accumulate( $bi: BasketItem( $p: price ) stats( $p ) )<br><br>All that remains is the syntactic sugar that's provided by <br> x in [0..4]<br> y in [0..4]<br> $c : Cell( row == y, col == x );<br>
as a on-the-fly pattern for selecting other patterns. Again, this could be<br>written more concisely as<br> $c : Cell( row >= 0 && <= 4, col >= 0 && <= 4 )<br>and a (minor) extension such as a set expression might simplify this:<br>
$c : Cell( row in [0..4], col in [0,1,2,3,4] )<br><br>Regards<br>Wolfgang<br><br><div class="gmail_quote">On 26 October 2010 01:36, Mark Proctor <span dir="ltr"><<a href="mailto:mproctor@codehaus.org" target="_blank">mproctor@codehaus.org</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">We are thinking of moving "accumulate" to a simple "for" keyword. We<br>
might allow 'in' and 'from' to be used interchangably and allow ';' semi<br>
colons to separate the sections. I'm also wondering ho we could allow<br>
function pipelines for the function part of the element. We also need<br>
type inference and "default" return values.<br>
<br>
So here are some code snippets to show what I'm thinking, as<br>
improvements over what we do with accumulate now.<br>
<br>
// Simple 'or' very simlar to accumulate before. ; for section<br>
separating. With a new boolean section at the end to decide whether to<br>
propagate or not. Will probably use '=' for function assignments.<br>
$c : Customer()<br>
for( $bi : BasketItem( customer == $c );<br>
$s = sum( $bi.price);<br>
$s > 100 )<br>
<br>
// Multiple functions are ofcourse allowed<br>
$c : Customer()<br>
for( $bi : BasketItem( customer == $c );<br>
$mn =min( $bi.price),<br>
$mx = max( $bi.price); )<br>
<br>
// As are multiple patterns, and as before patterns can come 'from' an<br>
expression and with type inference we can get some nice compact text:<br>
for ( x in [0..4]<br>
y in [0..4]<br>
$c : Cell( row == y, col == x );<br>
$avg = avg( $cell.value );<br>
$avg > 100 )<br>
<br>
The above is possible now with the following:<br>
Integer( this > 100) from<br>
accumulate( x : Integer() from [0, 1, 2, 3, 4]<br>
y : Integer() from [0, 1, 2, 3, 4],<br>
$c : Cell( row == y, col == x ),<br>
avg( $c.value) )<br>
<br>
I think the proposed additions reall help with declarative readability.<br>
<br>
The normal chaining of elements is supported:<br>
$c : Customer()<br>
for( $b1 : BasketItem() in<br>
for( $b2 : BasketItem( customer == $c );<br>
filter( $b2, $b2.price > 100); );<br>
$a = avg( $b1.price ); )<br>
<br>
'for' will have a default return type for each bound function. In this<br>
case it returns a single value $a, if there are multiple bound results<br>
an array/map must be used for access.<br>
<br>
I also think we should allow pipelineing of functions, much as you would<br>
do in a normal functional programming, possibly using haskell like<br>
"stream fusion" capable functions.<br>
<br>
// '$' refers to the magic contents of the function which is "piped" in.<br>
So $bi is piped to map, $ refers to each value evaluated in the<br>
function, with type inference. 'map' results are piped to 'filter'. The<br>
final results are assigned to $r.<br>
$c : Customer()<br>
for( $bi : BasketItem( customer == $c );<br>
$r = $bi | map( $, $.price * 2) |<br>
filter( $, $.price < 100);<br>
$r.size > 100 )<br>
<br>
More ideas welcome :) But I think this opens up some very interesting<br>
areas for DRL, with something that will hopefully feel more natural for<br>
developers.<br>
<br>
Mark<br>
<br>
_______________________________________________<br>
rules-dev mailing list<br>
<a href="mailto:rules-dev@lists.jboss.org" target="_blank">rules-dev@lists.jboss.org</a><br>
<a href="https://lists.jboss.org/mailman/listinfo/rules-dev" target="_blank">https://lists.jboss.org/mailman/listinfo/rules-dev</a><br>
</blockquote></div><br>