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

S

Steve Howell

In my rewritten code, here is the smell:
    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!')
There is nothing wrong with the code taken out of context, but one of
the first things that lexical duplication should alert you to is the
fact that you are creating code that is brittle to extension.

Really? It is very simple to extend it by adding another key:item to the
dict.

Easy for me to extend, of course, since I wrote the code. It's the
maintainers I am worried about. I can make their lives easier, of
course, by changing the text of the exception to say something like
this:

"Silly maintenance programmer, you now have to update the dispatch
table!"

I have no problem with that.

It gets worse -- the reference to the in operator is in a completely
different module to the implementation of the in operator, which may be
in a completely different language! (C in this case.)

I'm being sarcastic, of course, but I do have a serious point. I'm not
impressed by complaints that the definition of the function is oh-so-very-
far-away from where you use it. Well duh, that's one of the reasons we
have functions, so they can be used anywhere, not just where they're
defined.

The slippery slope here is that every block of code that you ever
write should be extracted out into a method. Now I am all in favor of
tiny methods, but the whole point of if/elif/elif/elif/elif/end code
is that you are actually calling out to the maintenance programmer
that this code is only applicable in certain conditions. That's why
"if" statements are called "conditionals"! You are actually telling
the maintenance programmer that is only sensible to use these
statements under these conditions. It is actually extremely explicit.

Now I'm being sarcastic too, but I also have a serious point. Nine
times out of ten if/elif/elif/end calls out the smell of spaghetti
code. But it can also occasionally be a false negative. It can be a
case of avoiding premature abstraction and indirection.
 
M

Michael Torrie

Steven said:
But you're right, the convention of using verbs for functions isn't as
strong as the convention of using nouns for classes and types.

The idea that functions should be verbs is plain wrong, coming from the
traditional world of functional programming. Since functions should
never have any side effects, ideally, they don't ever "do" anything to
something. Rather they return a result. I suppose if you were in a
language that had statements, that they could be the verbs.

One could argue that _methods_ should be verbs (which obviously doesn't
apply to Java and their over use of patterns to compensate for a weak
language) since methods are the means by which change to an object can
be effected.
 
M

Michael Torrie

Steve said:
Is there any particular reason why this might be a *bad* language-
design idea?

Syntactically, using braces, begin/end blocks, python white space, and
your if/elif/then/endif structures, amounts to the same thing; they are
all equivalent. Thus from a language pov, there's no compelling reason
to do one over the other.

One good reason to avoid the if/elif/then/endif syntax and its related
friends in a language (while/wend, do/loop, for/next) is that they
require parser support for what amounts to three or four versions of
precisely the same construct: the block. Thus from a parser or compiler
point of view, it's far better and easier to have blocks begin and end
with something that is consistent and recognizable without a lot of
look-ahead or context.

I once started to write a parser for the QuickBasic language but found
very quickly that the grammar required a fair amount of token
look-ahead. For example, if I found the token "End", I had to look at
least one token ahead to find out if this was an "end if" or just an
"end." Also "end" could, if I recall, have an optional number parameter
that would set the exit errorlevel code. Certainly QuickBasic was not
context-free and was not LL(1).

I'm not sure, but Python's grammar is LL(1) I think, and probably darn
close to context-free.
 
R

Robert Kern

I'm not sure, but Python's grammar is LL(1) I think, and probably darn
close to context-free.

It is LL(1) after some non-formal postprocessing of the tokens to properly
handle the indentation.

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco
 
J

James Harris

Syntactically, using braces, begin/end blocks, python white space, and
your if/elif/then/endif structures, amounts to the same thing; they are
all equivalent.  Thus from a language pov, there's no compelling reason
to do one over the other.

One good reason to avoid the if/elif/then/endif syntax and its related
friends in a language (while/wend, do/loop, for/next) is that they
require parser support for what amounts to three or four versions of
precisely the same construct: the block.  Thus from a parser or compiler
point of view, it's far better and easier to have blocks begin and end
with something that is consistent and recognizable without a lot of
look-ahead or context.

I'm not disagreeing with the above paragraph but in the interests of
even handedness an advantage of the other method is ease for a human
to match begins and ends of large blocks. With statement or block
brackets such as "begin" ... "end" (Pascal) and "{" ... "}" (C)
because they are all the same it can be hard to see where each
construct ends. C programmers sometimes write

} /* for */
} /* while */

or similar to indicate which construct the terminating brace is
closing.
I once started to write a parser for the QuickBasic language but found
very quickly that the grammar required a fair amount of token
look-ahead.  For example, if I found the token "End", I had to look at
least one token ahead to find out if this was an "end if" or just an
"end."  Also "end" could, if I recall, have an optional number parameter
that would set the exit errorlevel code.  Certainly QuickBasic was not
context-free and was not LL(1).

I'm not sure, but Python's grammar is LL(1) I think, and probably darn
close to context-free.

James
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top