On Wed, Nov 18, 2009 at 4:15 AM, Steve Howell <showel...@yahoo.com> wrote: > On the topic of "switch" statements and even-more-concise-then-we-have- > already if/elif/else/end constructs, I have to say that Python does > occasionally force you to write code like the code below. Maybe > "force" is too strong a word, but Python lends itself to if/elif > blocks like below, which get the job done just fine, but which are not > syntactically pretty, due to the "(el){0,1}if kind ==" duplication. > There are often cases where if/elif statements are just a smell that > you do not know how to do dictionary lookups, but if you converted the > below code to use dictionary lookups, you would complicate the code > almost as much as you abstracted the code, if not more, unless I am > just being very naive. Anonymous methods would help to a certain > degree. I am not saying I want either anonymous methods or switch > statements, but the lack of either in a language leads to very > procedural looking code when you use number-of-lines-of-code as a > (possibly dubious) metric. > > Maybe this excerpt can be golfed down to something simpler, I would > love to see it! > > if kind == 'dict': > return dictionary_schema(ast) > elif kind == 'list': > method = dictionary_schema(ast) > return lambda lst: map(method, lst) > elif kind == 'attr': > return ((lambda obj: getattr(obj, ast.field)), ast.field) > elif kind == 'key': > return (lambda obj: obj.get(ast.field), ast.field) > elif kind == 'as': > method, old_name = schema(ast.parent) > return (method, ast.synonym) > elif kind == 'call': > method, old_name = schema(ast.parent) > def call(obj): > return method(obj)() > return (call, old_name) > elif kind == 'recurse': > expr = ast.expr > kind = expr.kind > method, field_name = schema(ast.parent) > if kind in ['attr', 'key']: > new_method, new_field_name = schema(expr) > field_name = new_field_name > elif kind in ['dict', 'list']: > new_method = schema(expr) > else: > raise Exception('unknown kind!') > def recurse(obj): > obj = method(obj) > return new_method(obj) > return (recurse, field_name) > else: > raise Exception('unknown kind!')
This code is perhaps not a great example of your point. Every "(el){0,1}if" clause (other than the ones in the 'recurse' branch) end in return statements, so the "el's" are pointless. FWIW I might write it like so: class ASTthing: def processAST(self, ast, kind): try: method = getattr(self, 'do_' + kind) except AttributeError: raise Exception('unknown kind!') self.ast = ast return method() def do_dict(self): return dictionary_schema(self.ast) def do_list(self): method = dictionary_schema(self.ast) return lambda lst: map(method, lst) def do_attr(self): field_name = self.ast.field return lambda obj: getattr(obj, field_name), field_name def do_key(self): field_name = self.ast.field return lambda obj: obj.get(field_name), field_name def do_as(self): method, old_name = schema(self.ast.parent) return method, self.ast.synonym def do_call(self): method, old_name = schema(self.ast.parent) return lambda obj: method(obj)(), old_name def do_recurse(self): expr = self.ast.expr kind = expr.kind method, field_name = schema(self.ast.parent) if kind in 'attrkey': new_method, field_name = schema(expr) elif kind in 'dictlist': new_method = schema(expr) else: raise Exception('unknown kind!') def recurse(obj): obj = method(obj) return new_method(obj) return recurse, field_name IMO, that's more pythonic and less complicated. -- http://mail.python.org/mailman/listinfo/python-list