Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #69604 > unrolled thread

Re: Yet Another Switch-Case Syntax Proposal

Started byEthan Furman <ethan@stoneleaf.us>
First post2014-04-03 11:23 -0700
Last post2014-04-04 11:55 -0600
Articles 6 — 4 participants

Back to article view | Back to comp.lang.python

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: Yet Another Switch-Case Syntax Proposal Ethan Furman <ethan@stoneleaf.us> - 2014-04-03 11:23 -0700
    Re: Yet Another Switch-Case Syntax Proposal Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2014-04-04 08:33 +0000
      Re: Yet Another Switch-Case Syntax Proposal Marko Rauhamaa <marko@pacujo.net> - 2014-04-04 12:46 +0300
        Re: Yet Another Switch-Case Syntax Proposal Ian Kelly <ian.g.kelly@gmail.com> - 2014-04-04 10:02 -0600
          Re: Yet Another Switch-Case Syntax Proposal Marko Rauhamaa <marko@pacujo.net> - 2014-04-04 19:44 +0300
            Re: Yet Another Switch-Case Syntax Proposal Ian Kelly <ian.g.kelly@gmail.com> - 2014-04-04 11:55 -0600

#69604 — Re: Yet Another Switch-Case Syntax Proposal

FromEthan Furman <ethan@stoneleaf.us>
Date2014-04-03 11:23 -0700
SubjectRe: Yet Another Switch-Case Syntax Proposal
Message-ID<mailman.8852.1396550862.18130.python-list@python.org>
On 04/03/2014 09:02 AM, Lucas Malor wrote:
>
> In reply to Ian Kelly:
>>
>> Instead of disabling fallthrough by default, why not disable it all together?
>
> I was tempted but there are cases in which it's useful. An example
>
> switch day casein ("Monday", "Thursday", "Wednesday", "Tuesday", "Friday"):
>      gotowork = True
>      continue
> casein ("Monday", "Thursday", "Wednesday", "Tuesday", "Friday"):
>      daytype = "ferial"
> casein ("Saturday", "Sunday")
>      daytype = "festive"


Absolutely not.  Currently, the 'continue' key word means "stop processing and go back to the beginning".  You would 
have it mean "keep going forward".  Thus 'continue' would mean both "go backwards" and "go forwards" and would lead to 
unnecessary confusion.

--
~Ethan~

[toc] | [next] | [standalone]


#69655

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2014-04-04 08:33 +0000
Message-ID<533e6e58$0$29993$c3e8da3$5496439d@news.astraweb.com>
In reply to#69604
On Thu, 03 Apr 2014 11:23:39 -0700, Ethan Furman wrote:

> On 04/03/2014 09:02 AM, Lucas Malor wrote:
>>
>> In reply to Ian Kelly:
>>>
>>> Instead of disabling fallthrough by default, why not disable it all
>>> together?
>>
>> I was tempted but there are cases in which it's useful. An example
>>
>> switch day casein ("Monday", "Thursday", "Wednesday", "Tuesday",
>> "Friday"):
>>      gotowork = True
>>      continue
>> casein ("Monday", "Thursday", "Wednesday", "Tuesday", "Friday"):
>>      daytype = "ferial"
>> casein ("Saturday", "Sunday")
>>      daytype = "festive"
> 
> 
> Absolutely not.  Currently, the 'continue' key word means "stop
> processing and go back to the beginning".  

It does not go back to the beginning. That would require resetting the 
iterable, which may be impossible. And if you succeeded, it would mean a 
loop with continue might never terminate!

for i in (1, 2, 3):
    print(i)
    if i == 2: continue

=> prints:
1
2
1
2
1
2
1
...


Perhaps you mean "continue from the top"? But top and bottom is just an 
artifact of how we write the loop. The only direction that matters is 
iteration order, and I'm not aware of any language that allows for-loop 
iteration to go forward and backwards.

"continue" means "continue with the next iteration", as the documentation 
says:

https://docs.python.org/3/reference/simple_stmts.html

In some languages, it's even spelled "next", e.g. Perl. (After a decade 
plus of reading and writing Python code, I still try to write "next" when 
I mean continue.)  It's not a big stretch to go from "continue with the 
next iteration" to "continue with the next case".


> You would have it mean "keep
> going forward".  Thus 'continue' would mean both "go backwards" and "go
> forwards" and would lead to unnecessary confusion.

Well, there's certainly already some confusion :-)


-- 
Steven D'Aprano
http://import-that.dreamwidth.org/

[toc] | [prev] | [next] | [standalone]


#69660

FromMarko Rauhamaa <marko@pacujo.net>
Date2014-04-04 12:46 +0300
Message-ID<87ioqpqvef.fsf@elektro.pacujo.net>
In reply to#69655
>>>> Instead of disabling fallthrough by default, why not disable it all
>>>> together?
>>>
>>> I was tempted but there are cases in which it's useful. An example

No, it is never useful, it never was. It came into being by accident, a
design bug turned into an advertised feature.

>>> switch day casein ("Monday", "Thursday", "Wednesday", "Tuesday",
>>> "Friday"):
>>>      gotowork = True
>>>      continue
>>> casein ("Monday", "Thursday", "Wednesday", "Tuesday", "Friday"):
>>>      daytype = "ferial"
>>> casein ("Saturday", "Sunday")
>>>      daytype = "festive"

That "casein" next to "switch" bugs me. Did I already propose:

   switch: local_sabbath()
   case (1, 2, 3) as sabbath:
       ...
   case 6:
       ...
   else:
       ...

The key is to look at precedents:

   try:
        ...
   except (E1, E2) as e:
        ...
   except ...:
        ...
   finally:
        ...

and:

   lambda: expression


The "switch: day" format is a hybrid of the "try" and "lambda" syntaxes
and would be compatible with existing Python editors as well as general
Python sensibilities.


Marko

[toc] | [prev] | [next] | [standalone]


#69671

FromIan Kelly <ian.g.kelly@gmail.com>
Date2014-04-04 10:02 -0600
Message-ID<mailman.8894.1396627349.18130.python-list@python.org>
In reply to#69660

[Multipart message — attachments visible in raw view] — view raw

On Apr 4, 2014 3:51 AM, "Marko Rauhamaa" <marko@pacujo.net> wrote:
>
> >>> switch day casein ("Monday", "Thursday", "Wednesday", "Tuesday",
> >>> "Friday"):
> >>>      gotowork = True
> >>>      continue
> >>> casein ("Monday", "Thursday", "Wednesday", "Tuesday", "Friday"):
> >>>      daytype = "ferial"
> >>> casein ("Saturday", "Sunday")
> >>>      daytype = "festive"
>
> That "casein" next to "switch" bugs me. Did I already propose:
>
>    switch: local_sabbath()
>    case (1, 2, 3) as sabbath:
>        ...
>    case 6:
>        ...
>    else:
>        ...

I don't get what this is intended to do. First, why is the expression in
the first line after the colon? That doesn't match any existing block
syntax (as you note it matches lambda, but that's an expression-level
syntax). What's wrong with the much more natural "switch local_sabbath():"?

Second, "as" clauses are used in other contexts for local assignment. What
is the purpose of doing that here? How does this solve the problem of
explicitly denoting case multiplicity?

[toc] | [prev] | [next] | [standalone]


#69673

FromMarko Rauhamaa <marko@pacujo.net>
Date2014-04-04 19:44 +0300
Message-ID<87ppkx6o4p.fsf@elektro.pacujo.net>
In reply to#69671
Ian Kelly <ian.g.kelly@gmail.com>:

> On Apr 4, 2014 3:51 AM, "Marko Rauhamaa" <marko@pacujo.net> wrote:
>>    switch: local_sabbath()
>>    case (1, 2, 3) as sabbath:
>>        ...
>>    case 6:
>>        ...
>>    else:
>>        ...
> [...]
>
> What's wrong with the much more natural "switch local_sabbath():"?

Consider:

    switch local_sabbath():        # bad
    case (1, 2, 3) as sabbath:
        ...

Now Python "framing" requires that you place something between the first
":" and "case":

    switch local_sabbath():        # bad
        pass
    case (1, 2, 3) as sabbath:
        ...
    
Placing the expression after the colon terminates the first colon
cleanly. Also, the "lambda" precedent allows an expression to follow a
colon; both "lambda" and my "switch" mandate that the expression stay on
the same line with the colon.

> Second, "as" clauses are used in other contexts for local assignment.
> What is the purpose of doing that here? How does this solve the
> problem of explicitly denoting case multiplicity?

The "as" clause follows the precedent of the "try/except" statement. It
removes the occasional annoyance in C:

   switch (next_char()) {
   case '\n':
   case '\r':
       putchar(???);
        :   :   :

which forces you to introduce a temporary variable:

   char c;
        :   :   :
   c = next_char();
   switch (c) {
   case '\n':
   case '\r':
       putchar(c);
        :   :   :

It is most useful in the "default"/"else" branch:

   switch: q.pop()
   case 0:
       log_direction(0)
       return 1
   case (90, 270) as angle:
       log_direction(angle)
       return 0
   case 180:
       log_direction(180)
       return -1
   else angle:
       log_direction(angle)
       return math.cos(angle * 2 * PI / 360)


Marko

[toc] | [prev] | [next] | [standalone]


#69675

FromIan Kelly <ian.g.kelly@gmail.com>
Date2014-04-04 11:55 -0600
Message-ID<mailman.8897.1396634155.18130.python-list@python.org>
In reply to#69673
On Fri, Apr 4, 2014 at 10:44 AM, Marko Rauhamaa <marko@pacujo.net> wrote:
> Consider:
>
>     switch local_sabbath():        # bad
>     case (1, 2, 3) as sabbath:
>         ...

I'm not overly fond of that either.  That's why I liked the OP's
choice to put the first case in the switch statement.

> Now Python "framing" requires that you place something between the first
> ":" and "case":
>
>     switch local_sabbath():        # bad
>         pass
>     case (1, 2, 3) as sabbath:
>         ...

That's absurd.  Granted that omitting the pass doesn't match any
existing syntax, but that doesn't mean it *must* be done that way.

> Placing the expression after the colon terminates the first colon
> cleanly. Also, the "lambda" precedent allows an expression to follow a
> colon; both "lambda" and my "switch" mandate that the expression stay on
> the same line with the colon.

But in the case of the lambda *expression*, the following expression
is effectively the entire "suite" of the lambda "clause", mirroring
the form of a def statement.  If "local_sabbath()" is treated as the
suite of the switch *statement*, then "Python framing" tells us the
same construct could be written like this:

switch:
    local_sabbath()
case 1:
    ...

And if that's allowed, then why not this?

switch:
    if username == "ozzy":
        black_sabbath()
    else:
        local_sabbath()
case 1:
    ...

Or:

switch:
    for sabbath in list_of_sabbaths:
        sabbath
case 1:
    ...

Or even:

switch:
    pass
case 1:
    ...

The intent of the first two are fairly clear, but they're way out of
scope for a switch statement.  I don't even intuitively know what to
do with the last two.  The point here is that the switch expression
really ought to be a single expression contained in the switch header,
not a suite.


>> Second, "as" clauses are used in other contexts for local assignment.
>> What is the purpose of doing that here? How does this solve the
>> problem of explicitly denoting case multiplicity?
>
> The "as" clause follows the precedent of the "try/except" statement. It
> removes the occasional annoyance in C:
>
>    switch (next_char()) {
>    case '\n':
>    case '\r':
>        putchar(???);
>         :   :   :
>
> which forces you to introduce a temporary variable:

How is the target identifier of the "as" not a temporary variable?
Try/except statements and with statements use "as" keywords to capture
values that may not otherwise be available in scope for assignment.
Except assigns the exception instance that was just caught, and with
assigns whatever arbitrary object was returned by the context
manager's __enter__ method.  With switch there is no need for that;
just do this:

char = next_char()
switch next_char:
case in '\n\r':
    print(char)

Similarly there is no need for the "if" or "while" statements to
support an "as" keyword, as in:

while next_char() as char:
    print(char)

There are good reasons why the language generally does not allow
assignments in non-assignment statements, which is what your "as" is
trying to do.  The Pythonic way to write that loop is:

while True:
    char = next_char()
    if not char: break
    print(char)

Which is at least as ungraceful as assigning the switch variable
before the switch statement.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web