FAQ
This is a question for the language mavens that I know hang out here.
It is not Python related, except that recent comparisons of Python to
Google's new Go language brought it to mind.

NOTE that this is *not* a suggestion to change Python. I like Python
just the way it is. I'm just curious about language design.

For a long time I've wondered why languages still use blocks
(delimited by do/end, begin/end, { } , etc.) in ifThenElse statements.

I've often thought that a language with this kind of block-free syntax
would be nice and intuitive:

if <condition> then
do stuff
elif <condition> then
do stuff
else
do stuff
endif

Note that you do not need block delimiters.

Obviously, you could make a more Pythonesque syntax by using a colon
rather then "then" for the condition terminator. You could make it
more PL/I-like by using "do", etc.

You can write shell scripts using if ... fi, but other than that I
don't recall a language with this kind of syntax.

Does anybody know a language with this kind of syntax for
ifThenElseEndif?

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

Search Discussions

  • Robin Becker at Nov 16, 2009 at 5:03 pm
    Steve Ferg wrote:
    .........
    if <condition> then
    do stuff
    elif <condition> then
    do stuff
    else
    do stuff
    endif

    Note that you do not need block delimiters.

    Obviously, you could make a more Pythonesque syntax by using a colon
    rather then "then" for the condition terminator. You could make it
    more PL/I-like by using "do", etc.

    You can write shell scripts using if ... fi, but other than that I
    don't recall a language with this kind of syntax.

    Does anybody know a language with this kind of syntax for
    ifThenElseEndif?
    .......

    modern sh seems to use this with "fi" as endif eg

    ~:
    $ if true; then
    echo true
    elif false; then
    echo false
    else
    echo hostile logic
    fi
    true
    ~:
    $

    --
    Robin Becker
  • Robin Becker at Nov 16, 2009 at 5:42 pm
    Robin Becker wrote:
    .......
    modern sh seems to use this with "fi" as endif eg

    ~:
    $ if true; then
    echo true
    elif false; then
    echo false
    else
    echo hostile logic
    fi
    true
    ~:
    $
    I meant to say that since sh uses this construct it cannot be too bad as a
    language construct since the world is built with sh and bash and similar.

    Of course that's a bad argument since there's more cobol than everything else
    put together (allegedly).
    --
    Robin Becker
  • James Harris at Nov 16, 2009 at 5:09 pm

    On 16 Nov, 16:54, Steve Ferg wrote:
    This is a question for the language mavens that I know hang out here.
    It is not Python related, except that recent comparisons of Python to
    Google's new Go language brought it to mind.

    NOTE that this is *not* a suggestion to change Python. ?I like Python
    just the way it is. ?I'm just curious about language design.

    For a long time I've wondered why languages still use blocks
    (delimited by do/end, begin/end, { } , etc.) in ifThenElse statements.

    I've often thought that a language with this kind of block-free syntax
    would be nice and intuitive:

    ? ? if <condition> then
    ? ? ? ? do stuff
    ? ? elif <condition> then
    ? ? ? ? do stuff
    ? ? else
    ? ? ? ? do stuff
    ? ? endif

    Note that you do not need block delimiters.

    Obviously, you could make a more Pythonesque syntax by using a colon
    rather then "then" for the condition terminator. ?You could make it
    more PL/I-like by using "do", etc.

    You can write shell scripts using if ... fi, but other than that I
    don't recall a language with this kind of syntax.

    Does anybody know a language with this kind of syntax for
    ifThenElseEndif?

    Is there any particular reason why this might be a *bad* language-
    design idea?
    There are some. For example, Ada uses similar. See

    http://en.wikipedia.org/wiki/Ada_%28programming_language%29#Control_structures

    These other newsgroups may be of interest:

    comp.programming
    comp.lang.misc

    The latter is used by people designing programming languages where you
    can find knowledgeable comments aplenty.

    James
  • Adrian Cherry at Nov 16, 2009 at 5:16 pm
    Steve Ferg <steve.ferg.bitbucket at gmail.com> wrote in
    news:ff92db5b-9cb0-4a72-b339-2c5ac02fbad0 at p36g2000vbn.googlegro
    ups.com:
    This is a question for the language mavens that I know hang
    out here. It is not Python related, except that recent
    comparisons of Python to Google's new Go language brought it
    to mind.

    NOTE that this is *not* a suggestion to change Python. I
    like Python just the way it is. I'm just curious about
    language design.

    For a long time I've wondered why languages still use blocks
    (delimited by do/end, begin/end, { } , etc.) in ifThenElse
    statements.

    I've often thought that a language with this kind of
    block-free syntax would be nice and intuitive:

    if <condition> then
    do stuff
    elif <condition> then
    do stuff
    else
    do stuff
    endif

    Note that you do not need block delimiters.

    Obviously, you could make a more Pythonesque syntax by using
    a colon rather then "then" for the condition terminator.
    You could make it more PL/I-like by using "do", etc.

    You can write shell scripts using if ... fi, but other than
    that I don't recall a language with this kind of syntax.

    Does anybody know a language with this kind of syntax for
    ifThenElseEndif?

    Is there any particular reason why this might be a *bad*
    language- design idea?
    I believe MATLAB has similar if syntax - please correct me if I'm
    wrong.

    From

    http://www.mathworks.com/access/helpdesk/help/techdoc/ref/if.html

    "The if function can be used alone or with the else and elseif
    functions. When using elseif and/or else within an if statement,
    the general form of the statement is"

    if expression1
    statements1
    elseif expression2
    statements2
    else
    statements3
    end


    Adrian
  • MRAB at Nov 16, 2009 at 5:39 pm

    Steve Ferg wrote:
    This is a question for the language mavens that I know hang out here.
    It is not Python related, except that recent comparisons of Python to
    Google's new Go language brought it to mind.

    NOTE that this is *not* a suggestion to change Python. I like Python
    just the way it is. I'm just curious about language design.

    For a long time I've wondered why languages still use blocks
    (delimited by do/end, begin/end, { } , etc.) in ifThenElse statements.

    I've often thought that a language with this kind of block-free syntax
    would be nice and intuitive:

    if <condition> then
    do stuff
    elif <condition> then
    do stuff
    else
    do stuff
    endif

    Note that you do not need block delimiters.

    Obviously, you could make a more Pythonesque syntax by using a colon
    rather then "then" for the condition terminator. You could make it
    more PL/I-like by using "do", etc.

    You can write shell scripts using if ... fi, but other than that I
    don't recall a language with this kind of syntax.

    Does anybody know a language with this kind of syntax for
    ifThenElseEndif?

    Is there any particular reason why this might be a *bad* language-
    design idea?
    Ada and Turing have:

    if <condition> then
    do stuff
    elsif <condition> then
    do stuff
    else
    do stuff
    end if

    Comal has:

    if <condition> then
    do stuff
    elif <condition> then
    do stuff
    else
    do stuff
    end if

    Modula-2 has:

    if <condition> then
    do stuff
    elsif <condition> then
    do stuff
    else
    do stuff
    end
  • Nobody at Nov 16, 2009 at 6:17 pm

    On Mon, 16 Nov 2009 08:54:28 -0800, Steve Ferg wrote:

    For a long time I've wondered why languages still use blocks
    (delimited by do/end, begin/end, { } , etc.) in ifThenElse statements.

    I've often thought that a language with this kind of block-free syntax
    would be nice and intuitive:

    if <condition> then
    do stuff
    elif <condition> then
    do stuff
    else
    do stuff
    endif

    Note that you do not need block delimiters.
    Does anybody know a language with this kind of syntax for
    ifThenElseEndif?
    BBC BASIC V had if/then/else/endif (it didn't have elif).

    "make" has if/else/else/endif (it doesn't have a dedicated elif, but
    "else if ..." behaves like elif rather than starting a nested "if").
    Is there any particular reason why this might be a *bad* language-
    design idea?
    Blocks can be useful for other reasons (e.g. limiting variable scope), so
    if you already have them, you don't need to provide dedicated blocks
    for control constructs.
  • MRAB at Nov 16, 2009 at 6:37 pm

    Nobody wrote:
    On Mon, 16 Nov 2009 08:54:28 -0800, Steve Ferg wrote:

    For a long time I've wondered why languages still use blocks
    (delimited by do/end, begin/end, { } , etc.) in ifThenElse statements.

    I've often thought that a language with this kind of block-free syntax
    would be nice and intuitive:

    if <condition> then
    do stuff
    elif <condition> then
    do stuff
    else
    do stuff
    endif

    Note that you do not need block delimiters.
    Does anybody know a language with this kind of syntax for
    ifThenElseEndif?
    BBC BASIC V had if/then/else/endif (it didn't have elif).
    I forgot about that one. :-(

    I used to do this in order if I wanted to avoid a lot of indentation:

    CASE TRUE OF
    WHEN <condition>
    do something
    WHEN <condition>
    do something
    OTHERWISE
    do something
    ENDCASE
    "make" has if/else/else/endif (it doesn't have a dedicated elif, but
    "else if ..." behaves like elif rather than starting a nested "if").
    Is there any particular reason why this might be a *bad* language-
    design idea?
    Blocks can be useful for other reasons (e.g. limiting variable scope), so
    if you already have them, you don't need to provide dedicated blocks
    for control constructs.
  • Chris Rebert at Nov 16, 2009 at 7:20 pm

    On Mon, Nov 16, 2009 at 8:54 AM, Steve Ferg wrote:
    This is a question for the language mavens that I know hang out here.
    It is not Python related, except that recent comparisons of Python to
    Google's new Go language brought it to mind.

    NOTE that this is *not* a suggestion to change Python. ?I like Python
    just the way it is. ?I'm just curious about language design.

    For a long time I've wondered why languages still use blocks
    (delimited by do/end, begin/end, { } , etc.) in ifThenElse statements.

    I've often thought that a language with this kind of block-free syntax
    would be nice and intuitive:

    ? ?if <condition> then
    ? ? ? ?do stuff
    ? ?elif <condition> then
    ? ? ? ?do stuff
    ? ?else
    ? ? ? ?do stuff
    ? ?endif

    Note that you do not need block delimiters. <snip>
    Does anybody know a language with this kind of syntax for
    ifThenElseEndif?
    Ruby:

    if count > 10
    puts "Try again"
    elsif tries == 3
    puts "You lose"
    else
    puts "Enter a number"
    end

    Cheers,
    Chris
  • R at Nov 16, 2009 at 8:11 pm

    On Nov 16, 10:54?am, Steve Ferg wrote:

    I've often thought that a language with this kind of block-free syntax
    would be nice and intuitive:

    ? ? if <condition> then
    ? ? ? ? do stuff
    ? ? elif <condition> then
    ? ? ? ? do stuff
    ? ? else
    ? ? ? ? do stuff
    ? ? endif
    WHY? Python's syntax is by far the most elegant of all, no need to
    show the end of a block. Python is the smartest kid on the block. And
    are you saying you would rather type "then" instead of ":" and "endif"
    instead of "\n"?

    No thanks!
  • Erik Max Francis at Nov 16, 2009 at 10:37 pm

    r wrote:
    On Nov 16, 10:54 am, Steve Ferg wrote:

    I've often thought that a language with this kind of block-free syntax
    would be nice and intuitive:

    if <condition> then
    do stuff
    elif <condition> then
    do stuff
    else
    do stuff
    endif
    WHY? Python's syntax is by far the most elegant of all, no need to
    show the end of a block. Python is the smartest kid on the block. And
    are you saying you would rather type "then" instead of ":" and "endif"
    instead of "\n"?

    No thanks!
    You clipped out the part where he explicitly said it was not a
    suggestion to change Python.

    --
    Erik Max Francis && max at alcyone.com && http://www.alcyone.com/max/
    San Jose, CA, USA && 37 18 N 121 57 W && AIM/Y!M/Skype erikmaxfrancis
    Mona Lisa / Come to discover / I am your daughter
    -- Lamya
  • Edward A. Falk at Nov 16, 2009 at 8:40 pm
    In article <ff92db5b-9cb0-4a72-b339-2c5ac02fbad0 at p36g2000vbn.googlegroups.com>,
    Steve Ferg wrote:
    I've often thought that a language with this kind of block-free syntax
    would be nice and intuitive:

    if <condition> then
    do stuff
    elif <condition> then
    do stuff
    else
    do stuff
    endif

    Note that you do not need block delimiters.
    "then", "else", and "endif" *are* the block delimiters

    --
    -Ed Falk, falk at despams.r.us.com
    http://thespamdiaries.blogspot.com/
  • Robert Kern at Nov 16, 2009 at 8:51 pm

    On 2009-11-16 14:40 PM, Edward A. Falk wrote:
    In article<ff92db5b-9cb0-4a72-b339-2c5ac02fbad0 at p36g2000vbn.googlegroups.com>,
    Steve Fergwrote:
    I've often thought that a language with this kind of block-free syntax
    would be nice and intuitive:

    if<condition> then
    do stuff
    elif<condition> then
    do stuff
    else
    do stuff
    endif

    Note that you do not need block delimiters.
    "then", "else", and "endif" *are* the block delimiters
    I think he meant that you don't need *extra* block delimiters or generic block
    delimiters like {}.

    --
    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
  • Barry W Brown at Nov 16, 2009 at 10:14 pm

    On Nov 16, 10:54?am, Steve Ferg wrote:
    This is a question for the language mavens that I know hang out here.
    It is not Python related, except that recent comparisons of Python to
    Google's new Go language brought it to mind.

    NOTE that this is *not* a suggestion to change Python. ?I like Python
    just the way it is. ?I'm just curious about language design.

    For a long time I've wondered why languages still use blocks
    (delimited by do/end, begin/end, { } , etc.) in ifThenElse statements.

    I've often thought that a language with this kind of block-free syntax
    would be nice and intuitive:

    ? ? if <condition> then
    ? ? ? ? do stuff
    ? ? elif <condition> then
    ? ? ? ? do stuff
    ? ? else
    ? ? ? ? do stuff
    ? ? endif

    Note that you do not need block delimiters.

    Obviously, you could make a more Pythonesque syntax by using a colon
    rather then "then" for the condition terminator. ?You could make it
    more PL/I-like by using "do", etc.

    You can write shell scripts using if ... fi, but other than that I
    don't recall a language with this kind of syntax.

    Does anybody know a language with this kind of syntax for
    ifThenElseEndif?

    Is there any particular reason why this might be a *bad* language-
    design idea?
    Fortran95. You can even label the IF...END IF structure -- handy for
    immense blocks.

    This is not a criticism of Python (or of Fortran).
  • Erik Max Francis at Nov 16, 2009 at 10:38 pm

    Steve Ferg wrote:
    I've often thought that a language with this kind of block-free syntax
    would be nice and intuitive:

    if <condition> then
    do stuff
    elif <condition> then
    do stuff
    else
    do stuff
    endif

    Note that you do not need block delimiters.

    Obviously, you could make a more Pythonesque syntax by using a colon
    rather then "then" for the condition terminator. You could make it
    more PL/I-like by using "do", etc.

    You can write shell scripts using if ... fi, but other than that I
    don't recall a language with this kind of syntax.
    It's the same syntax, with `fi` written instead of `endif` -- not sure
    why the difference in keyword is that big of a deal to you.

    As others have pointed out, either way, there are quite a few languages
    that use this type of syntax.

    --
    Erik Max Francis && max at alcyone.com && http://www.alcyone.com/max/
    San Jose, CA, USA && 37 18 N 121 57 W && AIM/Y!M/Skype erikmaxfrancis
    Mona Lisa / Come to discover / I am your daughter
    -- Lamya
  • Alex23 at Nov 17, 2009 at 3:28 am

    Steve Ferg wrote:
    Does anybody know a language with this kind of syntax for
    ifThenElseEndif? VBScript.
    Is there any particular reason why this might be a *bad* language-
    design idea?
    VBScript.
  • Mark Dickinson at Nov 17, 2009 at 10:15 am

    On Nov 16, 4:54?pm, Steve Ferg wrote:
    I've often thought that a language with this kind of block-free syntax
    would be nice and intuitive:

    ? ? if <condition> then
    ? ? ? ? do stuff
    ? ? elif <condition> then
    ? ? ? ? do stuff
    ? ? else
    ? ? ? ? do stuff
    ? ? endif

    Note that you do not need block delimiters.
    GAP uses almost exactly this syntax, but with 'fi' instead of 'endif':

    http://www.gap-system.org/Manuals/doc/htm/ref/CHAP004.htm#SECT016

    Mark
  • Sjm at Nov 17, 2009 at 3:29 pm
    On Nov 16, 12:54?pm, Steve Ferg wrote:
    <snip>
    Does anybody know a language with this kind of syntax for
    ifThenElseEndif?
    Modern-day COBOL:

    IF some-condition
    do-something
    ELSE
    do-something-else
    END-IF.

    The period is also meaningful as a statement terminator in COBOL,
    so it's not as clean as one might like.

    I, too, like the Python way.

    Cheers,
    Steve J. Martin
  • Simon Brunning at Nov 18, 2009 at 12:31 pm

    2009/11/17 sjm <sjmsoft at gmail.com>:
    On Nov 16, 12:54?pm, Steve Ferg wrote:
    <snip>
    Does anybody know a language with this kind of syntax for
    ifThenElseEndif?
    Modern-day COBOL:

    IF ? ? ?some-condition
    ? ? ? ?do-something
    ELSE
    ? ? ? ?do-something-else
    END-IF.
    RPG/400's SELEC statement: http://bit.ly/2LDegk

    Thing of beauty.

    Cheers,
    Simon B.
  • Nn at Nov 17, 2009 at 5:39 pm

    On Nov 16, 11:54?am, Steve Ferg wrote:
    This is a question for the language mavens that I know hang out here.
    It is not Python related, except that recent comparisons of Python to
    Google's new Go language brought it to mind.

    NOTE that this is *not* a suggestion to change Python. ?I like Python
    just the way it is. ?I'm just curious about language design.

    For a long time I've wondered why languages still use blocks
    (delimited by do/end, begin/end, { } , etc.) in ifThenElse statements.

    I've often thought that a language with this kind of block-free syntax
    would be nice and intuitive:

    ? ? if <condition> then
    ? ? ? ? do stuff
    ? ? elif <condition> then
    ? ? ? ? do stuff
    ? ? else
    ? ? ? ? do stuff
    ? ? endif

    Note that you do not need block delimiters.

    Obviously, you could make a more Pythonesque syntax by using a colon
    rather then "then" for the condition terminator. ?You could make it
    more PL/I-like by using "do", etc.

    You can write shell scripts using if ... fi, but other than that I
    don't recall a language with this kind of syntax.

    Does anybody know a language with this kind of syntax for
    ifThenElseEndif?

    Is there any particular reason why this might be a *bad* language-
    design idea?
    I personally like the "END X" syntax (not that I would want it for
    Python mind you). It makes it easier to read programs backwards.
    Foxpro used that syntax form extensively:

    http://msdn.microsoft.com/en-us/library/b660264t%28VS.80%29.aspx

    DO CASE ... ENDCASE
    DO WHILE ... ENDDO
    FOR EACH ... ENDFOR
    FOR ... ENDFOR
    IF ... ENDIF
    PRINTJOB ... ENDPRINTJOB
    SCAN ... ENDSCAN
    TEXT ... ENDTEXT
    WITH ... ENDWITH
  • Steven.oldner at Nov 17, 2009 at 7:27 pm
    Along the COBOl line is ABAP, the 4gl language from SAP.

    If today = 'Mon'.
    message 'oh boy'.
    elseif today = 'Wed'.
    message 'Hump day'.
    elseif today = 'Fri'.
    message 'TGIF'.
    else.
    message 'get to work'.
    endif.

    The period is the statement teminator. Indentation and separte lines
    are just to make it readable.
  • TerryP at Nov 18, 2009 at 12:03 am

    On Nov 16, 4:54?pm, Steve Ferg wrote:
    This is a question for the language mavens that I know hang out here.
    It is not Python related, except that recent comparisons of Python to
    Google's new Go language brought it to mind.

    NOTE that this is *not* a suggestion to change Python. ?I like Python
    just the way it is. ?I'm just curious about language design.

    For a long time I've wondered why languages still use blocks
    (delimited by do/end, begin/end, { } , etc.) in ifThenElse statements.

    I've often thought that a language with this kind of block-free syntax
    would be nice and intuitive:

    ? ? if <condition> then
    ? ? ? ? do stuff
    ? ? elif <condition> then
    ? ? ? ? do stuff
    ? ? else
    ? ? ? ? do stuff
    ? ? endif

    Note that you do not need block delimiters.

    Obviously, you could make a more Pythonesque syntax by using a colon
    rather then "then" for the condition terminator. ?You could make it
    more PL/I-like by using "do", etc.

    You can write shell scripts using if ... fi, but other than that I
    don't recall a language with this kind of syntax.

    Does anybody know a language with this kind of syntax for
    ifThenElseEndif?

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

    If you search Google, you will likely find some huge comparason of if
    or flow control statements in general, in zillions of languages.


    I personally like

    if expr [then | { | do | :]
    the code
    [done | } | ]

    As long as it starts with if and is immediately followed by expr, I
    could care less about the rest, unless someone forgets to document
    it ;-). Lisps cond is also sexy.
  • Bartc at Nov 18, 2009 at 2:00 am
    "Steve Ferg" <steve.ferg.bitbucket at gmail.com> wrote in message
    news:ff92db5b-9cb0-4a72-b339-2c5ac02fbad0 at p36g2000vbn.googlegroups.com...
    This is a question for the language mavens that I know hang out here.
    It is not Python related, except that recent comparisons of Python to
    Google's new Go language brought it to mind.

    NOTE that this is *not* a suggestion to change Python. I like Python
    just the way it is. I'm just curious about language design.

    For a long time I've wondered why languages still use blocks
    (delimited by do/end, begin/end, { } , etc.) in ifThenElse statements.

    I've often thought that a language with this kind of block-free syntax
    would be nice and intuitive:

    if <condition> then
    do stuff
    elif <condition> then
    do stuff
    else
    do stuff
    endif

    Note that you do not need block delimiters.

    Obviously, you could make a more Pythonesque syntax by using a colon
    rather then "then" for the condition terminator. You could make it
    more PL/I-like by using "do", etc.

    You can write shell scripts using if ... fi, but other than that I
    don't recall a language with this kind of syntax.

    Does anybody know a language with this kind of syntax for
    ifThenElseEndif?
    I think Algol 68 was responsible for a lot of this syntax, but there must be
    huge numbers of languages using that those forms now, apart from C-family
    languages which evolved their own syntax (and even in C, the preprocessor
    uses #if, #elif, #endif).

    Some syntaxes insist on ugly begin...end blocks, but the bracketing
    introduced by Algol68 (maybe even earlier) showed that these are redundant:

    if s then s [elsif s]* [else s] fi

    where s is any sequence of statements. The statements after the 'then' are
    delimited by an elsif, else or fi (endif) keyword.

    The endif (or fi) is necessary to show where the final statement sequence
    ends, and fixes the dangling-else problem. (And Algol68 also allowed this
    short form:

    (a | b | c)

    which is just if a then b else c fi, although it gets a bit hairy with elsif
    in there too..)
    I've often thought that a language with this kind of block-free syntax
    would be nice and intuitive: ...
    You're not the first to think that.. I use these forms in my own language
    designs for that reason. And when people write pseudo-code, it always seems
    to look like this, then they go and implement it in some god-forsaken syntax
    like C++...

    ...For some reason I can't quite understand, this sort of clear syntax seems
    to be looked down on by 'real' programmers, who perhaps think code like this
    can't be taken seriously.


    --
    Bartc
  • Dotan Cohen at Nov 18, 2009 at 7:33 am

    2009/11/16 Steve Ferg <steve.ferg.bitbucket at gmail.com>:
    This is a question for the language mavens that I know hang out here.
    It is not Python related, except that recent comparisons of Python to
    Google's new Go language brought it to mind.

    NOTE that this is *not* a suggestion to change Python. ?I like Python
    just the way it is. ?I'm just curious about language design.

    For a long time I've wondered why languages still use blocks
    (delimited by do/end, begin/end, { } , etc.) in ifThenElse statements.

    I've often thought that a language with this kind of block-free syntax
    would be nice and intuitive:

    ? ?if <condition> then
    ? ? ? ?do stuff
    ? ?elif <condition> then
    ? ? ? ?do stuff
    ? ?else
    ? ? ? ?do stuff
    ? ?endif

    Note that you do not need block delimiters.

    Obviously, you could make a more Pythonesque syntax by using a colon
    rather then "then" for the condition terminator. ?You could make it
    more PL/I-like by using "do", etc.

    You can write shell scripts using if ... fi, but other than that I
    don't recall a language with this kind of syntax.

    Does anybody know a language with this kind of syntax for
    ifThenElseEndif?
    PHP has exactly this:

    if (condition) {
    // stuff
    } elseif (otherContition) {
    // otherStuff
    } elseif (yetAnotherCondition) {
    // yetOtherStuff
    }


    Furthermore, PHP has the switch statement:
    http://php.net/manual/en/control-structures.switch.php

    switch ($i) {
    case 0:
    echo "i equals 0";
    break;
    case 1:
    echo "i equals 1";
    break;
    case 2:
    echo "i equals 2";
    break;
    }

    The break commands end the switch, and they can be removed to have
    multiple matches perform multiple functions.

    Is there any particular reason why this might be a *bad* language-
    design idea?
    It is about as far from OO as one could get. Whether or not that is
    "bad" depends on the use case.
  • Steve Howell at Nov 18, 2009 at 9:15 am
    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!')
  • Chris Rebert at Nov 18, 2009 at 9:32 am

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

    Cheers,
    Chris
  • Steve Howell at Nov 18, 2009 at 9:53 am

    On Nov 18, 1:32?am, Chris Rebert wrote:
    On Wed, Nov 18, 2009 at 1:15 AM, Steve Howell 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.
    If you introduce seven tiny little methods, aren't you increasing the
    length of the module by seven lines and introducing more complexity
    with the dispatch mechanism? (Actually, it's 14 lines more if you put
    a line of whitespace between your methods, and then you are also
    blurring an important cue that each of the seven code blocks all
    perform within the same context.)

    I do agree with your point that separate methods lead to easier unit
    testing.

    I'm a little more skeptical about the documentation/understanding
    argument, since code is often best understood within the context of
    surrounding code. I am also a bit skeptical of any coding technique
    that leads to lexical duplication like {'attr': process_attr, 'key':
    process_key, 'call': process_call}(ast); that is just replacing one
    smell with another. Of course, you could do something like __modules__
    [kind](ast) too, but that gets a bit overly abstract for a simple
    dispatch.

    Having said all that, I'm gonna take your suggestion...thanks for the
    response!
  • Steven D'Aprano at Nov 18, 2009 at 11:02 pm

    On Wed, 18 Nov 2009 01:53:50 -0800, Steve Howell wrote:
    On Nov 18, 1:32?am, Chris Rebert 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.
    If you introduce seven tiny little methods, aren't you increasing the
    length of the module by seven lines and introducing more complexity with
    the dispatch mechanism? (Actually, it's 14 lines more if you put a line
    of whitespace between your methods, and then you are also blurring an
    important cue that each of the seven code blocks all perform within the
    same context.)

    Dear me, the 1960s called, they want their controversy over structured
    programming back *wink*

    Yes, you increase the length of the module by having function headers.
    You also increase the length of the module by using meaningful names
    instead of calling everything "a", "b", "c" etc. We're not playing code
    golf, there's no reward for making unreadable code.

    The dispatch mechanism is no more complicated than a series of if...elif
    statements. In fact, you can replace an arbitrary number of "if x == y"
    statements with a *single* lookup:

    if x == 1:
    return 27
    elif x == 2:
    return 14
    elif x == 5:
    return 7
    else:
    return -1

    becomes the single line:

    return {1: 27, 2: 14, 5: 7}.get(x, -1)

    (although for more complicated examples, you would put the dict into its
    own line, or even lines).

    Dispatching isn't a panacea. You can't (easily) replace a series of
    if...elif statements where the conditions being tested aren't equality
    tests, e.g.:

    if 0 <= x <= 1:
    return 27
    elif 1 < x < 1.5 or x == 2:
    return 14
    elif ...

    is hard to turn into a dispatcher. But it's still a very useful technique
    when it applies.


    I do agree with your point that separate methods lead to easier unit
    testing.

    I'm a little more skeptical about the documentation/understanding
    argument, since code is often best understood within the context of
    surrounding code.
    That depends on the code. In particular, it depends on how coupled the
    code is. Ideally, you should have loosely coupled code, not highly
    coupled. If the code is loosely coupled, then there's no problem with
    understanding it in isolation. If the code is highly coupled, then it is
    hard to refactor it into a separate function, but that's a side-effect of
    the original problem, namely the high degree of coupling.

    As a general rule, if you need to know the context of the surrounding
    code to understand a function, you have too much coupling.


    I am also a bit skeptical of any coding technique
    that leads to lexical duplication like {'attr': process_attr, 'key':
    process_key, 'call': process_call}(ast); that is just replacing one
    smell with another.
    But how is that different from this?

    if condition(x, 'attr'):
    return process_attr(x)(ast)
    elif condition(x, 'key'):
    return process_key(x)(ast)
    elif ...


    Lexical duplication is one of the weakest code smells around, because it
    is so prone to false negatives. You often can't avoid referring to the
    same lexical element multiple times:


    def sinc(x):
    if x != 0:
    return sin(x)/x
    return 1

    That's four references to x in a four line function. Is this a problem?
    No, of course not.



    --
    Steven
  • Steve Howell at Nov 19, 2009 at 12:44 am

    On Nov 18, 3:02?pm, Steven D'Aprano wrote:

    That depends on the code. In particular, it depends on how coupled the
    code is. Ideally, you should have loosely coupled code, not highly
    coupled. If the code is loosely coupled, then there's no problem with
    understanding it in isolation. If the code is highly coupled, then it is
    hard to refactor it into a separate function, but that's a side-effect of
    the original problem, namely the high degree of coupling.
    Different blocks of an if/elif/elif/elif/elif/end are never directly
    coupled to each other, since you know that only one of the blocks is
    gonna execute. The blocks inherently do not effect each other.

    What you really achieve by extracting the code from an inside an elif
    block into a method is decoupling the elif block from the code ABOVE
    the if. This in and of itself is a good thing, of course, because you
    get a nice clean namespace in the extracted method, and you make the
    coupling between the code ABOVE the if and the extracted method
    explicit by specifying which parameters get passed. And in the case
    of my original code, all seven methods that were extracted only
    depended on a single parameter, the variable I was calling "ast," so
    it was easy to dispatch them all using the same mechanism. (In my
    case I didn't achieve much in terms of cleaning the local namespace,
    since the only variable defined above the if/elif/elif/elif/end was
    "kind," but I did make my code less brittle to future changes.)

    I am not going to defend "if/elif/elif/elif/elif/end" too vigorously
    here. There are obvious advantages to extracting methods, even
    methods that only ever get called from one parent. I do not miss
    switch statements one bit in Python. I am little more ambivalent
    about anonymous methods. It pains me just a tiny bit whenever I have
    write code like this:

    dispatches = {
    'dict': handle_dict,
    'list': handle_list,
    'attr': handle_attr,
    'key': handle_key,
    'as': handle_as,
    'call': handle_call,
    }
    if kind in dispatches:
    return dispatches[kind](ast)
    else:
    raise Exception('unknown kind!')

    I have used the idiom that Simon suggested in an earlier post, shown
    below, but it is still brittle to name changes in a way that anonymous
    methods are not, because you can't break an inline anonymous method
    with a name change (the benefits on anonymity!!):

    try:
    method = getattr(self, 'do_' + kind)
    except AttributeError:
    raise Exception('unknown kind!')

    self.ast = ast

    return method()
  • Steve Howell at Nov 19, 2009 at 1:14 am

    On Nov 18, 3:02?pm, Steven D'Aprano wrote:
    Lexical duplication is one of the weakest code smells around, because it
    is so prone to false negatives. You often can't avoid referring to the
    same lexical element multiple times:

    def sinc(x):
    ? ? if x != 0:
    ? ? ? ? return sin(x)/x
    ? ? return 1
    The existence of one code sample where lexical duplication is a false
    negative should not get you into the habit of disregarding it all
    together.

    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. In my
    example, the reference to _dict is 36 lines of code away from its
    implementation, which forces indirection on the reader. So maybe the
    methods in between def _dict and _dict are too long. I can pretty
    quickly rule that out, as the methods average about four lines each.

    So maybe the dispatch method is calling out the need for a class, as
    Simon suggested in another post. I also wonder if an inline decorator
    is in order.

    One thing I promise not to do is revert the code to if/elif/elif. :)
  • Steven D'Aprano at Nov 19, 2009 at 1:42 am

    On Wed, 18 Nov 2009 17:14:27 -0800, Steve Howell wrote:

    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.

    In my
    example, the reference to _dict is 36 lines of code away from its
    implementation, which forces indirection on the reader.
    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.

    If a function *only* makes sense immediately where you use it, then the
    level of coupling is too great and you should either reduce the coupling
    or bite the bullet and live with all the hassles of inline code. (Code
    duplication, difficulty in testing, etc.)

    Of course it would be convenient if, having noticed the reference to
    (say) function _recurse, you could see its definition without needing to
    do more than just glance up a line or two. But you should rarely need to
    care about the implementation -- that's another point of functions. You
    should be able to treat _recurse as a black box, just as you use the
    built-in function len as a black box without needing to see its
    implementation every time you use it.



    --
    Steven
  • Steve Howell at Nov 19, 2009 at 2:28 am

    On Nov 18, 5:42?pm, Steven D'Aprano wrote:
    On Wed, 18 Nov 2009 17:14:27 -0800, Steve Howell wrote:
    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.

    In my
    example, the reference to _dict is 36 lines of code away from its
    implementation, which forces indirection on the reader.
    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.
  • Steve Howell at Nov 18, 2009 at 10:06 am

    On Nov 18, 1:32?am, Chris Rebert wrote:
    On Wed, Nov 18, 2009 at 1:15 AM, Steve Howell 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.
  • Steven D'Aprano at Nov 18, 2009 at 10:22 pm

    On Wed, 18 Nov 2009 02:06:49 -0800, Steve Howell wrote:

    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.

    Then name them something sensible that tells what they do!

    The convention (which you break at your peril) is that functions are
    verbs, and classes are nouns. Even "handle_dict" is better than _dict --
    the latter looks like you're calling a private mapping type.


    --
    Steven
  • Steve Howell at Nov 18, 2009 at 11:58 pm

    On Nov 18, 2:22?pm, Steven D'Aprano wrote:
    On Wed, 18 Nov 2009 02:06:49 -0800, Steve Howell wrote:
    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.
    Then name them something sensible that tells what they do!

    The convention (which you break at your peril) is that functions are
    verbs, and classes are nouns. Even "handle_dict" is better than _dict --
    the latter looks like you're calling a private mapping type.
    Do you verbify functions with no side effects? Do you prefer
    calculate_cosine(angle) to cosine(angle)?
  • Steven D'Aprano at Nov 19, 2009 at 1:13 am

    On Wed, 18 Nov 2009 15:58:24 -0800, Steve Howell wrote:

    On Nov 18, 2:22?pm, Steven D'Aprano
    wrote:
    On Wed, 18 Nov 2009 02:06:49 -0800, Steve Howell wrote:
    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.
    Then name them something sensible that tells what they do!

    The convention (which you break at your peril) is that functions are
    verbs, and classes are nouns. Even "handle_dict" is better than _dict
    -- the latter looks like you're calling a private mapping type.
    Do you verbify functions with no side effects? Do you prefer
    calculate_cosine(angle) to cosine(angle)?

    Neither, I prefer cos(angle).

    Mathematical functions are a special case. They have been around since
    long before computers, and there is a whole different tradition for them.
    (The tradition is that most functions are named after Euler, or the first
    person to discover them after Euler.)

    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. Functions
    that return some property of a noun are often named after the property:

    len(x) rather than get_len(x)
    sqrt(x) rather than calculate_sqrt(x)

    and similar.

    Likewise, conversion functions are often named after the return result:

    int(x) returns an int
    str(x) returns a str

    [pedant]
    these are actually types, not functions, in Python
    [/pedant]


    But I'm not sure what naming convention you used. It seems fairly
    arbitrary to me, but whatever it is, it clashes with built-ins, which is
    a good sign that you need a different set of names. Since naming the
    functions with leading underscores also clashes with the convention that
    such functions are private, that's a further sign that you should use a
    different naming convention. At the point that you are apologizing for
    the convention you use, maybe you should rethink it.

    But of course it's your code, and you're free to use whatever convention
    you like.



    --
    Steven
  • Steve Howell at Nov 19, 2009 at 1:25 am

    On Nov 18, 5:13?pm, Steven D'Aprano wrote:
    On Wed, 18 Nov 2009 15:58:24 -0800, Steve Howell wrote:
    On Nov 18, 2:22?pm, Steven D'Aprano
    wrote:
    On Wed, 18 Nov 2009 02:06:49 -0800, Steve Howell wrote:
    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.
    [...]

    But I'm not sure what naming convention you used. It seems fairly
    arbitrary to me, but whatever it is, it clashes with built-ins, which is
    a good sign that you need a different set of names. Since naming the
    functions with leading underscores also clashes with the convention that
    such functions are private, that's a further sign that you should use a
    different naming convention. At the point that you are apologizing for
    the convention you use, maybe you should rethink it.

    But of course it's your code, and you're free to use whatever convention
    you like.
    The code in question, with the _list and _dict, is used as a part of
    mini-compiler-like-thingy that generates code from an expression
    syntax. If you've ever worked with code to implement compilers,
    interpreters, VMs, etc., you probably know the naming challenges
    involved. The whole reason I mentioned the wierd names in a "P.S."
    was to say that I realized it was a little wierd, and it was kind of
    besides the point. But I have enjoyed your responses. They are
    slightly pedantic, of course, but in a good way! Makes me think about
    the code more...

    If you want more context on the code itself (apart from if/elif
    discussion and other digressions), I describe it in more detail here:

    http://showellonprogramming.blogspot.com/2009/11/more-on-python-deep-copy-schema.html
  • Michael Torrie at Dec 3, 2009 at 8:46 pm

    Steven D'Aprano wrote:
    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.
  • Simon Forman at Nov 18, 2009 at 8:10 pm

    On Wed, Nov 18, 2009 at 4:15 AM, Steve Howell 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.
  • Bartc at Nov 18, 2009 at 11:31 am

    Dotan Cohen wrote:
    2009/11/16 Steve Ferg steve.ferg.bitbucket at gmail.com:
    I've often thought that a language with this kind of block-free
    syntax would be nice and intuitive:

    if <condition> then
    do stuff
    elif <condition> then
    do stuff
    else
    do stuff
    endif

    Note that you do not need block delimiters.
    Does anybody know a language with this kind of syntax for
    ifThenElseEndif?
    PHP has exactly this:

    if (condition) {
    // stuff
    } elseif (otherContition) {
    // otherStuff
    } elseif (yetAnotherCondition) {
    // yetOtherStuff
    }
    The OP explicitly said no block delimiters. Your example uses {..}, and
    doesn't have endif.

    --
    Bartc
  • Dotan Cohen at Nov 18, 2009 at 8:20 pm

    The OP explicitly said no block delimiters. Your example uses {..}, and
    doesn't have endif.
    Just out of habit. I think that PHP, like C, lets you avoid the block
    deliminators so long as the block all fits on one line.
  • Steven D'Aprano at Nov 18, 2009 at 9:35 pm

    On Wed, 18 Nov 2009 09:33:38 +0200, Dotan Cohen wrote:

    Is there any particular reason why this might be a *bad* language-
    design idea?
    It is about as far from OO as one could get. Whether or not that is
    "bad" depends on the use case.

    That's crazy talk. IF...ENDIF is *syntax*, not a programming model. How
    is this hypothetical Python-like syntax not object oriented?

    class Parrot:
    def speak(self):
    if self.name is None:
    name = "Polly"
    else:
    name = self.name
    endif
    return "%s wants a cracker!" % name


    Syntax controls *how* you instruct the compiler, the programming model
    controls *what* you instruct the compiler to do.



    --
    Steven
  • Aahz at Nov 19, 2009 at 4:27 pm
    In article <ff92db5b-9cb0-4a72-b339-2c5ac02fbad0 at p36g2000vbn.googlegroups.com>,
    Steve Ferg wrote:
    Does anybody know a language with this kind of syntax for
    ifThenElseEndif?
    Several templating systems, including Cheetah.
    --
    Aahz (aahz at pythoncraft.com) <*> http://www.pythoncraft.com/

    "Debugging is twice as hard as writing the code in the first place.
    Therefore, if you write the code as cleverly as possible, you are, by
    definition, not smart enough to debug it." --Brian W. Kernighan
  • Michael Torrie at Dec 3, 2009 at 8:56 pm

    Steve Ferg wrote:
    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.
  • Robert Kern at Dec 3, 2009 at 9:10 pm

    On 2009-12-03 14:56 PM, Michael Torrie wrote:

    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
  • James Harris at Dec 4, 2009 at 7:11 am

    On 3 Dec, 20:56, Michael Torrie wrote:
    Steve Ferg wrote:
    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'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

Related Discussions

People

Translate

site design / logo © 2022 Grokbase