The Cost of Dynamism (was Re: Pyhon 2.x or 3.x, which is faster?)

BartC bc at freeuk.com
Tue Mar 15 07:52:18 EDT 2016


On 15/03/2016 01:55, Steven D'Aprano wrote:
> On Tue, 15 Mar 2016 04:53 am, BartC wrote:


>> I get it. The author doesn't like switch statements!
>
> I don't think you do -- there's no "the author". It's a wiki. There's
> potentially *thousands* of "authors". The page you (might have) read is a
> discussion between many different people, debating the pros and cons of
> switches.

I got the impression it was mostly cons, and that everyone was keen to 
replace them with OO constructs.

>> But they can be a succinct and convenient way of expressing some code
>> patterns.

> One of the problems with switch statements is that they are *anything but*
> succinct. Compare this:
>
>> switch X
>> when A,B   then S1
>> when C     then S2
>> when D,E,F then S3
>> else            S4
>> end switch
>
> to the object-oriented solution, using polymorphism:
>
> X.foo()
>
> where foo returns S1, S2, ... S4 as appropriate, according to the type of X.

(1) X.foo only looks more succinct because you've conveniently removed 
A..F and S1..S4. Presumably they have to be provided somewhere else.

(2) My version switches on the *value* of X not the type. (Except of 
course when you use switch type(X) then X.foo() might be better, *if* 
you've done the prerequisite work of setting up the classes and methods 
needed.)

> there have been two proposals to introduce a
> switch/case statement to Python, including one by Guido himself.
>
> https://www.python.org/dev/peps/pep-3103/

Which starts by saying it's been rejected. But when you read the rest, 
you can sort of understand why! So many complications are put forward, 
and some half-depend on the introduction of constants, that there is no 
clear single solution. It comes across as a mess.

>> The typical characteristics - when A to F are known at compile-time - are:
>>
>> * X is only evaluated once
>
> That's easy to emulate with a temporary variable.

You mean when X is complex? Sure, but Python is such that even with a 
local temporary, evaluating LOAD_FAST is needed before each test, with 
all the reference counting that goes with it. And a STORE_FAST before 
the lot. (And some switch statements may be outside a function.)

(My byte-code uses special switch compare operators that leave the test 
value on the stack.)

>> * None of A to F need to be evaluated
>> * Only a single test is needed, no matter how many case expressions
>
> How does the compiler know which case matches from a single test?
>
> I think that you might be assuming that the switch statement uses a jump
> table. In your case, since you wrote the language, you might be right, but
> that's certainly not the case in general.

Not in general, but, in my code at least, testing an integer value 
against a set of integer constants (literals, enums, named constants) is 
used extensively. And things such as enums tend to have a compact span 
of values.

And where a jump-table is not possible, then you just have to locate one 
integer value within a list of constant integers (with a label 
associated with each), and there are many ways to do that. Via hashing 
for example, which would be done in the interpreter and would still 
count as a single test.

> But of course, in Python any switch statement would have to support values
> of any and every type, not just integers. So any implementation you are
> thinking of would have to support cases like this:
>
>
> switch obj:
>      case "Hello", None: ...
>      case [1, 2, 3]: ...
>      case 23.01, 15+2j, Fraction(10, 11): ...
>      case 100**100, {}: ...
>
>
> and more. This is not negotiable: having a switch statement limited to small
> ints is simply not an option.

Not a problem: http://pastebin.com/qdQintSZ

> This syntax I find interesting, although it is rather limited in that you
> can only switch on integers:

(I use switch-when for integer-only and case-when for anything else, or 
when a jumptable is not viable. See above paste.)

>> Here's another pattern, which can also be implemented with an underlying
>> switch:
>>
>>    X = (N |A, B, C, ... |Z)
>>
>> This selects the N'th value from A, B, C (in Python, probably 0-based).
>> Z is the default if N is out of range. A, B, C can be any expressions.
>>
>> The main characteristic is that only *one* of A, B, C  or Z evaluated,
>> which is the difference between just using a list.
>
> Are there any well-known languages which support this or similar syntax?

I pinched this syntax from Algol-68. (I think 'when' comes from Ada.)

> Of course, the syntax won't work in Python, because ( ... ) is already used
> for tuples, and N|A would be ambiguous with bitwise-or. The closest we have
> in Python would be:

Is ¦ available? Then (N¦A,B,C¦Z) would work, but is more fiddly to type. 
But the syntax is not important; you could just use:

    select n in a,b,c,d else z

(I think Algol68, when not using the compact form, used case n in a,b,c 
out z esac or some such thing.)

-- 
Bartc






More information about the Python-list mailing list