Discussion:
When Is A High/Low-Level Language Not A High/Low-Level Language?
(too old to reply)
Lawrence D'Oliveiro
2024-08-16 05:58:10 UTC
Permalink
Here’s a little bit of Python code, from <https://gitlab.com/ldo/inotipy>:

info_type = infoptr.contents.info_type
infoptr = ct.cast \
(
infoptr,
ct.POINTER
(
{
FANOTIFY.EVENT_INFO_TYPE_FID : FANOTIFY.event_info_fid,
FANOTIFY.EVENT_INFO_TYPE_DFID_NAME : FANOTIFY.event_info_fid,
FANOTIFY.EVENT_INFO_TYPE_DFID : FANOTIFY.event_info_fid,
FANOTIFY.EVENT_INFO_TYPE_PIDFD : FANOTIFY.event_info_pidfd,
FANOTIFY.EVENT_INFO_TYPE_ERROR : FANOTIFY.event_info_error,
}[info_type]
)
)

That’s a conditional cast, based on a common header field, to the
appropriate struct type for that data block.

That’s not just a switch-expression, it’s a switch-expression
returning a type.
Steven G. Kargl
2024-08-17 02:40:23 UTC
Permalink
Post by Lawrence D'Oliveiro
info_type = infoptr.contents.info_type
infoptr = ct.cast \
(
infoptr,
ct.POINTER
(
{
FANOTIFY.EVENT_INFO_TYPE_FID : FANOTIFY.event_info_fid,
FANOTIFY.EVENT_INFO_TYPE_DFID_NAME : FANOTIFY.event_info_fid,
FANOTIFY.EVENT_INFO_TYPE_DFID : FANOTIFY.event_info_fid,
FANOTIFY.EVENT_INFO_TYPE_PIDFD : FANOTIFY.event_info_pidfd,
FANOTIFY.EVENT_INFO_TYPE_ERROR : FANOTIFY.event_info_error,
}[info_type]
)
)
That’s a conditional cast, based on a common header field, to the
appropriate struct type for that data block.
That’s not just a switch-expression, it’s a switch-expression
returning a type.
Who cares? So what? What does this have to do with C?
--
steve
Bart
2024-08-17 10:19:30 UTC
Permalink
Post by Lawrence D'Oliveiro
info_type = infoptr.contents.info_type
infoptr = ct.cast \
(
infoptr,
ct.POINTER
(
{
FANOTIFY.EVENT_INFO_TYPE_FID : FANOTIFY.event_info_fid,
FANOTIFY.EVENT_INFO_TYPE_DFID_NAME : FANOTIFY.event_info_fid,
FANOTIFY.EVENT_INFO_TYPE_DFID : FANOTIFY.event_info_fid,
FANOTIFY.EVENT_INFO_TYPE_PIDFD : FANOTIFY.event_info_pidfd,
FANOTIFY.EVENT_INFO_TYPE_ERROR : FANOTIFY.event_info_error,
}[info_type]
)
)
That’s a conditional cast, based on a common header field, to the
appropriate struct type for that data block.
That’s not just a switch-expression, it’s a switch-expression
returning a type.
So, something like:

i = a.b.c
a = cast(a, ptr({x.P:x.p, y.Q:y.q, z.R:z.r}[a]))

But as someone asked, what does this have to do with C, or anything at
all? Apart from being an apallingly bit of code.

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.

(Perhaps you're looking for 'match' in Python? Either that or
pre-evaluate the {...} expression elsewhere if the contents are fixed.)

If you're suggesting that a 'switch' (a real one) that returns a value
is 'high level', then a lower level language can do that too. (I think
that gnuC can do so, plus mine of course.)
Lawrence D'Oliveiro
2024-08-17 22:11:33 UTC
Permalink
... 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.)
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?
Bart
2024-08-17 23:20:49 UTC
Permalink
Post by Lawrence D'Oliveiro
... 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.
Post by Lawrence D'Oliveiro
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.)

The equivalent using 'switch' in one of my languages (or anything
expression-based that used any form of multi-way select) is this:

fun prnt(x) = (println x; x.len)

i := 3
a :=
switch i
when 1 then prnt("One")
when 2 then prnt("Two")
when 3 then prnt("Three")
else 0
end

println a

Output is:

Three
5

Only one branch has been evaluated. Plus there is a default value (it's
required). Also, since the index values here are in sequence, I can use
N-way select:

a := (i | prnt("One"), prnt("Two"), prnt("Three") | 0)

Same result. You can't use a list here plus normal indexing, as again
all elements would be evaluated.
Lawrence D'Oliveiro
2024-08-18 00:23:45 UTC
Permalink
Post by Bart
Post by Lawrence D'Oliveiro
... 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.
Post by Bart
Post by Lawrence D'Oliveiro
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?
def prnt(x): print(x); return len(x)
i=3 a={1:prnt("One"), 2:prnt("Two"), 3:prnt("Three")}[i]
print(a)
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]()
Post by Bart
(Also using a non-existent key gives an error.)
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»)()

You think this is somehow new to me? It’s all covered here:
<https://gitlab.com/ldo/python_topics_notebooks/-/blob/master/Simple%20Code-Shortening%20Idioms.ipynb>
Post by Bart
The equivalent using 'switch' in one of my languages ...
If you want an unlabelled switch, that’s covered in the above
notebook, too.
Bart
2024-08-18 00:45:48 UTC
Permalink
Post by Lawrence D'Oliveiro
Post by Bart
Post by Lawrence D'Oliveiro
... 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.
Post by Bart
Post by Lawrence D'Oliveiro
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?
def prnt(x): print(x); return len(x)
i=3 a={1:prnt("One"), 2:prnt("Two"), 3:prnt("Three")}[i]
print(a)
One Two Three 5
So 'prnt' has been called 3 times instance of just once. (Also using a
non-existent key gives an error.)
a = \
{
1 : lambda : prnt("One"),
2 : lambda : prnt("Two"),
3 : lambda : prnt("Three"),
}[i]()
Post by Bart
(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.
Post by Lawrence D'Oliveiro
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.
Lawrence D'Oliveiro
2024-08-18 01:59:30 UTC
Permalink
Post by Lawrence D'Oliveiro
Post by Bart
Post by Lawrence D'Oliveiro
Post by Bart
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.
Still not answering the question.
Bart
2024-08-18 11:32:08 UTC
Permalink
Post by Lawrence D'Oliveiro
Post by Lawrence D'Oliveiro
Post by Bart
Post by Lawrence D'Oliveiro
Post by Bart
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.
Still not answering the question.
What question was that? If you mean replacing that original lot of code,
I would just burn the lot.

It just would not exist in that form in any program of mine, but I would
need to see the bigger picture.

But if that code really needed to exist, you wouldn't write that junk
inline like that. At least wrap it in some function, with a name that
gives a clue as to what it does.

Ensure that that map is defined only once, rather than have to
reconstruct it each of the million times you end up performing this
assignment.

You are basically asking what I would do about pile of shit in the
middle of my living room. Move it to the bathroom at least!
Scott Lurndal
2024-08-20 15:05:40 UTC
Permalink
Which doesn't have anything to do with C. Take it elsewhere.
Kenny McCormack
2024-08-20 15:34:50 UTC
Permalink
Post by Scott Lurndal
Which doesn't have anything to do with C. Take it elsewhere.
Haven't you heard? Python is (now), like topicality itself, always
topical, everywhere.

You'll see Python brought up and discussed all over the Usenet.
--
When polled for who is/was the worst US president, the candidates (i.e. popular responses/suggestions) are usually:
(Andrew) Johnson, Buchanan, or Trump
When polled for who is/was the best US president, the candidates (i.e. popular responses/suggestions) are usually:
FDR, Lincoln, or Trump
Loading...