Language mavens: Is there a programming with "if then else ENDIF" syntax?
Steve Howell
showell30 at yahoo.com
Wed Nov 18 05:06:49 EST 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