Language mavens: Is there a programming with "if then else ENDIF" syntax?

Simon Forman sajmikins at
Wed Nov 18 21:10:25 CET 2009

On Wed, Nov 18, 2009 at 4:15 AM, Steve Howell <showell30 at> 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):
            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)

            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