Re: Yet Another Switch-Case Syntax Proposal

2014-04-10 Thread Lucas Malor
On 6 April 2014 20:07, Chris Angelico rosuav-at-gmail.com 
|python-list@python.org| d7v3zta...@sneakemail.com wrote:
 Here's a simpler form of the proposal, which might cover what you
 need. It's basically a short-hand if/elif tree.

 case expression comp_op expression:
 suite
 case [comp_op] expression:
 suite
 
 else:
 suite

I like this solution, but I tought about a simpler one. Basically it's my first 
proposal with two modifications:
1. case / elcase instead of continue, as before
2. if the case expression is a *tuple* (and not any one iterable), case suite 
is executed if the switched expression is an element of the tuple.

If you want to match exactly a tuple, you have simply to put it into another 
tuple of length 1. Tricky but too much rare to care about.
To recap:

switch_stmt ::=  switch expression case expression_list : suite
(case | elcase expression_list : suite)*
[else : suite]
1. if expression_list is a tuple, the case suite will be executed if the switch 
expression is a member of the tuple.
2. if expression_list is not a tuple, the case suite will be executed if the 
switch expression is equal
Example:

briefing_days = (Tue, Thu)
normal_days = (Mon, Wed, Fri)

switch day normal_days + briefing_days:
go_to_work = True
day_type = weekday
case normal_days:

lunch_time = datetime.time(12)
meeting_time = datetime.time(14)
elcase briefing_days:

lunch_time = datetime.time(11, 30)
meeting_time = datetime.time(12, 30)
else:

go_to_work = False
day_type = festive
lunch_time = None
meeting_time =None

Another example:
switch tarot case 0:
card = Fool
case 1:
card = Alan Moore
case 2:
card = High Priestess
etc.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Yet Another Switch-Case Syntax Proposal

2014-04-06 Thread Marco S.
On 3 April 2014 20:12, Ian Kelly ian.g.kelly-at-gmail.com |
python-list@python.org| dnl5yyr...@sneakemail.com wrote:
 Use this instead [of continue]:

 switch day case in (Mon, Tue, Wed, Thu, Fri):
 go_to_work = True
 day_type = ferial
 if day in (Tue, Thu):
 lunch_time = datetime.time(11, 30)
 meeting_time = datetime.time(12, 30)
 else:
 lunch_time = datetime.time(12)
 meeting_time = datetime.time(14)
 case in (Sat, Sun):
 go_to_work = False
 day_type = festive

 You get an extra level of indentation this way, but it reads less like
 spaghetti code.


Well, if you have to add an if-else to your switch-case, it means
switch-case syntax is not so useful.
An alternative is to imitate elif, so you'll have elcase. This way we don't
need continue. Since I do not like elcasein, the best solution is to do as
suggested by many of you, so case in instead of casein.
But if you can write case in, why you can't write case comp_operator in
general? With this syntax you can do also case is not, case  etc... Your
example will turn into

briefing_days = (Tue, Thu)
festive_days = (Sat, Sun)

switch day case in briefing_days:
lunch_time = datetime.time(11, 30)
meeting_time = datetime.time(12, 30)
case not in briefing_days + festive_days:
lunch_time = datetime.time(12)
meeting_time = datetime.time(14)
case in festive_days:
go_to_work = False
day_type = festive
else:
go_to_work = True
day_type = ferial

The if-else equivalent will be:

if day in briefing_days:
lunch_time = datetime.time(11, 30)
meeting_time = datetime.time(12, 30)
if day not in briefing_days + festive_days:
lunch_time = datetime.time(12)
meeting_time = datetime.time(14)
if day in festive_days:
go_to_work = False
day_type = festive
else:
go_to_work = True
day_type = ferial


If you don't specify comp_operator, the default is ==. Example:

switch day_num case 1:
day_str = Monday
elcase 2:
day_str = Thursday
else:
day_str = etcetera
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Yet Another Switch-Case Syntax Proposal

2014-04-06 Thread Chris Angelico
On Mon, Apr 7, 2014 at 3:49 AM, Marco S. elbar...@gmail.com wrote:
 switch day case in briefing_days:

 lunch_time = datetime.time(11, 30)
 meeting_time = datetime.time(12, 30)
 case not in briefing_days + festive_days:

 lunch_time = datetime.time(12)
 meeting_time = datetime.time(14)
 case in festive_days:

 go_to_work = False
 day_type = festive
 else:

 go_to_work = True
 day_type = ferial

 The if-else equivalent will be:

 if day in briefing_days:

 lunch_time = datetime.time(11, 30)
 meeting_time = datetime.time(12, 30)
 if day not in briefing_days + festive_days:

 lunch_time = datetime.time(12)
 meeting_time = datetime.time(14)
 if day in festive_days:

 go_to_work = False
 day_type = festive
 else:

 go_to_work = True
 day_type = ferial

Here's a simpler form of the proposal, which might cover what you
need. It's basically a short-hand if/elif tree.

case expression comp_op expression:
suite
case [comp_op] expression:
suite
...
else:
suite

This has a slight oddity of parsing (in that an expression can
normally have a comparison in it); if you really want to use the
result of a comparison inside a case block, you'd have to parenthesize
it. But it's easy enough to explain to a human.

case day in briefing_days:
lunch_time = datetime.time(11, 30)
meeting_time = datetime.time(12, 30)
case not in briefing_days + festive_days:
lunch_time = datetime.time(12)
meeting_time = datetime.time(14)
case in festive_days:
go_to_work = False
day_type = festive
else:
go_to_work = True
day_type = ferial

A case statement that opens with a comparison operator takes the value
from the previous case (without re-evaluating it); a case statement
that lacks a comparison altogether assumes == and does the above. In
either case (pardon the pun), the check will be done only if the
preceding case was false. An 'else' clause is effectively equivalent
to a 'case' that's always true.

Adds only one keyword to the language (switch is gone), and adds an
edge case to parsing that's unlikely to come up in non-contrived code.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Yet Another Switch-Case Syntax Proposal

2014-04-06 Thread Michael Torrie
On 04/06/2014 12:07 PM, Chris Angelico wrote:
 This has a slight oddity of parsing (in that an expression can
 normally have a comparison in it); if you really want to use the
 result of a comparison inside a case block, you'd have to parenthesize
 it. But it's easy enough to explain to a human.

This syntax is almost identical to the if/elif/else syntax, though, no?

 
 case day in briefing_days:
 lunch_time = datetime.time(11, 30)
 meeting_time = datetime.time(12, 30)
 case not in briefing_days + festive_days:
 lunch_time = datetime.time(12)
 meeting_time = datetime.time(14)
 case in festive_days:
 go_to_work = False
 day_type = festive
 else:
 go_to_work = True
 day_type = ferial
 
 A case statement that opens with a comparison operator takes the value
 from the previous case (without re-evaluating it); a case statement
 that lacks a comparison altogether assumes == and does the above. In
 either case (pardon the pun), the check will be done only if the
 preceding case was false. An 'else' clause is effectively equivalent
 to a 'case' that's always true.
 
 Adds only one keyword to the language (switch is gone), and adds an
 edge case to parsing that's unlikely to come up in non-contrived code.
 
 ChrisA
 

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Yet Another Switch-Case Syntax Proposal

2014-04-06 Thread Ian Kelly
On Sun, Apr 6, 2014 at 11:49 AM, Lucas Malor 3kywjyd...@snkmail.com wrote:
 On 3 April 2014 20:12, Ian Kelly ian.g.kelly-at-gmail.com
 |python-list@python.org| dnl5yyr...@sneakemail.com wrote:
 Use this instead [of continue]:


 switch day case in (Mon, Tue, Wed, Thu, Fri):
 go_to_work = True
 day_type = ferial
 if day in (Tue, Thu):
 lunch_time = datetime.time(11, 30)
 meeting_time = datetime.time(12, 30)
 else:
 lunch_time = datetime.time(12)
 meeting_time = datetime.time(14)
 case in (Sat, Sun):
 go_to_work = False
 day_type = festive

 You get an extra level of indentation this way, but it reads less like
 spaghetti code.


 Well, if you have to add an if-else to your switch-case, it means
 switch-case syntax is not so useful.

I agree; the above is better suited to be an if.

 An alternative is to imitate elif, so you'll have elcase. This way we don't
 need continue. Since I do not like elcasein, the best solution is to do as
 suggested by many of you, so case in instead of casein.

So if I'm understanding your intention correctly, case means to
check this case regardless of whether any preceding case was matched,
and elcase means to check this case only if the most recent case
and its dependent elcases preceding this one were not matched.

switch Mon case in (Tue, Thu):
print(1)
elcase in (Mon, Wed, Fri):
print(2)
case in (Sat, Sun):
print(3)
elcase in (Mon, Tue, Wed, Thu, Fri):
print(4)

will print 2 and 4, correct?

 But if you can write case in, why you can't write case comp_operator in
 general? With this syntax you can do also case is not, case  etc...

At this point I see no advantage in adding this syntax.  It is so
similar to an if-elif chain that surely any optimization that could be
applied would be equally possible if the if-elif syntax, so why not
just use that?
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Yet Another Switch-Case Syntax Proposal

2014-04-06 Thread Chris Angelico
On Mon, Apr 7, 2014 at 6:13 AM, Michael Torrie torr...@gmail.com wrote:
 On 04/06/2014 12:07 PM, Chris Angelico wrote:
 This has a slight oddity of parsing (in that an expression can
 normally have a comparison in it); if you really want to use the
 result of a comparison inside a case block, you'd have to parenthesize
 it. But it's easy enough to explain to a human.

 This syntax is almost identical to the if/elif/else syntax, though, no?

Like I said, it's a short-hand for an if/elif tree, nothing more. Most
of the proposals have effectively been that anyway. There are
differences, though; the case target gets evaluated only once, for
instance. I'm not pushing strongly for its addition to the language.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Yet Another Switch-Case Syntax Proposal

2014-04-04 Thread Steven D'Aprano
On Thu, 03 Apr 2014 15:11:38 -0400, Terry Reedy wrote:

 On 4/3/2014 12:02 PM, Lucas Malor wrote:
 
 A more suitable place to propose this would be the python-ideas
 mailing list.

 You're right. I posted here because this list was linked by PEP 1. But
 now that I read more there's also python-ideas listed. Let me know if I
 have to continue there instead.
 
 Given that the idea has been posted to python-ideas and rejected, more
 that once I believe, I think this was the right place to post this to
 have variations discussed in a friendly manner.

I agree with Terry. Nothing wrong with gathering some feedback here first.



-- 
Steven D'Aprano
http://import-that.dreamwidth.org/
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Yet Another Switch-Case Syntax Proposal

2014-04-04 Thread Steven D'Aprano
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/
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Yet Another Switch-Case Syntax Proposal

2014-04-04 Thread Marko Rauhamaa

 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
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Yet Another Switch-Case Syntax Proposal

2014-04-04 Thread Ian Kelly
On Apr 4, 2014 3:51 AM, Marko Rauhamaa ma...@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?
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Yet Another Switch-Case Syntax Proposal

2014-04-04 Thread Devin Jeanpierre
If one were to add switch into Python, wouldn't it be desirable to
make a pattern matching switch (think the match or case construct
from Haskell or ML)? Python currently has poor support for union/sum
types in general, not just enumerations. It feels weird to add better
support for enumerations while ignoring the broader use case.

If a switch statement gets added to Python and I still need to examine
ASTs by a long chain of if-elif and isinstance and so on I will cry.

-- Devin

On Wed, Apr 2, 2014 at 7:53 AM, Lucas Malor 3kywjyd...@snkmail.com wrote:
 Hi all. I would proposeto you all a switch-case syntax for Python. I already 
 read PEP 3103 and I'm not completely satisfied by any of the proposed 
 solutions. This is my proposal:

 switch_stmt ::=  switch identifier case expression_list : suite
 (case expression_list : suite)*
 [else : suite]

 or, more simply:



 switch x case var1:
 
 case var2:
 ...
 case var3:
 ...
 else:
 ...



 Expression list should yield an iterable. The case suite will be executed if 
 the variable of the identifier is a member of the iterable.

 For example, in a switch x statement, the code case iterable:  is 
 identical to if x in iterable:  (or elif etc). So if you want to perform 
 the same case block for more than one value, you have only to specify a 
 tuple, a range etc.
 I would suggest to add an exception for non-iterable variables, so that you 
 don't have to write case var, :  but simply case var:  and it will be 
 identical to if x == var: . It's a bit tricky but the alternative is ugly.

 Fallthrough is disabled by default. The continue keyword cause to skip all 
 the remaining current case suite. The next case will be checked. You can't 
 use the continue keyword in the else clause.

 Some random remarks:
 1. switch is on the same line of the first case. This will avoid any 
 unpythonic syntaxes like:
 switch x
 case var1:
 ...

 or

 switch x:
 case var1:
 ...

 2. Fallthrough is disabled by default because IMHO it's what non-programmers 
 expect and that's what programmer usually needs more. I don't think a switch 
 with such a syntax needs a break statement.

 3. As an alternative, the continue statement could be written only at the end 
 of a case suite; it will be less powerful and not consistent with the other 
 compound statements, but it will improve readability.

 4. I decided to not use already existing keyword like if or in, since it 
 will be misleading and problematic for syntax highlighters.


 Tell me what you think about.
 --
 https://mail.python.org/mailman/listinfo/python-list
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Yet Another Switch-Case Syntax Proposal

2014-04-04 Thread Marko Rauhamaa
Ian Kelly ian.g.ke...@gmail.com:

 On Apr 4, 2014 3:51 AM, Marko Rauhamaa ma...@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
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Yet Another Switch-Case Syntax Proposal

2014-04-04 Thread Ian Kelly
On Fri, Apr 4, 2014 at 10:44 AM, Marko Rauhamaa ma...@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.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Yet Another Switch-Case Syntax Proposal

2014-04-03 Thread Ian Kelly
On Wed, Apr 2, 2014 at 7:06 PM, Steven D'Aprano st...@pearwood.info wrote:
 If we're going to add switch and case keywords, how about we also add
 of? Then we can write:

 switch x case of a, b, c:
 # x equals one of a, b or c
 case of d, e, f:
 # x equals one of d, e or f
 case in g, h, i:
 # g, h and i must be iterable, and x is in one of them
 else:
 # none of the above match

I don't think I like the idea of having case in and case of
meaning two different things, particularly since the one that you have
labeled with of is the one that I think should use in and vice
versa.  Seems like too much potential for confusion here.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Yet Another Switch-Case Syntax Proposal

2014-04-03 Thread Lucas Malor
Thank you for reading and commenting my proposal. Here are my replies:

In reply to Chris Angelico:

 I don't like the iterable vs non-iterable distinction. Compare: [...]
 case Test: # And there's your problem.

Yes, I had already thought after I posted that testing against string it's a 
problem. But I think that the more practical and unambiguous solution is to 
introduce also casein as a new keyword. So if you want to test a string:

switch mystring case -h:
print_usage()
case --version
print_version()

If you want to test against membership:

switch mychar casein aeiou:
mychar.vocal = True

I prefer casein instead of case in for the same reason Python uses elif 
instead of else if.



In reply to Ian Kelly:

 A more suitable place to propose this would be the python-ideas mailing list.

You're right. I posted here because this list was linked by PEP 1. But now that 
I read more there's also python-ideas listed. Let me know if I have to continue 
there instead.

 Why just just an identifier after the switch keyword instead of an expression?

Because I wronged, it can be an expression_list as well.

 An expression_list is one or more independent expressions separated by commas 
 that 
 don't create a tuple.

Well, py docs state An expression list containing at least one comma yields a 
tuple.

 __contains__ is not part of the interface for iterables

For what I know there's not an Iterable interface. For example List simply 
extends Object. I hope that an ABC Iterable class will be introduced in a 
future. 
Anyway, I think that switch x casein y should simply raise a TypeError if y 
doesn't implement __contains__, like x in y do.

 If we overload the continue keyword in this way, then a continue can't be 
 used within the switch
 to control a loop that the switch is nested within.

Well, this is the same problem for, say, a for loop nested inside another for 
loop, and you can solve it with the same methods.

 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
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Yet Another Switch-Case Syntax Proposal

2014-04-03 Thread Ian Kelly
On Thu, Apr 3, 2014 at 10:02 AM, Lucas Malor 3kywjyd...@snkmail.com wrote:
 __contains__ is not part of the interface for iterables

 For what I know there's not an Iterable interface. For example List simply 
 extends Object. I hope that an ABC Iterable class will be introduced in a 
 future.

It already exists:

 import collections.abc
 isinstance([1,2,3], collections.abc.Iterable)
True

 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

I don't see how it's useful there.  The first two cases are the same,
so just combine the code into one suite.  For overlapping cases where
the intersection needs to be handled by both suites, you can match
against the union and use conditionals to determine in more detail
which code to run.  For example, if you would write:

switch day case in (Mon, Wed, Fri):
lunch_time = datetime.time(12)
meeting_time = datetime.time(14)
continue
case in (Tue, Thu):
lunch_time = datetime.time(11, 30)
meeting_time = datetime.time(12, 30)
continue
case in (Mon, Tue, Wed, Thu, Fri):
go_to_work = True
day_type = ferial
case in (Sat, Sun):
go_to_work = False
day_type = festive

Use this instead:

switch day case in (Mon, Tue, Wed, Thu, Fri):
go_to_work = True
day_type = ferial
if day in (Tue, Thu):
lunch_time = datetime.time(11, 30)
meeting_time = datetime.time(12, 30)
else:
lunch_time = datetime.time(12)
meeting_time = datetime.time(14)
case in (Sat, Sun):
go_to_work = False
day_type = festive

You get an extra level of indentation this way, but it reads less like
spaghetti code.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Yet Another Switch-Case Syntax Proposal

2014-04-03 Thread Ethan Furman

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~
--
https://mail.python.org/mailman/listinfo/python-list


Re: Yet Another Switch-Case Syntax Proposal

2014-04-03 Thread Terry Reedy

On 4/3/2014 12:02 PM, Lucas Malor wrote:


A more suitable place to propose this would be the python-ideas mailing list.


You're right. I posted here because this list was linked by PEP 1. But now that 
I read more there's also python-ideas listed. Let me know if I have to continue 
there instead.


Given that the idea has been posted to python-ideas and rejected, more 
that once I believe, I think this was the right place to post this to 
have variations discussed in a friendly manner.


--
Terry Jan Reedy

--
https://mail.python.org/mailman/listinfo/python-list


Re: Yet Another Switch-Case Syntax Proposal

2014-04-03 Thread Chris Angelico
On Fri, Apr 4, 2014 at 5:12 AM, Ian Kelly ian.g.ke...@gmail.com wrote:
 Use this instead:

 switch day case in (Mon, Tue, Wed, Thu, Fri):
 go_to_work = True
 day_type = ferial
 if day in (Tue, Thu):
 lunch_time = datetime.time(11, 30)
 meeting_time = datetime.time(12, 30)
 else:
 lunch_time = datetime.time(12)
 meeting_time = datetime.time(14)
 case in (Sat, Sun):
 go_to_work = False
 day_type = festive

 You get an extra level of indentation this way, but it reads less like
 spaghetti code.

Still not an ideal demonstration of fall-through. Here's a much more
useful form:

switch get(version) case 0:
commands_to_get_to_version_1
case 1:
commands_to_get_to_version_2
case 2:
commands_to_get_to_version_3

# Version 3 is current.
set(version, 3)
case 3:
break
else:
raise UnknownVersionError(Unexpected version!)

With fall-through, you don't need a loop around that. You jump to the
appropriate point and start executing code until you get to the bottom
(apart from the else, which obviously should never happen).

To implement this in current Python, I'd probably do all the
comparisons as inequalities:

v = get(version)
if v0:
raise UnknownVersionError(Version is below zero!)
if v1:
commands_to_get_to_version_1
if v2:
commands_to_get_to_version_2

# Version 3 is current.
set(version, 3)
if v3:
raise UnknownVersionError(Version is moving backward!)

Which means this isn't really a terribly compelling use-case; but I
think it's a better one than overlapping ranges. Fall-through in
C-like languages completely ignores the case labels on subsequent
sections, and executes them because of their position in the file; I'm
not sure how it's looking with the current proposals, but it seems the
case statements would have to be written to catch the values from
above.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Yet Another Switch-Case Syntax Proposal

2014-04-03 Thread Mark Lawrence

On 02/04/2014 15:53, Lucas Malor wrote:

Hi all. I would proposeto you all a switch-case syntax for Python. I already 
read PEP 3103 and I'm not completely satisfied by any of the proposed 
solutions. This is my proposal:

switch_stmt ::=  switch identifier case expression_list : suite
 (case expression_list : suite)*
 [else : suite]

or, more simply:



switch x case var1:
 
case var2:
 ...
case var3:
 ...
else:
 ...



Please don't take this personally, but there's more chance of me being 
the first ever World President than of anybody getting a switch/case 
statement past the BDFL.


--
My fellow Pythonistas, ask not what our language can do for you, ask 
what you can do for our language.


Mark Lawrence

---
This email is free from viruses and malware because avast! Antivirus protection 
is active.
http://www.avast.com


--
https://mail.python.org/mailman/listinfo/python-list


Re: Yet Another Switch-Case Syntax Proposal

2014-04-03 Thread Chris Angelico
On Fri, Apr 4, 2014 at 10:03 AM, Mark Lawrence breamore...@yahoo.co.uk wrote:
 Please don't take this personally, but there's more chance of me being the
 first ever World President than of anybody getting a switch/case statement
 past the BDFL.

The language in PEP 3103 (written by Guido) doesn't suggest this to
me. But maybe that's just being diplomatic.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Yet Another Switch-Case Syntax Proposal

2014-04-03 Thread MRAB

On 2014-04-03 19:23, 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.  You would
have it mean keep going forward.  Thus 'continue' would mean both go backwards and 
go forwards and would lead to
unnecessary confusion.


I thought it went to the end of the loop, but because it's a loop, it
just wraps around back to the top...
--
https://mail.python.org/mailman/listinfo/python-list


Re: Yet Another Switch-Case Syntax Proposal

2014-04-03 Thread Ethan Furman

On 04/03/2014 07:04 PM, MRAB wrote:

On 2014-04-03 19:23, 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.  You would
have it mean keep going forward.  Thus 'continue' would mean both go backwards and 
go forwards and would lead to
unnecessary confusion.


I thought it went to the end of the loop, but because it's a loop, it
just wraps around back to the top...


*sigh*  I see you are already confused.  ;)

H I think that would be more like 'skip' as in 'skip to the end'...

Either way, though, 'continue' would mean two very different things:

 - skip everything between here and the end of the loop

 - don't skip everything between here and the end of the case

--
~Ethan~
--
https://mail.python.org/mailman/listinfo/python-list


Re: Yet Another Switch-Case Syntax Proposal

2014-04-03 Thread Chris Angelico
On Fri, Apr 4, 2014 at 1:04 PM, MRAB pyt...@mrabarnett.plus.com wrote:
 I thought [continue] went to the end of the loop, but because it's a loop, it
 just wraps around back to the top...

It goes to the bottom of the loop, and then the loop condition may or
may not send it to the top of the loop.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Yet Another Switch-Case Syntax Proposal

2014-04-03 Thread Ethan Furman

On 04/03/2014 08:09 PM, Chris Angelico wrote:

On Fri, Apr 4, 2014 at 1:04 PM, MRAB pyt...@mrabarnett.plus.com wrote:

I thought [continue] went to the end of the loop, but because it's a loop, it
just wraps around back to the top...


It goes to the bottom of the loop, and then the loop condition may or
may not send it to the top of the loop.


*ahem*

The loop condition is *at* the top of the loop;  if it was at the bottom it 
would be a do..until.  ;)

--
~Ethan~
--
https://mail.python.org/mailman/listinfo/python-list


Re: Yet Another Switch-Case Syntax Proposal

2014-04-03 Thread Chris Angelico
On Fri, Apr 4, 2014 at 2:13 PM, Ethan Furman et...@stoneleaf.us wrote:
 On 04/03/2014 08:09 PM, Chris Angelico wrote:

 On Fri, Apr 4, 2014 at 1:04 PM, MRAB pyt...@mrabarnett.plus.com wrote:

 I thought [continue] went to the end of the loop, but because it's a
 loop, it
 just wraps around back to the top...


 It goes to the bottom of the loop, and then the loop condition may or
 may not send it to the top of the loop.


 *ahem*

 The loop condition is *at* the top of the loop;  if it was at the bottom it
 would be a do..until.  ;)

Well, if you go by the disassembly, Python does put the condition at
the top of the loop. But I've seen plenty of C compilers that invert
that - before the top of the loop it jumps down to the bottom, the
bottom has the condition, and the condition may or may not jump you up
to the top of the loop.

Semantics :)

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Yet Another Switch-Case Syntax Proposal

2014-04-02 Thread Lucas Malor
Hi all. I would proposeto you all a switch-case syntax for Python. I already 
read PEP 3103 and I'm not completely satisfied by any of the proposed 
solutions. This is my proposal:

switch_stmt ::=  switch identifier case expression_list : suite
(case expression_list : suite)*
[else : suite]

or, more simply:



switch x case var1:

case var2:
...
case var3:
...
else:
...



Expression list should yield an iterable. The case suite will be executed if 
the variable of the identifier is a member of the iterable. 

For example, in a switch x statement, the code case iterable:  is identical 
to if x in iterable:  (or elif etc). So if you want to perform the same case 
block for more than one value, you have only to specify a tuple, a range etc. 
I would suggest to add an exception for non-iterable variables, so that you 
don't have to write case var, :  but simply case var:  and it will be 
identical to if x == var: . It's a bit tricky but the alternative is ugly.

Fallthrough is disabled by default. The continue keyword cause to skip all the 
remaining current case suite. The next case will be checked. You can't use the 
continue keyword in the else clause.

Some random remarks:
1. switch is on the same line of the first case. This will avoid any unpythonic 
syntaxes like:
switch x
case var1:
...

or 

switch x:
case var1:
...

2. Fallthrough is disabled by default because IMHO it's what non-programmers 
expect and that's what programmer usually needs more. I don't think a switch 
with such a syntax needs a break statement. 

3. As an alternative, the continue statement could be written only at the end 
of a case suite; it will be less powerful and not consistent with the other 
compound statements, but it will improve readability.

4. I decided to not use already existing keyword like if or in, since it 
will be misleading and problematic for syntax highlighters.


Tell me what you think about.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Yet Another Switch-Case Syntax Proposal

2014-04-02 Thread Ian Kelly
On Wed, Apr 2, 2014 at 8:53 AM, Lucas Malor 3kywjyd...@snkmail.com wrote:
 Hi all. I would proposeto you all a switch-case syntax for Python. I already 
 read PEP 3103 and I'm not completely satisfied by any of the proposed 
 solutions. This is my proposal:

A more suitable place to propose this would be the python-ideas mailing list.

 switch_stmt ::=  switch identifier case expression_list : suite
 (case expression_list : suite)*
 [else : suite]

Why just just an identifier after the switch keyword instead of an
expression?  There are many cases where a user might wish to do
something along the lines of switch values[0] case 42:

 Expression list should yield an iterable. The case suite will be executed if 
 the variable of the identifier is a member of the iterable.

An expression_list is one or more independent expressions separated by
commas that don't create a tuple.  If you just want an iterable, then
it should just be one expression.  But I'm not sure I like that.
Additionally, what if the value that you want to match is itself a
tuple?  If I write switch 1, 2, 3 case 1, 2, 3: will it match
against the entire tuple or will it try to match against the
individual ints and fail?  I prefer the case in syntax of
Alternative B of PEP 3103 here; it reads naturally and makes explicit
in the syntax whether you're matching against an individual object or
a grouping of objects.

 For example, in a switch x statement, the code case iterable:  is 
 identical to if x in iterable:  (or elif etc). So if you want to perform 
 the same case block for more than one value, you have only to specify a 
 tuple, a range etc.

__contains__ is not part of the interface for iterables; it is defined
for containers only.  So if the matching expression evaluates to a
container that could be the code equivalent, but for arbitrary
iterables the equivalent code would have to be:

for item in iterable:
if value == item:
# suite
break
else:
# move on to the next case

Which is unlikely to be any more efficient than a simple elif chain.

 Fallthrough is disabled by default. The continue keyword cause to skip all 
 the remaining current case suite. The next case will be checked. You can't 
 use the continue keyword in the else clause.

If we overload the continue keyword in this way, then a continue can't
be used within the switch to control a loop that the switch is nested
within.  Instead of disabling fallthrough by default, why not disable
it all together?  The container/iterable matching means that we can
already match multiple values to the same suite, so the only use
remaining for fallthrough would be the kind that creates code smell.

 Some random remarks:
 1. switch is on the same line of the first case. This will avoid any 
 unpythonic syntaxes like:

I like this better than any of the alternatives in the PEP.

 4. I decided to not use already existing keyword like if or in, since it 
 will be misleading and problematic for syntax highlighters.

Syntax highlighters could easily distinguish between something like
case in and existing uses of in.  The former starts with the
keyword case, and the others do not.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Yet Another Switch-Case Syntax Proposal

2014-04-02 Thread Chris Angelico
On Thu, Apr 3, 2014 at 1:53 AM, Lucas Malor 3kywjyd...@snkmail.com wrote:
 For example, in a switch x statement, the code case iterable:  is 
 identical to if x in iterable:  (or elif etc). So if you want to perform 
 the same case block for more than one value, you have only to specify a 
 tuple, a range etc.
 I would suggest to add an exception for non-iterable variables, so that you 
 don't have to write case var, :  but simply case var:  and it will be 
 identical to if x == var: . It's a bit tricky but the alternative is ugly.


This is sounding like a nasty special case. I'm ambivalent on the
overall proposal (want to see some real-world usage examples and how
they read), but I don't like the iterable vs non-iterable
distinction. Compare:

case 1,2,3: # Tuple - checks for any of its members
case range(10,110,10): # Range object - beautiful, convenient!
case 42: # Non-iterable, works the way you'd expect
case {1:Test,2:Hello,3:[]}: # Dictionary, may be surprising
case Test,: # Tuple with a single string in it - works but ugly
case Test: # And there's your problem.

You now have three valid ways to interpret that last statement:
1) It matches the exact string Test, the way people will expect
2) It matches any of the results of iterating over it
3) It matches anything where x in Test is true

The first option is a big fat special case, and one that'll get more
complicated as you start looking at subclasses and such. The second
means that case x is equivalent to case tuple(x), but I can't
imagine people would actually want that in real usage. The third is
the way you've described it so far, but again, I cannot imagine it as
anything other than highly surprising that my last statement above
will match st and es.

It would be more invasive to the language, but possibly better, to
have a new magic method __case__ which gets called to see if this
object matches this switched object. If that isn't defined, an
equality check is done. Then all of the above cases can be made
unsurprising by simply defining __case__ on a tuple (membership test)
and a range (ditto, except that the members aren't specifically
instantiated); everything else will check equality. (Having a dict
check for its keys is surprising, IMO, and I don't mind that one not
working.) It'd make it a *lot* easier to ensure sane behaviour in
custom classes; if you want your class to function like a single unit,
don't define __case__, but if you want it to function like a
collection, set __case__=__in__. What do you reckon?

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Yet Another Switch-Case Syntax Proposal

2014-04-02 Thread Steven D'Aprano
On Thu, 03 Apr 2014 08:50:47 +1100, Chris Angelico wrote:

 On Thu, Apr 3, 2014 at 1:53 AM, Lucas Malor 3kywjyd...@snkmail.com
 wrote:
 For example, in a switch x statement, the code case iterable:  is
 identical to if x in iterable:  (or elif etc). So if you want to
 perform the same case block for more than one value, you have only to
 specify a tuple, a range etc. I would suggest to add an exception for
 non-iterable variables, so that you don't have to write case var, : 
 but simply case var:  and it will be identical to if x == var: .
 It's a bit tricky but the alternative is ugly.


 This is sounding like a nasty special case. I'm ambivalent on the
 overall proposal (want to see some real-world usage examples and how
 they read), but I don't like the iterable vs non-iterable distinction.

If we're going to add switch and case keywords, how about we also add 
of? Then we can write:

switch x case of a, b, c:
# x equals one of a, b or c
case of d, e, f:
# x equals one of d, e or f
case in g, h, i:
# g, h and i must be iterable, and x is in one of them
else:
# none of the above match


That means we can cleanly match the common use-case where we want to 
match something by equality, comparing against a list of 1 or more 
(usually) scalar values:

case of 1, 2, [23, 42], 99:
assert x == 1 or x == 2 or x = [23,42] or x == 99

while also supporting the more complex case where we're matching against 
one or more sequences:

case in (1, 2, 99), [23, 42]:
assert x == 1 or x == 2 or x = 99 or x == 23 or x == 42


Of course, in practice the second case is likely to be given dynamically, 
not as literals:

case in LIST_OF_KEYWORDS:
...


Another option is to say that the cases being tested ought to be quite 
small in number. If you're trying to do this:

case in range(1):
...

you're doing it wrong. That being the case, we only need to match by 
equality:

case 1, 2, 3:
assert x == 1 or x == 2 or x == 3

and can write this when we want to match against a sequence or iterator:

case *LIST_OF_KEYWORDS:
...


and on the rare occasion we want to match against substrings, we can 
build a wrapper class:

class Wrapper:
def __init__(self, value):
self.value = value
def __eq__(self, other):
return other in self.value

case Wrapper(Hello world!):
# matches if x is a substring of Hello world!



But what's the advantage here? Since Python is not a static-typed 
language, it's unlikely that there are any compile-time optimizations 
that can be performed here. If there are any run-time optimizations that 
a JIT optimizing compiler like Python can perform, it probably can 
perform them just as well on a series of if...elif. So I'm not sure I see 
what having special syntax for a switch-case statement gives us.



-- 
Steven
-- 
https://mail.python.org/mailman/listinfo/python-list