[issue44600] match/case statements trace incorrectly in 3.10.0b4

2021-07-28 Thread Łukasz Langa

Łukasz Langa  added the comment:


New changeset 5502ee052fb4257ad7438dd1130c80e1a9c4bc7f by Miss Islington (bot) 
in branch '3.10':
bpo-44600: Refactor new tracing tests (GH-27396) (GH-27404)
https://github.com/python/cpython/commit/5502ee052fb4257ad7438dd1130c80e1a9c4bc7f


--
nosy: +lukasz.langa

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44600] match/case statements trace incorrectly in 3.10.0b4

2021-07-27 Thread miss-islington


Change by miss-islington :


--
pull_requests: +25937
pull_request: https://github.com/python/cpython/pull/27404

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44600] match/case statements trace incorrectly in 3.10.0b4

2021-07-27 Thread Brandt Bucher


Brandt Bucher  added the comment:


New changeset 38ddc8beb38d9a685de296a58b0741850e4853e5 by Brandt Bucher in 
branch 'main':
bpo-44600: Refactor new tracing tests (GH-27396)
https://github.com/python/cpython/commit/38ddc8beb38d9a685de296a58b0741850e4853e5


--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44600] match/case statements trace incorrectly in 3.10.0b4

2021-07-27 Thread miss-islington


Change by miss-islington :


--
pull_requests: +25930
pull_request: https://github.com/python/cpython/pull/27397

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44600] match/case statements trace incorrectly in 3.10.0b4

2021-07-27 Thread Brandt Bucher


Change by Brandt Bucher :


--
pull_requests: +25929
pull_request: https://github.com/python/cpython/pull/27396

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44600] match/case statements trace incorrectly in 3.10.0b4

2021-07-25 Thread miss-islington


miss-islington  added the comment:


New changeset 01601aa7360ae51e74a64dbe957288096bb364fd by Miss Islington (bot) 
in branch '3.10':
[3.10] bpo-44600: Fix line numbers for pattern matching cleanup code (GH-27346) 
(GH-27356)
https://github.com/python/cpython/commit/01601aa7360ae51e74a64dbe957288096bb364fd


--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44600] match/case statements trace incorrectly in 3.10.0b4

2021-07-25 Thread Brandt Bucher


Change by Brandt Bucher :


--
resolution:  -> fixed
stage: patch review -> resolved
status: open -> closed

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44600] match/case statements trace incorrectly in 3.10.0b4

2021-07-25 Thread miss-islington


Change by miss-islington :


--
nosy: +miss-islington
nosy_count: 7.0 -> 8.0
pull_requests: +25897
pull_request: https://github.com/python/cpython/pull/27356

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44600] match/case statements trace incorrectly in 3.10.0b4

2021-07-25 Thread Brandt Bucher


Brandt Bucher  added the comment:


New changeset 4214f470f0cb9b6fef9a90758756fbc00ba95b5a by Charles Burkland in 
branch 'main':
bpo-44600: Fix line numbers for pattern matching cleanup code (GH-27346)
https://github.com/python/cpython/commit/4214f470f0cb9b6fef9a90758756fbc00ba95b5a


--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44600] match/case statements trace incorrectly in 3.10.0b4

2021-07-24 Thread Charles Burkland


Change by Charles Burkland :


--
keywords: +patch
nosy: +chaburkland
nosy_count: 6.0 -> 7.0
pull_requests: +25887
stage:  -> patch review
pull_request: https://github.com/python/cpython/pull/27346

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44600] match/case statements trace incorrectly in 3.10.0b4

2021-07-24 Thread Brandt Bucher


Brandt Bucher  added the comment:

Yup, I plan on having it in this weekend.

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44600] match/case statements trace incorrectly in 3.10.0b4

2021-07-24 Thread Pablo Galindo Salgado


Change by Pablo Galindo Salgado :


--
priority: normal -> release blocker

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44600] match/case statements trace incorrectly in 3.10.0b4

2021-07-24 Thread Pablo Galindo Salgado


Pablo Galindo Salgado  added the comment:

The release candidate is soon, so I would recommend to land a fix as soon as 
possible so it can be tested for some time before is released, if that is 
possible.

--
nosy: +pablogsal

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44600] match/case statements trace incorrectly in 3.10.0b4

2021-07-23 Thread Brandt Bucher


Brandt Bucher  added the comment:

Two other things we realized while working on this:

- The first occurrence of line 15 in the example output should be marked as 
incorrectly traced.

- We should emit a NOP to show coverage of "case _" (that fix will be part of 
the same PR).

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44600] match/case statements trace incorrectly in 3.10.0b4

2021-07-18 Thread Brandt Bucher

Brandt Bucher  added the comment:

Yeah, this is actively being worked on. Thanks for asking.

If anything changes, I’ll let you know and you can pick it up then!

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44600] match/case statements trace incorrectly in 3.10.0b4

2021-07-17 Thread Jack DeVries


Jack DeVries  added the comment:

@brandtbucher, is anyone working on this yet? I'd like to take a crack at it 
this week if it's still available!

--
nosy: +jack__d

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44600] match/case statements trace incorrectly in 3.10.0b4

2021-07-15 Thread Brandt Bucher


Brandt Bucher  added the comment:

Thanks, that test framework looks good for this.

My initial hunch (just from looking at this) is that this has to do with how we 
handle cleanup after failed matches. Our "fail pop" blocks probably have 
whatever the last line number compiled was (which I think is always the last 
line of the preceding case block).

The fix *should* be as simple as calling "SET_LOC(c, 
whatever_the_last_pattern_was)" before compiling these blocks.

I have some new-ish contributors who might want to take this. As far as 
compiler issues go, this one seems pretty straightforward.

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44600] match/case statements trace incorrectly in 3.10.0b4

2021-07-12 Thread Ammar Askar


Ammar Askar  added the comment:

Brandt, maybe this regression test from a previous tracing bug might be useful 
for the test writing: 
https://github.com/python/cpython/pull/22026/files#diff-8b73bfc55514d8add8904c5f4d1d24b7b644ebfccba8d846085303577aa94dd6

--
nosy: +ammar2

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44600] match/case statements trace incorrectly in 3.10.0b4

2021-07-11 Thread Brandt Bucher


Brandt Bucher  added the comment:

Thanks, I'll take a closer look at this soon (most likely this coming week).

Out of curiosity, do we have a standard way of writing regression tests for 
correct line numbers like this? Of the top of my head, it seems like we could 
either statically compare the dis output (fragile) or actually execute some 
code with a trace function enabled and check the line hits (tricky).

Neither really seems ideal, so I'm wondering if there's be a better way?

--
assignee:  -> brandtbucher
type:  -> behavior

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44600] match/case statements trace incorrectly in 3.10.0b4

2021-07-11 Thread Mark Shannon


Change by Mark Shannon :


--
nosy: +brandtbucher

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44600] match/case statements trace incorrectly in 3.10.0b4

2021-07-11 Thread Ned Batchelder


New submission from Ned Batchelder :

Some simple match/case statements show incorrect tracing.  Below is the code to 
run, as well as the output.  Output lines with initial stars are incorrect: 
they incorrectly indicate that case bodies are executing when they are not. 
Sorry for the bulk here, I wanted to give you all the cases I had.

-- 8< -
import linecache, sys

def trace(frame, event, arg):
# The weird globals here is to avoid a NameError on shutdown...
if frame.f_code.co_filename == globals().get("__file__"):
lineno = frame.f_lineno
print("{} {}: {}".format(event[:4], lineno, linecache.getline(__file__, 
lineno).rstrip()))
return trace

def match_with_default():
for command in ["huh", "go home", "go n"]:
print(command)
match command.split():
case ["go", direction] if direction in "nesw":
match = f"go: {direction}"
case ["go", _]:
match = "no go"
case _:
match = "default"
print(match)

def match_with_wildcard():
for command in ["huh", "go home", "go n"]:
print(command)
match command.split():
case ["go", direction] if direction in "nesw":
match = f"go: {direction}"
case ["go", _]:
match = "no go"
case x:
match = f"default: {x}"
print(match)

def match_without_wildcard():
match = None
for command in ["huh", "go home", "go n"]:
print(command)
match command.split():
case ["go", direction] if direction in "nesw":
match = f"go: {direction}"
case ["go", _]:
match = "no go"
print(match)

print(sys.version)
sys.settrace(trace)
match_with_default()
match_with_wildcard()
match_without_wildcard()
-- 8< -
Output:

  3.10.0b4 (default, Jul 11 2021, 13:51:53) [Clang 12.0.0 (clang-1200.0.32.29)]
  call 10: def match_with_default():
  line 11: for command in ["huh", "go home", "go n"]:
  line 12: print(command)
  huh
  line 13: match command.split():
  line 14: case ["go", direction] if direction in "nesw":
  line 15: match = f"go: {direction}"
  line 16: case ["go", _]:
* line 17: match = "no go"
  line 19: match = "default"
  line 20: print(match)
  default
  line 11: for command in ["huh", "go home", "go n"]:
  line 12: print(command)
  go home
  line 13: match command.split():
  line 14: case ["go", direction] if direction in "nesw":
  line 16: case ["go", _]:
  line 17: match = "no go"
  line 20: print(match)
  no go
  line 11: for command in ["huh", "go home", "go n"]:
  line 12: print(command)
  go n
  line 13: match command.split():
  line 14: case ["go", direction] if direction in "nesw":
  line 15: match = f"go: {direction}"
  line 20: print(match)
  go: n
  line 11: for command in ["huh", "go home", "go n"]:
  retu 11: for command in ["huh", "go home", "go n"]:
  call 22: def match_with_wildcard():
  line 23: for command in ["huh", "go home", "go n"]:
  line 24: print(command)
  huh
  line 25: match command.split():
  line 26: case ["go", direction] if direction in "nesw":
* line 27: match = f"go: {direction}"
  line 28: case ["go", _]:
* line 29: match = "no go"
  line 30: case x:
  line 31: match = f"default: {x}"
  line 32: print(match)
  default: ['huh']
  line 23: for command in ["huh", "go home", "go n"]:
  line 24: print(command)
  go home
  line 25: match command.split():
  line 26: case ["go", direction] if direction in "nesw":
  line 28: case ["go", _]:
  line 29: match = "no go"
  line 32: print(match)
  no go
  line 23: for command in ["huh", "go home", "go n"]:
  line 24: print(command)
  go n
  line 25: match comm

[issue44283] Add jump table for certain safe match-case statements

2021-06-14 Thread Brandt Bucher

Brandt Bucher  added the comment:

Also (because some of the people who might be interested are nosied on this 
issue), I’ve been working a bit on general performance benchmarks for our 
pattern-matching implementation:

https://github.com/brandtbucher/patmaperformance

I still need something that hits sequence patterns hard, but I think these will 
help give us a good baseline for measuring future perf work in this area.

(There’s also the perf script at the bottom of Lib/test/test_patma.py, but the 
test cases it runs on probably are much less representative of “real” code.)

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44283] Add jump table for certain safe match-case statements

2021-06-14 Thread Brandt Bucher

Brandt Bucher  added the comment:

Sorry, I’ve been out on vacation this weekend. I didn’t realize that there was 
already a PR for this… I’m honestly not sure that it’s totally ready yet.

While I absolutely agree that compiling efficient decision trees lies in our 
future, it certainly seems to me that using *both* strategies (decision trees 
and jump tables) would create the most efficient branching structure. In 
effect, our control flow would be a rose tree.

In your example, Mark, we could perform the checks for the integers 1 and 2 
simultaneously, right?

Or consider a slightly more complicated example (simplified from PEP 636):

match …:
case ["quit"]: …
case ["look"]: …
case ["get", obj]: …
case ["go", direction]: …

We could compile this to something like:

- Check for Sequence.
- Multi-way jump on length.
- Multi-way jump on first item.

…which looks ideal to me.

I’m also confident that the jumping ops could also be broken up into fairly 
primitive instructions. A multi-way branch would just look something like:

(subject on TOS)
LOAD_CONST()
ROT_TWO
BINARY_SUBSCR
JUMP_FORWARD_TOS

…where only JUMP_FORWARD_TOS is new.

> For a sequence of integer constants, introducing the test `type(x) == int` at 
> the start would allow you to convert the linear sequence of tests into a 
> tree. Reducing `n` tests to `ln(n) + 1` tests.

Sorry, I’m having a bit of difficulty following this part. Is it something like 
the strategy I just described?

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44283] Add jump table for certain safe match-case statements

2021-06-14 Thread Mark Shannon


Mark Shannon  added the comment:

This is going in the wrong direction.

Rather than add more complex instructions for use only by pattern matching, we 
need to simplify the individual operations and re-use existing instructions.
That way pattern matching can benefit from the general performance improvements 
that we are making.


If you are serious about improving the performance of pattern matching, you 
need to do the following in the compiler:
1. Generate a decision tree.
2. Improve that decision tree so that fewer decisions are required.
3. Generate bytecode from that tree that uses lower level operations.

E.g.

match x:
case [1]:
A
case [2]:
B

The initial decision tree looks like:

if is_sequence(x):
if len(x) == 1:
if x[0] == 1:
A
if is_sequence(x):
if len(x) == 1:
if x[0] == 2:
B

which can be improved to:

if is_sequence(x):
if len(x) == 1:
if x[0] == 1:
A
elif x[0] == 2:
B

For a sequence of integer constants, introducing the test `type(x) == int` at 
the start would allow you to convert the linear sequence of tests into a tree. 
Reducing `n` tests to `ln(n) + 1` tests.

--
nosy: +Mark.Shannon

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44283] Add jump table for certain safe match-case statements

2021-06-13 Thread Raymond Hettinger


Raymond Hettinger  added the comment:

> How common match-case statements with literal integers? 

Nothing is common yet because the feature hasn't been released ;-)

I suspect that if match-case were optimized for integer constants, they would 
be used.  In discussions about case statements, there are two groups, one 
looking for a prettier if-elif-else chain and the other looking for a fast 
vectored jump.  This optimization is aimed at the latter group -- they would be 
happy to have this opportunity to make faster code, even if it means using 
integer constants.

--

___
Python tracker 
<https://bugs.python.org/issue44283>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44283] Add jump table for certain safe match-case statements

2021-06-13 Thread Serhiy Storchaka


Serhiy Storchaka  added the comment:

How common match-case statements with literal integers? I expect that in most 
cases such magic numbers are not used directly, but as named constants.

--
nosy: +serhiy.storchaka

___
Python tracker 
<https://bugs.python.org/issue44283>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44283] Add jump table for certain safe match-case statements

2021-06-12 Thread Dennis Sweeney


Dennis Sweeney  added the comment:

Here are some benchmarks:

PS C:\Users\sween\Source\Repos\cpython2\cpython> .\python.bat -m pyperf 
compare_to .\main.json .\PR-26697.json
Running Release|x64 interpreter...
1: Mean +- std dev: [main] 117 us +- 4 us -> [PR-26697] 122 us +- 3 us: 1.04x 
slower
2: Mean +- std dev: [main] 202 us +- 11 us -> [PR-26697] 180 us +- 7 us: 1.12x 
faster
3: Mean +- std dev: [main] 320 us +- 11 us -> [PR-26697] 243 us +- 13 us: 1.32x 
faster
4: Mean +- std dev: [main] 474 us +- 15 us -> [PR-26697] 306 us +- 15 us: 1.55x 
faster
5: Mean +- std dev: [main] 625 us +- 27 us -> [PR-26697] 341 us +- 6 us: 1.83x 
faster
6: Mean +- std dev: [main] 806 us +- 24 us -> [PR-26697] 404 us +- 20 us: 1.99x 
faster
7: Mean +- std dev: [main] 1.01 ms +- 0.04 ms -> [PR-26697] 461 us +- 19 us: 
2.19x faster
8: Mean +- std dev: [main] 1.22 ms +- 0.03 ms -> [PR-26697] 538 us +- 20 us: 
2.27x faster
9: Mean +- std dev: [main] 1.47 ms +- 0.05 ms -> [PR-26697] 607 us +- 27 us: 
2.42x faster
10: Mean +- std dev: [main] 1.75 ms +- 0.07 ms -> [PR-26697] 666 us +- 36 us: 
2.62x faster

--
Added file: https://bugs.python.org/file50106/matchperf.py

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44283] Add jump table for certain safe match-case statements

2021-06-12 Thread Dennis Sweeney


Change by Dennis Sweeney :


--
keywords: +patch
pull_requests: +25282
stage:  -> patch review
pull_request: https://github.com/python/cpython/pull/26697

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44283] Add jump table for certain safe match-case statements

2021-06-09 Thread Dong-hee Na


Change by Dong-hee Na :


--
nosy: +corona10

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44283] Add jump table for certain safe match-case statements

2021-06-07 Thread Brandt Bucher


Brandt Bucher  added the comment:

> Are you sure you want to do this?

No, not yet. But there has been some positive feedback here, and it seems like 
an interesting project to prototype. :)

> This optimisation is not applicable if the matched values are given symbolic 
> names. You would be encouraging people to write bad code with lots of 
> literals, for speed.

I had the same concern initially, but I'm honestly not losing too much sleep 
over it. Literals already get lots of optimizations that symbolic constants 
don't, and to me it seems a bit silly to avoid optimizing literals here when it 
is quite straightforward (and powerful) to do so. There are also many cases 
where using symbolic constants for certain literals doesn't make much sense.

I'd be okay not loudly publicizing this change if it lands. After all, I'm the 
guy who spent the better part of a year trying to convince people that this is 
Not A Switch Statement. :)

(Although, on the flip side, maybe it will help appease the people who have 
been asking for one all these years.)

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44283] Add jump table for certain safe match-case statements

2021-06-07 Thread Anders Munch


Anders Munch  added the comment:

Are you sure you want to do this?

This optimisation is not applicable if the matched values are given symbolic 
names.  You would be encouraging people to write bad code with lots of 
literals, for speed.

--
nosy: +AndersMunch

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44283] Add jump table for certain safe match-case statements

2021-06-04 Thread Dennis Sweeney


Dennis Sweeney  added the comment:

Hi Brandt,

I would welcome your collaboration/mentorship in whatever capacity makes sense. 
I sent an email to bra...@python.org from sweeney.dennis...@gmail.com.

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44283] Add jump table for certain safe match-case statements

2021-06-03 Thread Brandt Bucher


Brandt Bucher  added the comment:

I'm hoping we can get something close that for free by just waiting... the 
faster-cpython folks are working on a tagged-pointer implementation of integers 
as we speak.

I've been looking for a new project, so I'd love to help work on this issue (if 
you're open to it). The pattern compiler is a bit of a beast, and I like to 
think I have a better than-average-understanding of it. ;)

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44283] Add jump table for certain safe match-case statements

2021-06-02 Thread Kshitiz Arya


Change by Kshitiz Arya :


--
nosy: +Kshitiz17

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44283] Add jump table for certain safe match-case statements

2021-06-02 Thread Dennis Sweeney


Dennis Sweeney  added the comment:

Very interesting -- that is shorter than I thought also!

If we really wanted to optimize the tar out of this, we could probably find a 
way to re-use just the PyDictKeysObject to find the index into a C-array of 
integer jump targets and not have to worry about unboxing.

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44283] Add jump table for certain safe match-case statements

2021-06-02 Thread Brandt Bucher


Brandt Bucher  added the comment:

For anyone curious, I had some free time today and took a stab at creating a 
minimal _frozendict type (sharing as much implementation with dict as possible) 
to see how difficult it would be.

It was actually much simpler than I thought... just a few dozen lines of code, 
including marshal support. If you'd like to see it, you can check out my 
"frozendict" branch here:

https://github.com/python/cpython/compare/main...brandtbucher:frozendict

For testing purposes, I've exposed in the _testcapi module. It has the same 
constructor signature as dict, and basically only supports lookups:

>>> from _testcapi import _frozendict
>>> fd = _frozendict({1: 2, "3": 4, None: 5})
>>> fd
<_frozendict object at 0x7f4e127e4ef0>
>>> fd[1]
2
>>> fd[3]
Traceback (most recent call last):
  File "", line 1, in 
KeyError: 3
>>> import marshal
>>> marshal.loads(marshal.dumps(fd)) == fd
True

I'm not gonna lie... I really like it. It sidesteps any runtime 
construction/caching issues that using a normal dict would have, but with all 
of the same performance characteristics. It also seems like it would not 
introduce much of a maintenance burden, since it has very little of its own 
code.

Anyways, food for thought. It was a fun experiment at the very least.

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44283] Add jump table for certain safe match-case statements

2021-06-02 Thread Ken Jin


Change by Ken Jin :


--
nosy: +kj

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44283] Add jump table for certain safe match-case statements

2021-06-02 Thread Dennis Sweeney


Dennis Sweeney  added the comment:

FWIW PEP 603 includes a graph (Figure 2) of dict.get versus hamt.get 
performance as the mappings grow, and it seems the hamt is roughly 1.4x slower 
on inputs of sizes between 10 and 1000.

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44283] Add jump table for certain safe match-case statements

2021-06-02 Thread Brandt Bucher


Brandt Bucher  added the comment:

> If I understand your proposal, that would mean that calling a function with a 
> N-case constant-pattern match would require N hashes and N insertions into a 
> dict (including memory allocation), followed by O(1) lookup. Wouldn't that 
> eliminate any hope of making such a function O(1)? Unless there's a way to 
> cache the populated dict somewhere else?

Yeah, that was the idea sketched out above. Basically, if we go with a vanilla 
dictionary here, we're going to need to build it at runtime. It only really 
makes sense to do that once, the first time we need it. Then we stash it 
away... uh... somewhere. As you note, it doesn't make much sense to spend 
linear time building a constant-time jump table if it's only going to be used 
once. :)

Maybe somebody familiar with the constantly-evolving opcaches could chime in if 
this is the sort of thing that could benefit from that infrastructure. 
Basically, we would need a separate cache per bytecode offset, per code object. 
My understanding is that we don't have anything like that yet.

(A quick-and-dirty prototype could probably store them at "hidden" local names 
like ".table0", ".table1", ".table2", etc. I know comprehensions do something 
like that.)

> Re-implementing all of the dict logic seems like an unnecessary pain, which 
> is why I was suggesting either the HAMT or a thin wrapper around dict, not a 
> re-implementation of a new hash table.

Well, I don't think we'd need to do any of that. I believe set and frozenset 
share the same core design and routines, but differ only in the interfaces 
provided by the objects themselves. I imagine we could do something similar 
with a hypothetical _PyFrozenDict_Type... copy most of the type definition, 
dropping all of the methods except mp_subcript, tp_hash, and a few other 
members. That would probably be all we needed to get this design up and running 
for a proof-of-concept.

A lot of work goes into making dicts fast (especially for things like strings), 
so it would be nice for a new type to be able to benefit from those incremental 
improvements.

> I was hoping to do the minimum amount of disruption possible to get 
> reasonable O(1) performance, and then seeing where that leaves us.

Agreed, but the HAMT mapping has logarithmic time complexity for lookups, 
right? Maybe for realistic cases the coefficients make it basically equivalent, 
but on the surface it seems more promising to try reusing the dict guts instead.

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44283] Add jump table for certain safe match-case statements

2021-06-01 Thread Dennis Sweeney


Dennis Sweeney  added the comment:

I agree that we should benchmark for what the value of "two" should be ;) . 
Maybe only match statements with >=20 consecutive simple cases end up being 
worth it. I would assume that if "case 1, case 2, ..., case 20" are all in a 
row then "case 1" wouldn't be *that* much more likely than "case 20", so a 
slowdown on case 1 wouldn't matter too much if the average gets better.

I'm under the impression that match-case statements would frequently be used 
only once per function call. If I understand your proposal, that would mean 
that calling a function with a N-case constant-pattern match would require N 
hashes and N insertions into a dict (including memory allocation), followed by 
O(1) lookup. Wouldn't that eliminate any hope of making such a function O(1)? 
Unless there's a way to cache the populated dict somewhere else?

I suggested HAMT because it's a well-tested pre-existing fast immutable mapping 
that already implements __hash__, so it would be safe to store in co_consts 
already populated. Re-implementing all of the dict logic seems like an 
unnecessary pain, which is why I was suggesting either the HAMT or a thin 
wrapper around dict, not a re-implementation of a new hash table. I was hoping 
to do the minimum amount of disruption possible to get reasonable O(1) 
performance, and then seeing where that leaves us.

--

___
Python tracker 
<https://bugs.python.org/issue44283>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44283] Add jump table for certain safe match-case statements

2021-06-01 Thread Brandt Bucher

Brandt Bucher  added the comment:

Hm. I’m not sure if the HAMT makes much sense. We don’t really care about 
efficient mutation or copies... constant-time lookups seem to be overwhelmingly 
the most valuable factor here.

I personally think that creating some sort of hashable dict and teaching 
marshal how to serialize/deserialize it could be a promising path forward. I 
imagine its actual design could mirror dict (sort of like set/frozenset).

That might be a rather drastic step though. Perhaps it’s better to first prove 
that building a mapping at runtime is too slow.

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44283] Add jump table for certain safe match-case statements

2021-06-01 Thread Dennis Sweeney


Dennis Sweeney  added the comment:

At first I thought of matches with only the int/str/None cases and then I saw 
the easy generalization, but yeah, each contiguous block seems better.

One solution to the code hashability/lookup speed apparent dilemma: writing the 
equivalent of this in C:

class HashableDict(dict):
def __new__(cls, pairs):
return dict.__new__(cls, pairs)
def __eq__(self, other):
return tuple(self.mapping.items()) == tuple(other.sequence.items())
def __hash__(self):
return CONSTANT ^ hash(tuple(self.items()))
def __getnewargs__(self):
return tuple(self.items())

# forbid all mutating methods
__setitem__ = __delitem__ = update = __ior__ = None # etc.

(Or maybe using composition rather than inheritence)

Maybe using the HAMT in /Python/hamt.c would suffice instead.

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44283] Add jump table for certain safe match-case statements

2021-06-01 Thread Brandt Bucher


Brandt Bucher  added the comment:

Seems like a good idea as long as we're careful about the implementation. I've 
just jotted down a few notes here:

- We should probably break the table upon encountering a guard.

- We probably can't get away with storing a dictionary in the code object's 
constants, since the entire code object needs to be hashable. We could store a 
tuple of key-value pairs and either (a) build the dictionary each time we enter 
the block, or (b) stash it somewhere. If we stash it:
  - Should we defer building it until the first time we hit the block, or 
earlier than that?
  - Where would we stash it?

- We should probably have some heuristic perhaps more restrictive than "two or 
more of the following in a row". I'm not entirely sure that loading/building a 
dictionary, hashing an integer/string/None, looking it up in a dictionary, and 
then either (a) recovering from the error, or (b) converting the Python integer 
value into a C long and jumping on it is faster than the current implementation 
for the first two cases. I know it's really fast, but I'm not *sure* it will be 
an obvious win yet. Ideally, the best-case scenario (match on first case) would 
be just as fast as it is currently. I'm probably willing to speed up the 
average case at the expense of the best case, though.

- I'm not sure we need to limit this to leading cases. What's stopping us from 
having one of these jump tables in the middle of a match block (or even having 
more than one scattered throughout)? Unless I'm missing something, this should 
work anytime we observe contiguous "simple" cases.

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44283] Add jump table for certain safe match-case statements

2021-06-01 Thread Brandt Bucher


Change by Brandt Bucher :


--
nosy: +brandtbucher

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44283] Add jump table for certain safe match-case statements

2021-06-01 Thread Raymond Hettinger


Raymond Hettinger  added the comment:

Big +1 from me.  This would make use of match-case more compelling.

--
nosy: +rhettinger

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44283] Add jump table for certain safe match-case statements

2021-06-01 Thread Dennis Sweeney


New submission from Dennis Sweeney :

Anecdotally, a few people I've talked to have expected that match-case 
statements would improve performance in the same way that switch-cases 
sometimes do in C-like languages. While this is impossible in general without 
changing semantics (since, for example, __eq__ can have side effects), it would 
be nice if a jump table was implemented in certain safe cases.

My idea was to implement this whenever the list of cases begins with 2 or more 
of the following in a row:

(1) ints
(2) strings
(3) None
(4) OR (`|`) patterns of any of the above
(5?) potentially later add support for tuples

Example:

match x:
case 10: # safe
print("A")
case 20: # safe
print("B")
case 30 | 31:# safe
print("C")
case 40: # safe
print("D")
case MyClass(10, 20): # unsafe
print("E")
case []:  # unsafe
print("F")
case whatever:# unsafe
print("G")


This would compile to something like

LOAD_FAST (x)
LOAD_CONST 16({10: 16, 20: 38, 30: 80, 31: 80, 40: 102})
ATTEMPT_SAFE_MATCH 110

... all the rest of the code is the same ...

Where the new opcode would be would be something like

case TARGET(ATTEMPT_SAFE_MATCH): {
PyObject *jump_dict = POP();
PyObject *x = TOP();

if (PyLong_CheckExact(x) ||
PyUnicode_CheckExact(x) ||
Py_Is(x, Py_None))
{
PyObject *boxed = PyDict_GetItemWithError(jump_dict, x);
Py_DECREF(jump_dict);
if (res == NULL) {
if (PyErr_Occurred()) {
goto error;
}
else {
JUMPBY(oparg);
}
}
assert(PyLong_CheckExact(boxed));
int target = (int)PyLong_AsLong(boxed);
JUMPBY(target);
}
else {
// fall back to general matching code
Py_DECREF(jump_dict);
DISPATCH();
}
}

I can work on an implementation in the next couple of weeks.

--
components: Interpreter Core
messages: 394874
nosy: Dennis Sweeney
priority: normal
severity: normal
status: open
title: Add jump table for certain safe match-case statements
type: performance
versions: Python 3.11

___
Python tracker 
<https://bugs.python.org/issue44283>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



Re: Case Statements

2016-03-20 Thread Antoon Pardon
Op 16-03-16 om 12:07 schreef Mark Lawrence:
> On 16/03/2016 10:52, Antoon Pardon wrote:
>> Op 16-03-16 om 10:51 schreef Mark Lawrence:
>>> On 16/03/2016 09:35, Antoon Pardon wrote:
>>>> Op 16-03-16 om 09:47 schreef Mark Lawrence:
>>>>>
>>>>>>
>>>>>> Same with switch. You can use a hash table etc. to simulate
>>>>>> switches,
>>>>>> but only if the codeblocks are independent. Otherwise, if-elif
>>>>>> chains
>>>>>> are the way to go. Command line parsing is a case where switch
>>>>>> statements are often used, e.g. in shell scripts.
>>>>>
>>>>> I've seen at least six different ways of simulating switches, so
>>>>> those
>>>>> people who want them, can have them.  if-elif chains are not
>>>>> likely to
>>>>> kill any Python programmer.
>>>>>
>>>>> I have no interest what other languages use switch/case statements
>>>>> for, as we've on the PYTHON mailing list.
>>>>
>>>> There once were multiple ways to simulate a conditional expression.
>>>> And it was generally thought that using if else statements instead
>>>> of a conditional expression was unlikely to kill any Python
>>>> programmer.
>>>>
>>>> But then one of the core developers was bitten by a nasty bug because
>>>> he was using one of those constructs that simulated a conditional
>>>> expression and soon enough Python had a conditional expression.
>>>>
>>>> So I guess those who would like a case statement in Python can
>>>> only hope a core developer gets bitten by a nasty bug while using
>>>> one of those ways of simulating switches.
>>>>
>>>
>>> So that core developers can waste their time putting something into
>>> the language that we've done without for 25 years, yes, that strikes
>>> me as extremely worthwhile.
>>
>> Do you think python should stop progressing? Because all progress
>> python wil make, will be done by putting something in the language
>> we've done without for 25 years.
>>
>> That we have done without doesn't contradict it can be useful to have.
>>
>
> Raise the item on the python-ideas mailing list for the umpteenth time
> then, and see how far you get.

I don't care enough. I do care about people using valid arguments.

-- 
Antoon Pardon


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


Re: Case Statements

2016-03-20 Thread Mark Lawrence

On 16/03/2016 15:27, Antoon Pardon wrote:

Op 16-03-16 om 15:02 schreef Mark Lawrence:

On 16/03/2016 13:38, Antoon Pardon wrote:

Op 16-03-16 om 12:07 schreef Mark Lawrence:


Raise the item on the python-ideas mailing list for the umpteenth time
then, and see how far you get.


I don't care enough. I do care about people using valid arguments.



Arguments have been made for and against.  When the PEPs were rejected
are you saying that the arguments for acceptance were actually
stronger than the arguments for rejection?


No, I was just saying that your argument: "We've done without for 25
years" is invalid, because that would imply python should no longer make
any progress. Because any progress that will be made now, we've done
without for 25 years. -- Antoon



So putting something into the language that we don't actually need is 
progress?  Hum, in my book that's just plain weird.


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

Mark Lawrence

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


Re: Case Statements

2016-03-20 Thread Mark Lawrence

On 20/03/2016 08:01, Rustom Mody wrote:

On Wednesday, March 16, 2016 at 5:51:21 PM UTC+5:30, Marko Rauhamaa wrote:

BartC :


On 16/03/2016 11:07, Mark Lawrence wrote:

but I still very much doubt we'll be adding a switch statement --
it's a "sexy" language design issue




I did *NOT* write the above, that was me quoting the BDFL from 
https://mail.python.org/pipermail/python-ideas/2014-April/027667.html.


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

Mark Lawrence

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


Re: Case Statements

2016-03-20 Thread Rustom Mody
On Wednesday, March 16, 2016 at 5:51:21 PM UTC+5:30, Marko Rauhamaa wrote:
> BartC :
> 
> > On 16/03/2016 11:07, Mark Lawrence wrote:
> >> but I still very much doubt we'll be adding a switch statement --
> >> it's a "sexy" language design issue
> >
> > That's the first time I've heard a language feature common in C
> > described as sexy.
> 
> Scheme has a "switch" statement (a "case" form). However, it is slightly
> better equipped for it than Python:
> 
>  * Scheme has an atom type ("symbol"). It corresponds to interned
>strings and is supposed to be compared by reference.
> 
>  * Scheme has defined three equality operators: "eq?", "eqv?" and
>"equal?". Python only has two: "is" (~ "eq?") and "==" (~ "equal?").
>The "case" form makes use of the operator "eqv?" that is missing from
>Python ("eqv?" compares numbers numerically but is otherwise the same
>as "eq?").
> 
> 
> Marko

I think it needs to be mentioned:
Almost every modern functional language has pattern matching
And pattern matching is really case statements on steroids

https://www.vex.net/~trebla/haskell/crossroad.xhtml

>From those of us who regularly use functional programming, its important
to say that the things that get big press -- lambdas, monads etc -- are probably
less significant than things like pattern matching that dont

A smattering of languages that support it:

Erlang: http://erlang.org/doc/reference_manual/functions.html
Scala: 
https://kerflyn.wordpress.com/2011/02/14/playing-with-scalas-pattern-matching/
SML: http://www.cs.cornell.edu/courses/cs312/2004fa/lectures/lecture3.htm
Clojure : https://github.com/clojure/core.match

Scheme is an odd case: Does not have it builtin but writing a macro for that is 
an entertaining exercise
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Case Statements

2016-03-20 Thread Antoon Pardon
Op 16-03-16 om 18:24 schreef Mark Lawrence:
> On 16/03/2016 15:27, Antoon Pardon wrote:
>> Op 16-03-16 om 15:02 schreef Mark Lawrence:
>>> On 16/03/2016 13:38, Antoon Pardon wrote:
 Op 16-03-16 om 12:07 schreef Mark Lawrence:
>
> Raise the item on the python-ideas mailing list for the umpteenth time
> then, and see how far you get.

 I don't care enough. I do care about people using valid arguments.

>>>
>>> Arguments have been made for and against.  When the PEPs were rejected
>>> are you saying that the arguments for acceptance were actually
>>> stronger than the arguments for rejection?
>>>
>> No, I was just saying that your argument: "We've done without for 25
>> years" is invalid, because that would imply python should no longer make
>> any progress. Because any progress that will be made now, we've done
>> without for 25 years. -- Antoon
>>
> 
> So putting something into the language that we don't actually need is 
> progress?  Hum, in my book that's just plain weird.

It can be yes. Look at decorators. They don't provide functionality
we wouldn't have without them. So we don't actually need them. Do
you argue that introducing them wasn't progress?

-- 
Antoon Pardon.

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


Re: Case Statements

2016-03-19 Thread Steven D'Aprano
On Thursday 17 March 2016 16:45, Gregory Ewing wrote:

> Steven D'Aprano wrote:
>> On Thu, 17 Mar 2016 11:31 am, Chris Angelico wrote:
>> 
>>>orig = globals()[cls.__name__]
>> 
>> I wouldn't want to rely on it working with decorator syntax either. Even
>> if it does now, I'm not sure that's a language guarantee.
> 
> The following idiom relies on similar behaviour:
> 
>  @property
>  def x(self):
>  return self._x
> 
>  @x.setter
>  def x(self, value):
>  self._x = value
> 
> That's taken from the official docs, so I don't think
> this is likely to change any time soon.


I don't think that property is a similar situation. I think what happens 
here is that the first call to property sets:

# @property def x...
x = property(x)

Then the second decorator does:

# @x.setter def x...
x = x.setter(x)

which replaces x with a brand new property object.

What happens if you use different names?

@property
def x(self):
pass

@x.setter
def y(self, arg):
pass


Now you have two different properties:

py> x

py> y



Both x and y's getter points to the same function (our original def x):

py> y.fget

py> x.fget



But x's setter is None, while y has a valid setter:

py> x.fset is None
True
py> y.fset



I don't think that either x or y will misbehave, but the behaviour will 
certainly be surprising if you're not expecting it.

I think the documentation in Python 2.7 is misleading. help(x.setter) says:

setter(...)
Descriptor to change the setter on a property.

which is, I believe, a lie. It doesn't "change the setter" (modify the 
property object in place), but returns a new property object. Here's my 
pseudo-code for what I think property.setter does:

class property:
def setter(self, func):
return property(self.fget, func, self.fdel, self.__doc__)



As far as I can tell, none of this behaviour relies on the decorator being 
called before the name of the decorated thing is bound.




-- 
Steve

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


Re: Case Statements

2016-03-19 Thread Chris Angelico
On Thu, Mar 17, 2016 at 8:23 PM, Antoon Pardon
 wrote:
> Op 17-03-16 om 03:02 schreef Chris Angelico:
>> On Thu, Mar 17, 2016 at 12:54 PM, Steven D'Aprano  
>> wrote:
>>
>>> I wouldn't want to rely on it working with decorator syntax either. Even if
>>> it does now, I'm not sure that's a language guarantee.
>> That's the thing, though. It's not a guarantee, yet it does work in
>> every Python interpreter that I tried it in.
>
> That depends on what you mean by work. This failes:
> [doing the same thing in a function]

Very true; I could have messed around with getframe, but most classes
are global, and it keeps things simple.

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


Re: Case Statements

2016-03-19 Thread Steven D'Aprano
On Thu, 17 Mar 2016 12:15 am, l0r0m0a0...@gmail.com wrote:

> What hath I wrought?


Dr Ray Stantz: Fire and brimstone coming down from the skies! Rivers and
seas boiling!

Dr Egon Spengler: Forty years of darkness! Earthquakes, volcanoes...

Winston Zeddemore: The dead rising from the grave!

Dr Peter Venkman: Human sacrifice, dogs and cats living together... mass
hysteria! 



-- 
Steven

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


Re: Case Statements

2016-03-19 Thread l0r0m0a0i0l
What hath I wrought?
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Case Statements

2016-03-19 Thread BartC

On 16/03/2016 12:21, Marko Rauhamaa wrote:

BartC <b...@freeuk.com>:



That's the first time I've heard a language feature common in C
described as sexy.


Scheme has a "switch" statement (a "case" form). However, it is slightly
better equipped for it than Python:

  * Scheme has an atom type ("symbol"). It corresponds to interned
strings and is supposed to be compared by reference.

  * Scheme has defined three equality operators: "eq?", "eqv?" and
"equal?". Python only has two: "is" (~ "eq?") and "==" (~ "equal?").
The "case" form makes use of the operator "eqv?" that is missing from
Python ("eqv?" compares numbers numerically but is otherwise the same
as "eq?").



Yes, a few scripting languages can do interesting things with switch or 
case statements. Perl for example (where I think it is created out other 
language features, but it looks a regular part of the syntax).


Even Ruby has one. It doesn't do anything 'sexy' with it, but it does 
have this:


 case
 when this

 when that

 when other
...
 end

which is exactly equivalent to if this... elif that... (when the tests 
are ordered), with one difference:


Each test starts with "when", instead of "if" for the first and "elif" 
for subsequent ones. That makes it easier to reorder tests, temporarily 
comment out the first test, copy a test from elsewhere, insert a new 
first test (you get the idea).


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


Re: Case Statements

2016-03-19 Thread Marko Rauhamaa
l0r0m0a0...@gmail.com:

> Gratified to see that with all this back-and-forth this thread still
> has a sense of humor. Perhaps, we can all just agree to disagree? :)

I might agree with you if you tell me what we disagree about.


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


Re: Case Statements

2016-03-19 Thread Steven D'Aprano
On Wed, 16 Mar 2016 09:34 pm, BartC wrote:


> (BTW why does Python have 'elif' when if-else is all that is really
> needed?)

To save indentation.


if condition:
block
else:
if other:
block
else:
if third:
block
else:
block


versus:

if condition:
block
elif other:
block
elif third:
block
else:
block


Python could have spelled "elif" as "else if", but that's just a matter of
spelling. Either way, the important thing is that the else-if/elif keeps
the same indentation as the if.



-- 
Steven

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


Re: Case Statements

2016-03-19 Thread Mark Lawrence

On 16/03/2016 19:41, BartC wrote:

On 16/03/2016 09:51, Mark Lawrence wrote:

On 16/03/2016 09:35, Antoon Pardon wrote:



So I guess those who would like a case statement in Python can
only hope a core developer gets bitten by a nasty bug while using
one of those ways of simulating switches.



So that core developers can waste their time putting something into the
language that we've done without for 25 years, yes, that strikes me as
extremely worthwhile.



I've noticed that Python doesn't appear to have a way of putting
separators into numeric literals. (Or if it does, I've no idea how).
That means being able to write:

a = 1'000'000
b =   239_288
c = 0x7FFF```

depending on what separator is used. Despite waiting for it for 25
years, would that be worthwhile or not? (And if not, why not? And if it
is, perhaps other things can be too.)


Of course the change is actually trivial,


The above really is trivial (to anyone already familiar with the
workings of the byte-code compiler).


as
BartC has all ready pointed out. The work involved is shown here
https://mail.python.org/pipermail/python-dev/2006-June/065827.html


That article appears to try to do without using a new switch byte-code,
as the author doesn't see the point. My code to implement a 'switch'
byte-code (for integer expression and constant integer case-expressions)
is below.

Not shown is the support needed in the byte-code compiler (about 300
lines in my case as it's a bit fiddly, but it's not a run-time cost).

For a Python version, it might be an idea to make use of the convention
for constants (all-caps), then a streamlined switch could be on the cards.

global function k_switch:ref void =
 int index,n,lower

 n := getopnda
 lower := getopndb

 case sptr^.tag
 when tint,ttype then
 else
 pcerror("switch not int")
 esac

 index:=(sptr++)^.value-lower

 if u32(index)>=u32(n) then# out of range
 return ref int((pcptr+n*2+4)^)
 else
 return ref int((pcptr+index*2+4)^)
 fi
end




Job done then.  Raise an issue on the bug tracker and the extremely 
simple task of having a switch/case statement in Python is solved.  How 
the dumbo core developers didn't see this in the first place I'll just 
never know.


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

Mark Lawrence

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


Re: Case Statements

2016-03-19 Thread Steven D'Aprano
On Thu, 17 Mar 2016 10:14 am, Chris Angelico wrote:

> On Thu, Mar 17, 2016 at 5:31 AM, Antoon Pardon
>  wrote:
>> It can be yes. Look at decorators. They don't provide functionality
>> we wouldn't have without them.
> 
> Really? Okay, try implementing this without decorators:
 
[...]
> @monkeypatch
> class Foo:
[...]


I think Antoon is referring to decorator *syntax*, not the concept of
decorators in general. Decorator syntax is just syntactic sugar for:


class Foo:
...

Foo = monkeypatch(Foo)

which has been valid all the way back to Python 1.0.

Given first class functions and types, plus closures, I can't imagine how
you could fail to have decorators. Regardless of what monkeypatch actually
does internally, it takes a class as argument, and returns a new or
modified class. If you can create new classes on the fly, or modify them,
then you can implement decorator functionality, but without the convenience
of decorator syntax.

Indeed, Python started providing built-in decorators (such as classmethod
and staticmethod) as early as 2.2, but didn't gain the @ decorator syntax
until 2.4 for functions:

https://www.python.org/dev/peps/pep-0318/

and 2.6 for classes. The availability of a nice syntax to transform
functions and classes has, as Bruce Eckel predicted, transformed the Python
ecosystem, and decorators are now extensively used in libraries and
frameworks:

The reason I think decorators will have such a big impact is
because this little bit of syntax sugar changes the way you
think about programming. Indeed, it brings the idea of 
"applying code to other code" (i.e.: macros) into mainstream 
thinking by formalizing it as a language construct.

http://www.artima.com/weblogs/viewpost.jsp?thread=240808



-- 
Steven

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


Re: Case Statements

2016-03-19 Thread Chris Angelico
On Thu, Mar 17, 2016 at 11:19 AM, Steven D'Aprano  wrote:
> On Thu, 17 Mar 2016 10:14 am, Chris Angelico wrote:
>
>> On Thu, Mar 17, 2016 at 5:31 AM, Antoon Pardon
>>  wrote:
>>> It can be yes. Look at decorators. They don't provide functionality
>>> we wouldn't have without them.
>>
>> Really? Okay, try implementing this without decorators:
>
> [...]
>> @monkeypatch
>> class Foo:
> [...]
>
>
> I think Antoon is referring to decorator *syntax*, not the concept of
> decorators in general. Decorator syntax is just syntactic sugar for:
>
>
> class Foo:
> ...
>
> Foo = monkeypatch(Foo)
>
> which has been valid all the way back to Python 1.0.
>

Yes... in theory. But try rewriting my example to avoid decorator
syntax. It won't work, because of this line:

orig = globals()[cls.__name__]

It depends on the decorator being run before the name actually gets
bound - which means the previous class is available to the decorator.
You can't do that without decorator syntax, or messing around with
multiple names.

It works under PyPy3, CPython 3, and MicroPython; running it under a
Py2-compatible interpreter has issues with bound methods, but other
than that, it works on CPython 2, Jython, and PyPy2. Feel free to try
it under other interpreters to see if any of them actually implement
decorators as per their description.

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


Re: Case Statements

2016-03-19 Thread Marko Rauhamaa
BartC :

> On 16/03/2016 11:07, Mark Lawrence wrote:
>> but I still very much doubt we'll be adding a switch statement --
>> it's a "sexy" language design issue
>
> That's the first time I've heard a language feature common in C
> described as sexy.

Scheme has a "switch" statement (a "case" form). However, it is slightly
better equipped for it than Python:

 * Scheme has an atom type ("symbol"). It corresponds to interned
   strings and is supposed to be compared by reference.

 * Scheme has defined three equality operators: "eq?", "eqv?" and
   "equal?". Python only has two: "is" (~ "eq?") and "==" (~ "equal?").
   The "case" form makes use of the operator "eqv?" that is missing from
   Python ("eqv?" compares numbers numerically but is otherwise the same
   as "eq?").


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


Re: Case Statements

2016-03-19 Thread BartC

On 16/03/2016 21:43, Mark Lawrence wrote:

On 16/03/2016 19:41, BartC wrote:



That article appears to try to do without using a new switch byte-code,
as the author doesn't see the point. My code to implement a 'switch'
byte-code (for integer expression and constant integer case-expressions)
is below.



Job done then.  Raise an issue on the bug tracker and the extremely
simple task of having a switch/case statement in Python is solved.  How
the dumbo core developers didn't see this in the first place I'll just
never know.


The technical side is not the problem. But the language, the size of it, 
the organisation behind it, and the myriad implementations, is a monster.


I'm not interested in battling with that or all the people who don't 
want change. Plus the problems of keeping backwards compatibility.


But if you're talking about the code to implement 'switch', then yes it 
can be that simple. Although it seems no one is going to agree on the 
exact form it would take.


(If I wanted to code in Python, and really wanted a switch statement, 
then I would do a syntax translator, which I have already experimented 
with in the past.


So I would write code in 'Python+switch', and translate to normal Python 
being running it. Then I get some of the benefits immediately. What I 
don't get however is the performance that could go with it if it was a 
real part of the language.)


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


Re: Case Statements

2016-03-19 Thread l0r0m0a0i0l
Gratified to see that with all this back-and-forth this thread still has a 
sense of humor.  Perhaps, we can all just agree to disagree? :)

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


Re: Case Statements

2016-03-19 Thread Gregory Ewing

Chris Angelico wrote:

So maybe it's a language guarantee that
hasn't been written down somewhere,


The Language Reference says:

  [the decorator] is invoked with the function object as the only argument.
  The returned value is bound to the function name instead of the function
  object.

The "instead" there seems to imply that the name is *not*
bound to the original function object. But it could perhaps
be made clearer.

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


Re: Case Statements

2016-03-19 Thread Antoon Pardon
Op 17-03-16 om 03:02 schreef Chris Angelico:
> On Thu, Mar 17, 2016 at 12:54 PM, Steven D'Aprano  wrote:
>
>> I wouldn't want to rely on it working with decorator syntax either. Even if
>> it does now, I'm not sure that's a language guarantee.
> That's the thing, though. It's not a guarantee, yet it does work in
> every Python interpreter that I tried it in.

That depends on what you mean by work. This failes:

def monkeypatch(cls):
orig = globals()[cls.__name__]
print("Monkeypatch",id(cls),"into",id(orig))
for attr in dir(cls):
if not attr.startswith("_"):
setattr(orig,attr,getattr(cls,attr))
return orig

def main():
class Foo:
def method1(self):
print("I am method 1")

print("Foo is currently",id(Foo))
some_object = Foo()

@monkeypatch
class Foo:
def method2(self):
print("I am method 2")

print("Foo is now",id(Foo))

some_object.method1()
some_object.method2()

main()


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


Re: Case Statements

2016-03-19 Thread Mark Lawrence

On 16/03/2016 13:38, Antoon Pardon wrote:

Op 16-03-16 om 12:07 schreef Mark Lawrence:


Raise the item on the python-ideas mailing list for the umpteenth time
then, and see how far you get.


I don't care enough. I do care about people using valid arguments.



Arguments have been made for and against.  When the PEPs were rejected 
are you saying that the arguments for acceptance were actually stronger 
than the arguments for rejection?


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

Mark Lawrence

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


Re: Case Statements

2016-03-19 Thread Antoon Pardon
Op 16-03-16 om 15:02 schreef Mark Lawrence:
> On 16/03/2016 13:38, Antoon Pardon wrote:
>> Op 16-03-16 om 12:07 schreef Mark Lawrence:
>>>
>>> Raise the item on the python-ideas mailing list for the umpteenth time
>>> then, and see how far you get.
>>
>> I don't care enough. I do care about people using valid arguments.
>>
>
> Arguments have been made for and against.  When the PEPs were rejected
> are you saying that the arguments for acceptance were actually
> stronger than the arguments for rejection?
>
No, I was just saying that your argument: "We've done without for 25
years" is invalid, because that would imply python should no longer make
any progress. Because any progress that will be made now, we've done
without for 25 years. -- Antoon

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


Re: Case Statements

2016-03-19 Thread Gregory Ewing

Steven D'Aprano wrote:

On Thu, 17 Mar 2016 11:31 am, Chris Angelico wrote:


   orig = globals()[cls.__name__]


I wouldn't want to rely on it working with decorator syntax either. Even if
it does now, I'm not sure that's a language guarantee.


The following idiom relies on similar behaviour:

@property
def x(self):
return self._x

@x.setter
def x(self, value):
self._x = value

That's taken from the official docs, so I don't think
this is likely to change any time soon.

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


Re: Case Statements

2016-03-19 Thread Mark Lawrence

On 16/03/2016 13:27, Steven D'Aprano wrote:

On Thu, 17 Mar 2016 12:15 am, l0r0m0a0...@gmail.com wrote:


What hath I wrought?



Dr Ray Stantz: Fire and brimstone coming down from the skies! Rivers and
seas boiling!

Dr Egon Spengler: Forty years of darkness! Earthquakes, volcanoes...

Winston Zeddemore: The dead rising from the grave!

Dr Peter Venkman: Human sacrifice, dogs and cats living together... mass
hysteria!



Much like the Marty Feldman weather forecast for the UK then :)

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

Mark Lawrence

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


Re: Case Statements

2016-03-19 Thread Marko Rauhamaa
Antoon Pardon :

> Op 16-03-16 om 20:27 schreef Marko Rauhamaa:
>> Antoon Pardon :
>>> Look at decorators. They don't provide functionality we wouldn't have
>>> without them. So we don't actually need them. Do you argue that
>>> introducing them wasn't progress?
>> I do.
>
> Way to miss the point.

Just answering your question.

> I am sure you can find your own examples if you search for them.

To your point, I have disliked Python's dunderitis. However, yesterday
Steven made me doubt my doubts by demonstrating a very promising
pipelining idea that makes use of __ror__. My imagination is running
wild with the possibilities.


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


Re: Case Statements

2016-03-19 Thread Steven D'Aprano
On Thu, 17 Mar 2016 11:31 am, Chris Angelico wrote:

> Yes... in theory. But try rewriting my example to avoid decorator
> syntax. It won't work, because of this line:
> 
> orig = globals()[cls.__name__]

That's a nasty, dirty piece of code, and I hope you are thoroughly ashamed
of having written it :-)

> It depends on the decorator being run before the name actually gets
> bound - which means the previous class is available to the decorator.
> You can't do that without decorator syntax, or messing around with
> multiple names.


I wouldn't want to rely on it working with decorator syntax either. Even if
it does now, I'm not sure that's a language guarantee.



-- 
Steven

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


Re: Case Statements

2016-03-19 Thread Antoon Pardon
Op 17-03-16 om 01:31 schreef Chris Angelico:
> On Thu, Mar 17, 2016 at 11:19 AM, Steven D'Aprano  wrote:
>> On Thu, 17 Mar 2016 10:14 am, Chris Angelico wrote:
>>
>>> On Thu, Mar 17, 2016 at 5:31 AM, Antoon Pardon
>>>  wrote:
 It can be yes. Look at decorators. They don't provide functionality
 we wouldn't have without them.
>>> Really? Okay, try implementing this without decorators:
>> [...]
>>> @monkeypatch
>>> class Foo:
>> [...]
>>
>>
>> I think Antoon is referring to decorator *syntax*, not the concept of
>> decorators in general. Decorator syntax is just syntactic sugar for:
>>
>>
>> class Foo:
>> ...
>>
>> Foo = monkeypatch(Foo)
>>
>> which has been valid all the way back to Python 1.0.
>>
> Yes... in theory. But try rewriting my example to avoid decorator
> syntax. It won't work, because of this line:
>
> orig = globals()[cls.__name__]
>
> It depends on the decorator being run before the name actually gets
> bound - which means the previous class is available to the decorator.
> You can't do that without decorator syntax, or messing around with
> multiple names.

So? That is an implementation detail. With a new features, functionality
can now be accessible in a way it was not before the feature. It still doesn't
add new functionality, which in this case was just transferring methods from
one class to an other.


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


Re: Case Statements

2016-03-19 Thread BartC

On 16/03/2016 11:07, Mark Lawrence wrote:


I don't want to discourage you too much, but I think that adding a
switch statement comes *very* low on the list of improvements we would
like to make in Python 3.5.

We should probably focus on speed ...


OK, you're coming round...


but I still very much doubt
we'll be adding a switch statement -- it's a "sexy" language design
issue


That's the first time I've heard a language feature common in C 
described as sexy.


--
Bartc

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


Re: Case Statements

2016-03-19 Thread Chris Angelico
On Thu, Mar 17, 2016 at 5:31 AM, Antoon Pardon
 wrote:
> It can be yes. Look at decorators. They don't provide functionality
> we wouldn't have without them.

Really? Okay, try implementing this without decorators:

def monkeypatch(cls):
orig = globals()[cls.__name__]
print("Monkeypatch",id(cls),"into",id(orig))
for attr in dir(cls):
if not attr.startswith("_"):
setattr(orig,attr,getattr(cls,attr))
return orig

class Foo:
def method1(self):
print("I am method 1")

print("Foo is currently",id(Foo))
some_object = Foo()

@monkeypatch
class Foo:
def method2(self):
print("I am method 2")

print("Foo is now",id(Foo))

some_object.method1()
some_object.method2()


Granted, this is an evil use of decorators, and possibly is exploiting
an undocumented behaviour of CPython, but still... :)

Porting this code to Python 2 is left as an exercise for the reader,
although it would be interesting to see how IronPython, Jython, and
other Pythons handle this. I've tried it in MicroPython and the
behaviour is exactly the same (save that type objects don't have a
__dict__, so I had to adjust the above code - but it's still
compatible with CPython and uPy). Haven't tried PyPy3 yet.

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


Re: Case Statements

2016-03-19 Thread Marko Rauhamaa
BartC :

> On 16/03/2016 14:31, Marko Rauhamaa wrote:
>> Scheme has this:
>
>> (case (die10)
>>   ((1 3 5 7 9)
>>=> (lambda (n)
>> n))
>>   (else
>>=> (lambda (n)
>> (/ n 2
>>
>> which maps 1, 3, 5, 7 and 9 onto themselves but halves 2, 4, 6, 8 and
>> 10.
>
> I don't get this; what does the lambda do here? Why not just yield
> either n or n/2?

Scheme is all about lambdas. They are everywhere. The margin of this
posting is too small for me to explain it.

>> As for a chained if/elif, Scheme as "cond:"
>
>> (cond
>>  ((windy?)
>>   (fly-kite))
>>  ((shining? sun)
>>   (go-out))
>>  ((raining?)
>>   (play-soccer))
>>  (else
>>   (read-book)))
>
> Which is like my Ruby case example. Simple and to the point. (Not sure
> of the significance of ?)

Scheme identifiers can contain punctuation characters. Functions that
return a boolean are conventionally given names that end in a question
mark. Functions that modify their arguments are conventionally given
names that end in an exclamation point.


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


Re: Case Statements

2016-03-19 Thread Antoon Pardon
Op 16-03-16 om 20:27 schreef Marko Rauhamaa:
> Antoon Pardon :
>
>> Look at decorators. They don't provide functionality we wouldn't have
>> without them. So we don't actually need them. Do you argue that
>> introducing them wasn't progress?
> I do.

Way to miss the point. Sure there will be people for which this particular
example doesn't work. The point is, that often enough progress in python
is not about introducing something new that is "actually needed" but about
making functionality that is already available more easily accessible.

I am sure you can find your own examples if you search for them.

-- 
Antoon.

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


Re: Case Statements

2016-03-19 Thread BartC

On 16/03/2016 09:51, Mark Lawrence wrote:

On 16/03/2016 09:35, Antoon Pardon wrote:



So I guess those who would like a case statement in Python can
only hope a core developer gets bitten by a nasty bug while using
one of those ways of simulating switches.



So that core developers can waste their time putting something into the
language that we've done without for 25 years, yes, that strikes me as
extremely worthwhile.



I've noticed that Python doesn't appear to have a way of putting 
separators into numeric literals. (Or if it does, I've no idea how). 
That means being able to write:


a = 1'000'000
b =   239_288
c = 0x7FFF```

depending on what separator is used. Despite waiting for it for 25 
years, would that be worthwhile or not? (And if not, why not? And if it 
is, perhaps other things can be too.)



Of course the change is actually trivial,


The above really is trivial (to anyone already familiar with the 
workings of the byte-code compiler).



as
BartC has all ready pointed out. The work involved is shown here
https://mail.python.org/pipermail/python-dev/2006-June/065827.html


That article appears to try to do without using a new switch byte-code, 
as the author doesn't see the point. My code to implement a 'switch' 
byte-code (for integer expression and constant integer case-expressions) 
is below.


Not shown is the support needed in the byte-code compiler (about 300 
lines in my case as it's a bit fiddly, but it's not a run-time cost).


For a Python version, it might be an idea to make use of the convention 
for constants (all-caps), then a streamlined switch could be on the cards.


global function k_switch:ref void =
int index,n,lower

n := getopnda
lower := getopndb

case sptr^.tag
when tint,ttype then
else
pcerror("switch not int")
esac

index:=(sptr++)^.value-lower

if u32(index)>=u32(n) then# out of range
return ref int((pcptr+n*2+4)^)
else
return ref int((pcptr+index*2+4)^)
fi
end


--
Bartc


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


Re: Case Statements

2016-03-19 Thread Steven D'Aprano
On Thu, 17 Mar 2016 05:48 pm, Chris Angelico wrote:

> On Thu, Mar 17, 2016 at 5:29 PM, Steven D'Aprano
>  wrote:
>> I don't think that property is a similar situation. I think what happens
>> here is that the first call to property sets:
>>
>> # @property def x...
>> x = property(x)
>>
>> Then the second decorator does:
>>
>> # @x.setter def x...
>> x = x.setter(x)
>>
>> which replaces x with a brand new property object.

A slight hitch, as you (Chris) has just identified:

By the time i go to call "x.setter", x has been replaced by "def x". Easily
fixed:

def x(self):
...

t = x = property(x)

def x(self, value):
...

x = t.setter(x)


> Okay. Let's try this.
[...]
> Decorators work. Now let's try NOT using decorators.

You are still using a decorator. You're just not using @ decorator syntax.


 class Demo:
> ... def x(self):
> ... print("Getting x")
> ... return 42
> ... x = property(x)
> ... def x(self, value):
> ... print("Setting x to", value)

Oops, there's the problem. "def x" re-binds the property object, as so this
line:

> ... x = x.setter(x)

fails.

But we can fix it like this:

def x(self):
print("Getting x")
return 42
x = property(x)
def y(self, value):
print("Setting x to", value)
x = x.setter(y)


> Since the 'def' line bound the undecorated function to the name 'x',
> the decoration underneath *fails*. The only way this could work would
> be with a temporary name for either the new function or the decorator:

Right! We seem to be repeating each other each other each other each other
each other each other.


> This is how CPython implements this (it evaluates the decoration
> expressions first, leaving them on the stack, then creates the
> function, then calls the decorators), but I don't see anywhere that
> this is guaranteed in the docs either - the only way I know this is
> current behaviour is from trying it (with dis.dis). The documented
> equivalence simply doesn't work.

It does work. You just have to be careful to not garbage collect objects
before you can use them :-)


> Note, by the way, that I am not in any way criticising the *behaviour*
> here. I don't think anything needs to be changed as regards
> functionality. And it's not even that big an issue as regards
> documentation. It's mainly just an esoteric curiosity.

I agree with that. It's an interesting corner case in the application of
decorators.




-- 
Steven

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


Re: Case Statements

2016-03-19 Thread Mark Lawrence

On 16/03/2016 13:15, l0r0m0a0...@gmail.com wrote:

What hath I wrought?



The Comfy Chair :)

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

Mark Lawrence

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


Re: Case Statements

2016-03-19 Thread Chris Angelico
On Thu, Mar 17, 2016 at 12:54 PM, Steven D'Aprano  wrote:
> On Thu, 17 Mar 2016 11:31 am, Chris Angelico wrote:
>
>> Yes... in theory. But try rewriting my example to avoid decorator
>> syntax. It won't work, because of this line:
>>
>> orig = globals()[cls.__name__]
>
> That's a nasty, dirty piece of code, and I hope you are thoroughly ashamed
> of having written it :-)

No, I am not ashamed of having written it. The file it's in is called
"evil.py" and it exists specifically to showcase bad uses of
decorators :)

>> It depends on the decorator being run before the name actually gets
>> bound - which means the previous class is available to the decorator.
>> You can't do that without decorator syntax, or messing around with
>> multiple names.
>
>
> I wouldn't want to rely on it working with decorator syntax either. Even if
> it does now, I'm not sure that's a language guarantee.

That's the thing, though. It's not a guarantee, yet it does work in
every Python interpreter that I tried it in. And that puts it on par
with dictionary iteration order - people will end up depending on it.
So while it's definitely not wise to deliberately depend on this (and
believe you me, there is nothing like this in any of my production
code!!), it's entirely possible that there's code out in the wild that
unwittingly does.

Anyway, it's just a fun thing to bring out when people start talking
about decorator equivalence. And even experienced Pythonistas can be
confused by it - I certainly was, when I first saw it. Fun fun.

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


Re: Case Statements

2016-03-19 Thread Chris Angelico
On Thu, Mar 17, 2016 at 4:45 PM, Gregory Ewing
 wrote:
> Steven D'Aprano wrote:
>>
>> On Thu, 17 Mar 2016 11:31 am, Chris Angelico wrote:
>>
>>>orig = globals()[cls.__name__]
>>
>>
>> I wouldn't want to rely on it working with decorator syntax either. Even
>> if
>> it does now, I'm not sure that's a language guarantee.
>
>
> The following idiom relies on similar behaviour:
>
> @property
> def x(self):
> return self._x
>
> @x.setter
> def x(self, value):
> self._x = value
>
> That's taken from the official docs, so I don't think
> this is likely to change any time soon.

Ooh, didn't think of that. So maybe it's a language guarantee that
hasn't been written down somewhere, and the "func = deco(func)"
version is a known-imperfect-equivalent, same as "for x in iter: yield
x" is an imperfect equivalent for "yield from iter".

It would be possible to support @x.setter by simply guaranteeing that
the decorator expression is evaluated prior to the function creation:

_tmp = x.setter # but without using an actual name
def x(self, value):
self._x = value
x = _tmp(x)

But I doubt the language needs to go to this level of finickiness. In
fact, all it really needs is an acknowledgement that there are corner
cases:

http://bugs.python.org/issue26576

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


Re: Case Statements

2016-03-19 Thread Marko Rauhamaa
BartC <b...@freeuk.com>:

> Yes, a few scripting languages can do interesting things with switch or
> case statements. Perl for example (where I think it is created out other
> language features, but it looks a regular part of the syntax).
>
> Even Ruby has one. It doesn't do anything 'sexy' with it, but it does
> have this:
>
>  case
>  when this
> 
>  when that
> 
>  when other
> ...
>  end

That's a different topic.

> which is exactly equivalent to if this... elif that... (when the tests
> are ordered), with one difference:
>
> Each test starts with "when", instead of "if" for the first and "elif"
> for subsequent ones. That makes it easier to reorder tests, temporarily
> comment out the first test, copy a test from elsewhere, insert a new
> first test (you get the idea).

That is no different from a chained if/elif.

Scheme has this:

   (case (* 2 3)
 ((2 3 5 7)
  'prime)
 ((1 4 6 8 9)
  'composite)
 (else
  'unknown))

It has something better than C even:

   (case (die10)
 ((1 3 5 7 9)
  => (lambda (n)
   n))
 (else
  => (lambda (n)
   (/ n 2

which maps 1, 3, 5, 7 and 9 onto themselves but halves 2, 4, 6, 8 and
10.

As for a chained if/elif, Scheme as "cond:"

   (cond
((windy?)
 (fly-kite))
((shining? sun)
 (go-out))
((raining?)
 (play-soccer))
(else
 (read-book)))

which also has a "=>" variant:

   (cond
((best-selling-book (this-year))
 => (lambda (book)
  (read book)))
(else
 (play wii pes08)))


Marko

PS What is a "scripting language?"
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Case Statements

2016-03-19 Thread Chris Angelico
On Thu, Mar 17, 2016 at 5:29 PM, Steven D'Aprano
 wrote:
> I don't think that property is a similar situation. I think what happens
> here is that the first call to property sets:
>
> # @property def x...
> x = property(x)
>
> Then the second decorator does:
>
> # @x.setter def x...
> x = x.setter(x)
>
> which replaces x with a brand new property object.

Okay. Let's try this.

>>> class Demo:
... @property
... def x(self):
... print("Getting x")
... return 42
... @x.setter
... def x(self, value):
... print("Setting x to", value)
...
>>> d = Demo()
>>> d.x
Getting x
42
>>> d.x = 1
Setting x to 1


Decorators work. Now let's try NOT using decorators.

>>> class Demo:
... def x(self):
... print("Getting x")
... return 42
... x = property(x)
... def x(self, value):
... print("Setting x to", value)
... x = x.setter(x)
...
Traceback (most recent call last):
  File "", line 1, in 
  File "", line 8, in Demo
AttributeError: 'function' object has no attribute 'setter'


Since the 'def' line bound the undecorated function to the name 'x',
the decoration underneath *fails*. The only way this could work would
be with a temporary name for either the new function or the decorator:

>>> class Demo:
... def x(self):
... print("Getting x")
... return 42
... x = property(x)
... decorator = x.setter
... def x(self, value):
... print("Setting x to", value)
... x = decorator(x)
... del decorator
...
>>> d = Demo()
>>> d.x
Getting x
42
>>> d.x = 1
Setting x to 1

This is how CPython implements this (it evaluates the decoration
expressions first, leaving them on the stack, then creates the
function, then calls the decorators), but I don't see anywhere that
this is guaranteed in the docs either - the only way I know this is
current behaviour is from trying it (with dis.dis). The documented
equivalence simply doesn't work.

Note, by the way, that I am not in any way criticising the *behaviour*
here. I don't think anything needs to be changed as regards
functionality. And it's not even that big an issue as regards
documentation. It's mainly just an esoteric curiosity.

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


Re: Case Statements

2016-03-19 Thread Marko Rauhamaa
Antoon Pardon :

> Look at decorators. They don't provide functionality we wouldn't have
> without them. So we don't actually need them. Do you argue that
> introducing them wasn't progress?

I do.


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


Re: Case Statements

2016-03-18 Thread Antoon Pardon
Op 17-03-16 om 09:57 schreef Marko Rauhamaa:
> Antoon Pardon :
>
>> Op 16-03-16 om 20:27 schreef Marko Rauhamaa:
>>> Antoon Pardon :
 Look at decorators. They don't provide functionality we wouldn't have
 without them. So we don't actually need them. Do you argue that
 introducing them wasn't progress?
>>> I do.
>> Way to miss the point.
> Just answering your question.

Just answering the question --- without regard for the context and the
purpose of the question --- sure is a way to miss the point.

-- 
Antoon.


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


Re: Case Statements

2016-03-18 Thread BartC

On 16/03/2016 14:31, Marko Rauhamaa wrote:

BartC :



Even Ruby has one.



  case
  when this
 
  when that



That's a different topic.


Yes but, if Ruby has it, why shouldn't Python? (Aren't they rivals or 
something?)



which is exactly equivalent to if this... elif that... (when the tests
are ordered), with one difference:



That is no different from a chained if/elif.


That's what I said, but it's an interesting, more symmetric alternative.


Scheme has this:



(case (die10)
  ((1 3 5 7 9)
   => (lambda (n)
n))
  (else
   => (lambda (n)
(/ n 2

which maps 1, 3, 5, 7 and 9 onto themselves but halves 2, 4, 6, 8 and
10.


I don't get this; what does the lambda do here? Why not just yield 
either n or n/2?



As for a chained if/elif, Scheme as "cond:"



(cond
 ((windy?)
  (fly-kite))
 ((shining? sun)
  (go-out))
 ((raining?)
  (play-soccer))
 (else
  (read-book)))


Which is like my Ruby case example. Simple and to the point. (Not sure 
of the significance of ?)


--
Bartc

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


Re: Case Statements

2016-03-18 Thread Antoon Pardon
Op 17-03-16 om 00:14 schreef Chris Angelico:
> def monkeypatch(cls):
> orig = globals()[cls.__name__]
> print("Monkeypatch",id(cls),"into",id(orig))
> for attr in dir(cls):
> if not attr.startswith("_"):
> setattr(orig,attr,getattr(cls,attr))
> return orig
>
> class Foo:
> def method1(self):
> print("I am method 1")
>
> print("Foo is currently",id(Foo))
> some_object = Foo()
>
> @monkeypatch
> class Foo:
> def method2(self):
> print("I am method 2")
>
> print("Foo is now",id(Foo))
>
> some_object.method1()
> some_object.method2()

This seems close enough as far as I am concerned.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

def monkeypatch(cls, orig):
print("Monkeypatch",id(cls),"into",id(orig))
for attr in dir(cls):
if not attr.startswith("_"):
setattr(orig,attr,getattr(cls,attr))
return orig

class Foo:
def method1(self):
print("I am method 1")

print("Foo is currently",id(Foo))
some_object = Foo()

class Foo2:
def method2(self):
print("I am method 2")

monkeypatch(Foo2, Foo)

print("Foo is now",id(Foo))

some_object.method1()
some_object.method2()

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


Re: Case Statements

2016-03-18 Thread Chris Angelico
On Thu, Mar 17, 2016 at 9:53 PM, Steven D'Aprano  wrote:
> On Thu, 17 Mar 2016 05:48 pm, Chris Angelico wrote:
>
>> Okay. Let's try this.
> [...]
>> Decorators work. Now let's try NOT using decorators.
>
> You are still using a decorator. You're just not using @ decorator syntax.

Oops, sorry. That was sloppy wording on my part. What I meant was
"decorator syntax".

The rest of your analysis was equally correct.

> But we can fix it like this:
>
> def x(self):
> print("Getting x")
> return 42
> x = property(x)
> def y(self, value):
> print("Setting x to", value)
> x = x.setter(y)

Oh... I thought x.setter() needed the name to be the same. Okay, in
that case it's not so hard. Doesn't need the messy temporaries of the
other option.

>> This is how CPython implements this (it evaluates the decoration
>> expressions first, leaving them on the stack, then creates the
>> function, then calls the decorators), but I don't see anywhere that
>> this is guaranteed in the docs either - the only way I know this is
>> current behaviour is from trying it (with dis.dis). The documented
>> equivalence simply doesn't work.
>
> It does work. You just have to be careful to not garbage collect objects
> before you can use them :-)

The "documented equivalence" is what's written here:

https://docs.python.org/3/reference/compound_stmts.html#function
"""
For example, the following code

@f1(arg)
@f2
def func(): pass

is equivalent to

def func(): pass
func = f1(arg)(f2(func))
"""

Saying "is equivalent to" implies a correlation that, in this case, is
imperfect. But to be fair, these kinds of edge cases are (a) only of
interest to language developers and the curious, and (b) exist in
quite a few places in the language. The correspondence between
operators and magic methods [1] has the same flaw; saying that xhttps://docs.python.org/3/reference/datamodel.html#object.__lt__
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Case Statements

2016-03-18 Thread Mark Lawrence

On 16/03/2016 11:16, BartC wrote:

On 16/03/2016 11:07, Mark Lawrence wrote:


I don't want to discourage you too much, but I think that adding a
switch statement comes *very* low on the list of improvements we would
like to make in Python 3.5.

We should probably focus on speed ...


OK, you're coming round...



No, those were the words of the BDFL, not me.  Further, please do not 
deliberately cut words to change the context. The original said quite 
clearly "We should probably focus on speed (or aspects of it, like 
startup)...".


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

Mark Lawrence

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


Re: Case Statements

2016-03-16 Thread Mark Lawrence

On 16/03/2016 10:52, Antoon Pardon wrote:

Op 16-03-16 om 10:51 schreef Mark Lawrence:

On 16/03/2016 09:35, Antoon Pardon wrote:

Op 16-03-16 om 09:47 schreef Mark Lawrence:




Same with switch. You can use a hash table etc. to simulate switches,
but only if the codeblocks are independent. Otherwise, if-elif chains
are the way to go. Command line parsing is a case where switch
statements are often used, e.g. in shell scripts.


I've seen at least six different ways of simulating switches, so those
people who want them, can have them.  if-elif chains are not likely to
kill any Python programmer.

I have no interest what other languages use switch/case statements
for, as we've on the PYTHON mailing list.


There once were multiple ways to simulate a conditional expression.
And it was generally thought that using if else statements instead
of a conditional expression was unlikely to kill any Python programmer.

But then one of the core developers was bitten by a nasty bug because
he was using one of those constructs that simulated a conditional
expression and soon enough Python had a conditional expression.

So I guess those who would like a case statement in Python can
only hope a core developer gets bitten by a nasty bug while using
one of those ways of simulating switches.



So that core developers can waste their time putting something into
the language that we've done without for 25 years, yes, that strikes
me as extremely worthwhile.


Do you think python should stop progressing? Because all progress
python wil make, will be done by putting something in the language
we've done without for 25 years.

That we have done without doesn't contradict it can be useful to have.



Raise the item on the python-ideas mailing list for the umpteenth time 
then, and see how far you get.  The last attempt that I can find starts 
here 
https://mail.python.org/pipermail/python-ideas/2014-April/027665.html. 
The BDFL reply at 
https://mail.python.org/pipermail/python-ideas/2014-April/027667.html was:-



I don't want to discourage you too much, but I think that adding a 
switch statement comes *very* low on the list of improvements we would 
like to make in Python 3.5.


We should probably focus on speed (or aspects of it, like startup),
language features that help porting Python 2 code to it (e.g. bytes
formatting), and things that improve the user experience of getting 
started with Python on a new machine (e.g. pip/venv). Or perhaps stdlib 
issues like an asyncio-infused variation of WSGI.


I've probably missed a few focus areas, but I still very much doubt 
we'll be adding a switch statement -- it's a "sexy" language design 
issue (like anonymous functions) but that's not what will help Python 
compete.



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

Mark Lawrence

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


Re: Case Statements

2016-03-16 Thread Antoon Pardon
Op 16-03-16 om 10:51 schreef Mark Lawrence:
> On 16/03/2016 09:35, Antoon Pardon wrote:
>> Op 16-03-16 om 09:47 schreef Mark Lawrence:
>>>
>>>>
>>>> Same with switch. You can use a hash table etc. to simulate switches,
>>>> but only if the codeblocks are independent. Otherwise, if-elif chains
>>>> are the way to go. Command line parsing is a case where switch
>>>> statements are often used, e.g. in shell scripts.
>>>
>>> I've seen at least six different ways of simulating switches, so those
>>> people who want them, can have them.  if-elif chains are not likely to
>>> kill any Python programmer.
>>>
>>> I have no interest what other languages use switch/case statements
>>> for, as we've on the PYTHON mailing list.
>>
>> There once were multiple ways to simulate a conditional expression.
>> And it was generally thought that using if else statements instead
>> of a conditional expression was unlikely to kill any Python programmer.
>>
>> But then one of the core developers was bitten by a nasty bug because
>> he was using one of those constructs that simulated a conditional
>> expression and soon enough Python had a conditional expression.
>>
>> So I guess those who would like a case statement in Python can
>> only hope a core developer gets bitten by a nasty bug while using
>> one of those ways of simulating switches.
>>
>
> So that core developers can waste their time putting something into
> the language that we've done without for 25 years, yes, that strikes
> me as extremely worthwhile.

Do you think python should stop progressing? Because all progress
python wil make, will be done by putting something in the language
we've done without for 25 years.

That we have done without doesn't contradict it can be useful to have.

-- 
Antoon.

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


Re: Case Statements

2016-03-16 Thread BartC

On 16/03/2016 04:06, Mario R. Osorio wrote:

On Tuesday, March 15, 2016 at 9:55:27 PM UTC-4, jj0ge...@gmail.com wrote:

You have apparently mistaken me for someone who's worried.  I don't use Python, I was 
just curious as to why a construct that is found, not only to be useful in 95% of other 
languages, but is generally considered more flexible and readable than the if-elif, was 
missing in Python.  (your link "Switch Statement Code Smell" not withstanding)

Have a great day :)


Switch and case statements are such a waste of time that, in order to 
understand them you have to mentally use if/elseif/else/endif statements. 
Furthermore, the concepts of switch and case could not even exist without the 
notion of if/elseif/else/endif statements. Why then, add an extra level of 
complication??.


You're understanding them wrong then. Switch can be used like a 
'computed go to', where you execute the nth statement of a selection, or 
select the nth value of a list /without needing to evaluate any of the 
others/.


Or it can be more general, where each statement or value in the 
selection has a corresponding 'case', and it will directly execute or 
select it according to the switch expression:


switch d:
case 1:
   n = p//8
   pal = 2
case 4:
   n = p//2
   pal=16
case 8:
   n = p
   pal = 256
case 16:
   n = p*2
case 24:
   n = p*3
case 32:
   n = p*4
   a = 1
else:
   raise ...

Sure, there are half a dozen ways of writing such code. But you don't 
want to think of it in terms if-elif where you first have to test all 
the other cases when d is 32, and have to keep writing 'd==' over and over.


And you don't want to take this straightforward bit of code and spread 
it over many functions and classes and methods; it's all here.


(BTW why does Python have 'elif' when if-else is all that is really needed?)


Go play with Java or Maybe C++. Have fun with their fancy if/elseif/else/endif 
statements oops, sorry, they call them switch and/or case statements.

Wish you the best and please lete us know if and when you have a deep fall 
through a breakeless case ...


C got those badly wrong. (It got a lot of things wrong.) That doesn't 
mean that switch, properly implemented, is bad.


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


Re: Case Statements

2016-03-16 Thread Mark Lawrence

On 16/03/2016 09:35, Antoon Pardon wrote:

Op 16-03-16 om 09:47 schreef Mark Lawrence:




Same with switch. You can use a hash table etc. to simulate switches,
but only if the codeblocks are independent. Otherwise, if-elif chains
are the way to go. Command line parsing is a case where switch
statements are often used, e.g. in shell scripts.


I've seen at least six different ways of simulating switches, so those
people who want them, can have them.  if-elif chains are not likely to
kill any Python programmer.

I have no interest what other languages use switch/case statements
for, as we've on the PYTHON mailing list.


There once were multiple ways to simulate a conditional expression.
And it was generally thought that using if else statements instead
of a conditional expression was unlikely to kill any Python programmer.

But then one of the core developers was bitten by a nasty bug because
he was using one of those constructs that simulated a conditional
expression and soon enough Python had a conditional expression.

So I guess those who would like a case statement in Python can
only hope a core developer gets bitten by a nasty bug while using
one of those ways of simulating switches.



So that core developers can waste their time putting something into the 
language that we've done without for 25 years, yes, that strikes me as 
extremely worthwhile.  Of course the change is actually trivial, as 
BartC has all ready pointed out. The work involved is shown here 
https://mail.python.org/pipermail/python-dev/2006-June/065827.html


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

Mark Lawrence

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


Re: Case Statements

2016-03-16 Thread Antoon Pardon
Op 16-03-16 om 09:47 schreef Mark Lawrence:
>
>>
>> Same with switch. You can use a hash table etc. to simulate switches,
>> but only if the codeblocks are independent. Otherwise, if-elif chains
>> are the way to go. Command line parsing is a case where switch
>> statements are often used, e.g. in shell scripts.
>
> I've seen at least six different ways of simulating switches, so those
> people who want them, can have them.  if-elif chains are not likely to
> kill any Python programmer.
>
> I have no interest what other languages use switch/case statements
> for, as we've on the PYTHON mailing list.

There once were multiple ways to simulate a conditional expression.
And it was generally thought that using if else statements instead
of a conditional expression was unlikely to kill any Python programmer.

But then one of the core developers was bitten by a nasty bug because
he was using one of those constructs that simulated a conditional
expression and soon enough Python had a conditional expression.

So I guess those who would like a case statement in Python can
only hope a core developer gets bitten by a nasty bug while using
one of those ways of simulating switches.

-- 
Antoon Pardon

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


Re: Case Statements

2016-03-16 Thread Marko Rauhamaa
Christian Gollwitzer :

> That happens indeed if one were to simulate polymorphism using switch
> statements, but not for other cases.

There are not many other cases. Decoding is the only generally valid
case I can think of.

> In Python, you need to go the other way round, you don't have a
> switch, but you can simulate it via function tables or polymorphism.

Let's look at one case that I routinely implement using switch
statements in C: finite state machines. The reaction of an entity to a
stimulus depends on the state of the entity. That clearly is a case of
polymorphism.

There there is the reaction to system errors. However, there usually are
not so many options to consider that one would yearn for a switch
statement:

try:
bytes = self.tcpconn.read()
except socket.error as e:
if e.errno == errno.EAGAIN:
raise incomplete
raise

What other cases do you have in mind?

> The difference between a switch and its simulation via function
> pointer tables etc. is the scope. In a true switch statement, the code
> blocks access the same variables. You can't truly simulate an if
> statement in Python [...] Same with switch. You can use a hash table
> etc. to simulate switches, but only if the codeblocks are independent.

Such assignments are usually done to an object's data attributes.
Closures have "self" accessible to them so they can naturally update
"self.x" in the polymorphic methods.

> Same with switch. You can use a hash table etc. to simulate switches,
> but only if the codeblocks are independent. Otherwise, if-elif chains
> are the way to go. Command line parsing is a case where switch
> statements are often used, e.g. in shell scripts.

You have the same thing in C:

 if (!strcmp(arg, "now"))
 do_it_now();
 else if (!strcmp(arg, "soon"))
 do_it_now();
 else if  (!strcmp(arg, "later"))
 do_it_later();
 else complain();


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


Re: Case Statements

2016-03-16 Thread Mark Lawrence

On 16/03/2016 08:13, Christian Gollwitzer wrote:

Am 16.03.16 um 05:26 schrieb Mark Lawrence:

So you would rather write something like:-

switch (x):
   case COW:
 moo()
 break

   case DUCK:
 quack()
 break

   default IDUNNO:
 panic()

than:-

x.makeNoise()


No sane person would do that. But just because you selected the worst
possible semantics (fallthrough/break) and the worst posible use case
(simulating polymorphism) doesn't mean that switches have no use. Code
like the above was used a lot in early GUI toolkits for C - Motif and
the Windows C API, for instance, use a gigantic switch to decide upon
incoming events. Now the strange statement in the switch discussion
makes sense:


I've never said that switches have no use. As the powers to be have 
decreed that they're not going into Python, and I fully agree with that 
decision, I just wish people would shut up about them, but the issue 
keeps cropping up.




"Typically, similar switch statements are scattered throughout a
program. If you add or remove a clause in one switch, you often have to
find and repair the others too."

That happens indeed if one were to simulate polymorphism using switch
statements, but not for other cases.

In Python, you need to go the other way round, you don't have a switch,
but you can simulate it via function tables or polymorphism.
The difference between a switch and its simulation via function pointer
tables etc. is the scope. In a true switch statement, the code blocks
access the same variables. You can't truly simulate an if statement in
Python, if it were missing:


I've no idea at all what you mean by the above.



 >>> def hi():
...  print "hi"
...
 >>> def yu():
...  print "yu"
...
 >>> hi() if 1>2 else yu()
yu
 >>> hi() if 2>1 else yu()
hi

This gives you, in principal, an if-then-else statement back. But you
can't do something like

if 1>2:
   a=3
else:
   b=2


The above appears to have crept into Python when you weren't looking.

C:\Users\Mark\Documents\MyPython>py -3
Python 3.5.1 (v3.5.1:37a07cee5969, Dec  6 2015, 01:54:25) [MSC v.1900 64 
bit (AMD64)] on win32

Type "help", "copyright", "credits" or "license" for more information.
>>> if 1>2:
...   a=2
... else:
...   b=3
...
>>> a
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'a' is not defined
>>> b
3



Same with switch. You can use a hash table etc. to simulate switches,
but only if the codeblocks are independent. Otherwise, if-elif chains
are the way to go. Command line parsing is a case where switch
statements are often used, e.g. in shell scripts.


I've seen at least six different ways of simulating switches, so those 
people who want them, can have them.  if-elif chains are not likely to 
kill any Python programmer.


I have no interest what other languages use switch/case statements for, 
as we've on the PYTHON mailing list.




 Christian



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

Mark Lawrence

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


Re: Case Statements

2016-03-16 Thread Christian Gollwitzer

Am 16.03.16 um 05:26 schrieb Mark Lawrence:

So you would rather write something like:-

switch (x):
   case COW:
 moo()
 break

   case DUCK:
 quack()
 break

   default IDUNNO:
 panic()

than:-

x.makeNoise()


No sane person would do that. But just because you selected the worst 
possible semantics (fallthrough/break) and the worst posible use case 
(simulating polymorphism) doesn't mean that switches have no use. Code 
like the above was used a lot in early GUI toolkits for C - Motif and 
the Windows C API, for instance, use a gigantic switch to decide upon 
incoming events. Now the strange statement in the switch discussion 
makes sense:


"Typically, similar switch statements are scattered throughout a 
program. If you add or remove a clause in one switch, you often have to 
find and repair the others too."


That happens indeed if one were to simulate polymorphism using switch 
statements, but not for other cases.


In Python, you need to go the other way round, you don't have a switch, 
but you can simulate it via function tables or polymorphism.
The difference between a switch and its simulation via function pointer 
tables etc. is the scope. In a true switch statement, the code blocks 
access the same variables. You can't truly simulate an if statement in 
Python, if it were missing:


>>> def hi():
...  print "hi"
...
>>> def yu():
...  print "yu"
...
>>> hi() if 1>2 else yu()
yu
>>> hi() if 2>1 else yu()
hi

This gives you, in principal, an if-then-else statement back. But you 
can't do something like


if 1>2:
  a=3
else:
  b=2

Same with switch. You can use a hash table etc. to simulate switches, 
but only if the codeblocks are independent. Otherwise, if-elif chains 
are the way to go. Command line parsing is a case where switch 
statements are often used, e.g. in shell scripts.


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


Re: Case Statements

2016-03-15 Thread Mark Lawrence

On 16/03/2016 01:55, jj0gen0i...@gmail.com wrote:

You have apparently mistaken me for someone who's worried.  I don't use Python, I was 
just curious as to why a construct that is found, not only to be useful in 95% of other 
languages, but is generally considered more flexible and readable than the if-elif, was 
missing in Python.  (your link "Switch Statement Code Smell" not withstanding)

Have a great day :)



So you would rather write something like:-

switch (x):
  case COW:
moo()
break

  case DUCK:
quack()
break

  default IDUNNO:
panic()

than:-

x.makeNoise()

?

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

Mark Lawrence

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


Re: Case Statements

2016-03-15 Thread Mario R. Osorio
On Tuesday, March 15, 2016 at 9:55:27 PM UTC-4, jj0ge...@gmail.com wrote:
> You have apparently mistaken me for someone who's worried.  I don't use 
> Python, I was just curious as to why a construct that is found, not only to 
> be useful in 95% of other languages, but is generally considered more 
> flexible and readable than the if-elif, was missing in Python.  (your link 
> "Switch Statement Code Smell" not withstanding)
> 
> Have a great day :)

Switch and case statements are such a waste of time that, in order to 
understand them you have to mentally use if/elseif/else/endif statements. 
Furthermore, the concepts of switch and case could not even exist without the 
notion of if/elseif/else/endif statements. Why then, add an extra level of 
complication??.

Go play with Java or Maybe C++. Have fun with their fancy if/elseif/else/endif 
statements oops, sorry, they call them switch and/or case statements.

Wish you the best and please lete us know if and when you have a deep fall 
through a breakeless case ... You must love debugging those ... they are fun, 
specially a 4:30am, with an hour and a half to deploy...
-- 
https://mail.python.org/mailman/listinfo/python-list


  1   2   >