<br><br>On Tuesday, 3 September 2013, PJ Eby wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On Sun, Sep 1, 2013 at 4:07 PM, Sébastien de Menten <<a href="javascript:;" onclick="_e(event, 'cvml', 'sdementen@gmail.com')">sdementen@gmail.com</a>> wrote:<br>
> @abstract<br>
> def foo(a,b):<br>
> pass<br>
> foo.when = lambda condition: when(foo, condition) #<== this could be<br>
> better implemented in the abstract decorator<br>
<br>
Better still might be to implement @when() and other such APIs as<br>
macros that transform just the second argument; that way your code<br>
would not need the extra "s" function. Still, it's definitely a way<br>
around the IDE issues, and doesn't suffer from the usual issues of<br>
access to source code (I assume, anyway).<br>
<br></blockquote><div>Indeed, good idea ! </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
> For my second question, explaining the real domain space would need pages so<br>
> I must find a 'to-the-point" analogy that captures the gist of the problem.<br>
> So here is one that does not use domain-specific terms but maps 100% with<br>
> the problem.<br>
> I have different kind of cars (pickup, sedans, convertible, etc) which have<br>
> different transmissions (4x4, traction, propulsion) and different tires (all<br>
> season, snow, high performance, etc) and all combinations of Car x<br>
> Transmission x Tires are possible.<br>
> Now the generic functions I want to write are like :<br>
> - "optimal_acceleration(car, weather)"<br>
> - "maintenance_planning(car)"<br>
> - "customer_match(car, customer_profile)"<br>
> These functions may depend on the Car(Transmission, Tire) combination and<br>
> while all may not be supported, I want to be able to add support for any of<br>
> them. Moreover, if a user adds a new kind of transmission, or car, or tire,<br>
> I want to be able to add the functions for these new combinations (if they<br>
> make sense ... otherwise, an exception NoApplicableMethods is perfect !<br>
<br>
Sounds just like what PEAK-Rules is intended for.<br>
<br>
One thing you might want to watch out for in de-structuring rules like<br>
this (ones that depend on attributes of a parameter), is to remember<br>
that PEAK-Rules generally applies tests to parameters before testing<br>
attributes. This doesn't affect rule *precedence* (as far as what's<br>
most specific), but it does affect *evaluation order*.<br>
<br>
For example, if all your rules for a given function read in this order:<br>
<br>
isinstance(car.tires, Foo) and isinstance(car.transmission, Bar)<br>
<br>
That is, if they all check the tires before checking the transmission,<br>
then PEAK-Rules will conservatively assume that it's not safe to<br>
access the transmission attribute until after the tires are checked.<br>
This limits the shapes that the dispatch tree will be built in, even<br>
though it doesn't affect the answers given. Under some circumstances,<br>
this might create larger or slower dispatch trees.<br>
<br>
In contrast, tests based directly on parameters are assumed to be<br>
independent of each other (e.g. "param1>1 and param2>2" is assumed to<br>
allow checking either condition first) and so can be used at any level<br>
of the dispatch tree, and so the builder is free to use whatever shape<br>
works best for that subtree (at a cost of a little more setup time to<br>
decide which shape is best.)<br>
<br>
I guess what I'm trying to say is that if you have a relatively flat<br>
rule structure, based mainly on car, car.tires, and car.transmission,<br>
you may find it useful to make the tires and transmissions direct<br>
parameters, or else to deliberately vary the order they appear in your<br>
rules, so that the rule system will have maximum freedom to construct<br>
dispatch trees.<br>
<br>
I wouldn't even bother to mention this, except that from your<br>
description I don't have any way to know just how complex your<br>
dispatch trees will be. In general, I find that generic functions<br>
tend to follow one of two patterns:<br>
<br>
1. "Registry" functions -- not heavily dependent on predicates, more<br>
dependent on types of a few key parameters, relatively simple rules<br>
with occasional extra criteria<br>
2. "Pattern matching" or "compiler" functions -- while one or two<br>
parameter types may be involved, the bulk of the rules are predicates,<br>
often deeply nested predicates on component objects; often found in<br>
compilers or compiler-like systems (such as PEAK-Rules itself) to<br>
pattern-match subtrees with complex conditions.<br>
<br>
In pattern #2, evaluation order may be rather important, but the tree<br>
size is fairly limited by the fact that most of the actual predicates<br>
exist for only a few rules. In pattern #1, the bulk of the indexing<br>
is for that handful of parameters, so as long as they're<br>
freely-orderable (i.e., can be tested independently), you can't get a<br>
blowup of tree size. (And in pattern #1, the tests are usually done<br>
directly on the parameters, not on attributes or methods or formulas<br>
using the parameters.)<br>
<br>
>From your vague description, I can't tell if your use case is more<br>
like #1 or #2, or some sort of hybrid. If it's basically #1 but using<br>
lots of independent attribute-level checks, and you have very large<br>
rulesets, then you may want to promote the attributes to parameters<br>
(or access those attributes in different order some of the time), in<br>
order to allow PEAK-Rules full tree reordering freedom. It will not<br>
affect the answers you get, only memory usage (and possibly speed).<br>
Even then, it's unlikely to do it in the kinds of uses I'm familiar<br>
with, but since I'm not familiar with your case, I am being<br>
extra-thorough and cautious. ;-)<br>
</blockquote><div>It is definitely more the #2 (pattern matching). Is there some introspection ability on the decision tree PEAK-rules build ? Otherwise, i'll check first the overhead to see if it is penalising or not before optimising. </div>
<div>Thank you for you detailed description of these mechanisms !<span></span></div>