Language mavens: Is there a programming with "if then else ENDIF" syntax?
Simon Forman
sajmikins at gmail.com
Wed Nov 18 15:10:25 EST 2009
On Wed, Nov 18, 2009 at 4:15 AM, Steve Howell <showell30 at 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.
More information about the Python-list
mailing list