Re: Yet Another Switch-Case Syntax Proposal
On 6 April 2014 20:07, Chris Angelico rosuav-at-gmail.com |python-list@python.org| 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
On Mon, Apr 7, 2014 at 6:13 AM, Michael Torrie 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
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| 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
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
On Mon, Apr 7, 2014 at 3:49 AM, Marco S. 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
On 3 April 2014 20:12, Ian Kelly ian.g.kelly-at-gmail.com | python-list@python.org| 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
On Fri, Apr 4, 2014 at 10:44 AM, Marko Rauhamaa 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
Ian Kelly : > On Apr 4, 2014 3:51 AM, "Marko Rauhamaa" 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
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
On Apr 4, 2014 3:51 AM, "Marko Rauhamaa" 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
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
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
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
On Fri, Apr 4, 2014 at 2:13 PM, Ethan Furman wrote: > On 04/03/2014 08:09 PM, Chris Angelico wrote: >> >> On Fri, Apr 4, 2014 at 1:04 PM, MRAB 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
Re: Yet Another Switch-Case Syntax Proposal
On 04/03/2014 08:09 PM, Chris Angelico wrote: On Fri, Apr 4, 2014 at 1:04 PM, MRAB 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
On Fri, Apr 4, 2014 at 1:04 PM, MRAB 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
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
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
On Fri, Apr 4, 2014 at 10:03 AM, Mark Lawrence 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
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
On Fri, Apr 4, 2014 at 5:12 AM, Ian Kelly 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 v<0: raise UnknownVersionError("Version is below zero!") if v<1: commands_to_get_to_version_1 if v<2: commands_to_get_to_version_2 # Version 3 is current. set("version", 3) if v>3: 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
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
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
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
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
On Wed, Apr 2, 2014 at 7:06 PM, Steven D'Aprano 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
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
Re: Yet Another Switch-Case Syntax Proposal
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
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
Yet Another Switch-Case Syntax Proposal
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