Sujet : Re: When Is A High/Low-Level Language Not A High/Low-Level Language?
De : bc (at) *nospam* freeuk.com (Bart)
Groupes : comp.lang.cDate : 18. Aug 2024, 01:45:48
Autres entêtes
Organisation : A noiseless patient Spider
Message-ID : <v9rg7r$23hh1$1@dont-email.me>
References : 1 2 3 4 5
User-Agent : Mozilla Thunderbird
On 18/08/2024 01:23, Lawrence D'Oliveiro wrote:
On Sun, 18 Aug 2024 00:20:49 +0100, Bart wrote:
On 17/08/2024 23:11, Lawrence D'Oliveiro wrote:
>
On Sat, 17 Aug 2024 11:19:30 +0100, Bart wrote:
>
... what does this have to do with C, or anything at all?
>
C is supposed to be the epitome of the low-level language that can do
bit-fiddling and unsafe type conversions and the like. This is an
example of an unsafe type conversion (offering a typesafe interface to
the caller, of course) done dynamically, in a language which is
generally considered to be “higher-level” than C.
>
In sum: types as first-class objects + low-level bit-fiddling = a
combination unavailable in traditional “low-level” languages like C.
>
Apart from being an apallingly bit of code.
>
How would you it less “apallingly”?
>
(This sentence no verb. Also speling.)
>
It's an adverb. Although there should have been two P's.
Still not answering the question.
However I can't see the switch-expression; there is a Dict
constructor, where all elements are evaluated, not just the one
selected. That is not how 'switch' works.
>
How does a switch-expression work, then? Can you give us an example?
>
Take this Python code that has a similar dict constructor:
>
def prnt(x): print(x); return len(x)
>
i=3 a={1:prnt("One"), 2:prnt("Two"), 3:prnt("Three")}[i]
>
print(a)
>
It selects the third element keyed with '3', but the output is:
>
One Two Three 5
>
So 'prnt' has been called 3 times instance of just once. (Also using a
non-existent key gives an error.)
So do it this way:
a = \
{
1 : lambda : prnt("One"),
2 : lambda : prnt("Two"),
3 : lambda : prnt("Three"),
}[i]()
(Also using a non-existent key gives an error.)
That gives you lazily called elements, but the lambdas still have to be evaluated! If you had 100 such lines, you'd still need to build a 100-element key-map (so executing 100 lots of LOAD_CONST and MAKE_FUNCTION) just so you can select one lambda.
Want a default case for your switch? Easy:
a = \
{
1 : lambda : prnt("One"),
2 : lambda : prnt("Two"),
3 : lambda : prnt("Three"),
}.get(i, lambda : «default»)()
I wouldn't call that easy. What, using a totally different syntax?
Plus it uses this new 'get' attribute. It's ugly.
For the switch example I used, only these two bytecode instructions are executed, to get to the bit of code you want to evaluate:
-----pushm i
-----switch 3 , 1
(followed by a jumptable, but that is constant data, not executable code)
If I have a loop calling your code with i ranging from 1 to 10 million (so usually it is invoking the default case, which I've changed to a numeric value), then CPython takes 5 seconds.
The equivalent in my interpreter is 0.15 seconds. (PyPy will take 0.5 seconds; still slower, but such a measurement is not meaningful anyway; my version will still be fast in the context of a real program; PyPy mainly does its thing with loops.)
So your Python solutions are both ugly, and slow, sorry.