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

Steve Howell showell30 at yahoo.com
Wed Nov 18 11:06:49 CET 2009


On Nov 18, 1:32 am, Chris Rebert <c... at rebertia.com> wrote:
> On Wed, Nov 18, 2009 at 1:15 AM, Steve Howell <showel... 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.
>
> I'm gonna have to disagree and say using the dictionary dispatch
> technique would clean it up a good bit.
> Yes, it would entail creating several functions, but those functions
> could then be documented (vs. the currently opaque code blocks); and
> due to their separation and smaller length, they would be easier to
> understand and test than the given code.
> Additionally, the sheer length of the given code segment probably
> constitutes a code smell in and of itself for the function containing
> that code.
>


Here's the rewrite.  The indirection from the definition of _dict to
the first use of _dict is a little painful (36 lines away), but apart
from that I am pleased with how the new code looks, so your points are
well taken:

    kind = ast.kind
    def _dict(ast):
        return dictionary(ast, metavar)

    def _list(ast):
        ignore, code = dictionary(ast, 'item')
        code = '[%s for item in %s]' % (code, metavar)
        return label, code

    def _attr(ast):
        return ast.field, '%s.%s' % (metavar, ast.field)

    def _key(ast):
        return ast.field, '%s[%s]' % (metavar, repr(ast.field))

    def _as(ast):
        ignore, parent = _code_generate(ast.parent, metavar)
        return ast.synonym, parent

    def _call(ast):
        parent_name, parent = _code_generate(ast.parent, metavar)
        parent += '()'
        return parent_name, parent

    def _recurse(ast):
        parent = ast.parent
        expr = ast.expr
        parent_name, parent = _code_generate(parent, metavar)
        kind = expr.kind
        if kind in ['attr', 'key', 'list']:
            parent_name, parent = _code_generate(expr, parent,
parent_name)
        else:
            subparent_name, subparent = _code_generate(expr,
parent_name)
            parent = '(lambda %s:\n' % parent_name + indent_block
(subparent+')(%s)' % parent)
        return parent_name, parent

    dispatches = {
            'dict': _dict,
            'list': _list,
            'attr': _attr,
            'key': _key,
            'as': _as,
            'call': _call,
            'recurse': _recurse,
            }
    if kind in dispatches:
        return dispatches[kind](ast)
    else:
        raise Exception('unknown kind!')

Thanks!

P.S. The underscores before the method names might look a little funny
for inner methods, but it's the nature of the code..._dict and _list
would lead to confusion with builtins, if not actual conflict.



More information about the Python-list mailing list