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