On Thu, Aug 18, 2016 at 2:47 PM, Marko Rauhamaa <ma...@pacujo.net> wrote: > Lawrence D’Oliveiro <lawrenced...@gmail.com>: > >> Solution: set up a table of rules > > Without judging the individual merits of rules for your use case, I just > want to mention that as a rule, I dislike rules. Rule languages tend to > grow out of all bounds, always remain deficient and have impenetrable, > ad-hoc semantics.
So you'd be with the Queen Elsa in singing "Doğru yanliş, bir kural yok"? (I figure this song's famous enough that you probably know what I mean even without seeing it in English.) Rule-based code adds a level of abstraction above raw code. Thing is, though, I actually have no idea about the merits of this exact example, because (a) the actual rules don't seem to be there, and (b) there's a lot of guff in the code that makes it very hard to skim. (I include the "#end if" lines as guff. They're nothing but distraction, plus a good chance at mismatching stuff when you edit. Here's how *I* would do this kind of problem. > Problem: let the user specify certain parameters for a screen display (width, > height, diagonal, pixel density, pixels across, pixels down, optimum viewing > distance) and from the ones specified, work out the parameters which were not > specified. > For each parameter, define zero or more sets of parameters from which it can be calculated. Then iterate over the parameters you don't have, iterate over the sets, and when you find one that's <= the parameters you have, call the corresponding function. It's a variant of a rule-based solution, where the rules are functions tagged with a decorator. parameters = defaultdict(dict) def param(func): target = func.__name__ source = func.__code__.co_varnames[:func.__code__.co_argcount] parameters[target][frozenset(source)] = func return func @param def width(height, diagonal): """Calculate the width from the height and diagonal""" # Probably the wrong way to calculate this but whatev, this is an example return diagonal*diagonal - height*height @param def width(pixel_density, pixels_across): return pixels_across / pixel_density @param def diagonal(height, width): return math.hypot(height, width) # ... etc etc etc def make_display(**args): for kwd, sources in parameters.items(): if kwd in args: continue for source, func in sources.items(): if source <= set(args): args[kwd] = func(**{arg:args[arg] for arg in source}) break else: # TODO: Queue this for retry down below, or something if set(args) <= set(parameters): raise InsufficientInformation This is a variant of data-driven code. The work is broken out into individual functions whose names and parameters are used to create the lookups. Then the actual searching is fairly compact (and could be done better than this, too). You may notice that very little of this code is actually aware of specific parameter names - only the formula functions themselves. Everything else is completely generic. (There may be bugs in the above code. It's completely untested. Correction: The above code is completely untested, therefore there are definitely bugs in it.) ChrisA PS. "No right, no wrong, no rules for me". -- https://mail.python.org/mailman/listinfo/python-list