• When Is A High/Low-Level Language Not A High/Low-Level Language?

    From Lawrence D'Oliveiro@21:1/5 to All on Fri Aug 16 05:58:10 2024
    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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Steven G. Kargl@21:1/5 to Lawrence D'Oliveiro on Sat Aug 17 02:40:23 2024
    On Fri, 16 Aug 2024 05:58:10 +0000, Lawrence D'Oliveiro wrote:

    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.

    Who cares? So what? What does this have to do with C?

    --
    steve

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Lawrence D'Oliveiro on Sat Aug 17 11:19:30 2024
    On 16/08/2024 06:58, Lawrence D'Oliveiro wrote:
    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.


    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.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Bart on Sat Aug 17 22:11:33 2024
    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.)

    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?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Lawrence D'Oliveiro on Sun Aug 18 00:20:49 2024
    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.


    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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Lawrence D'Oliveiro on Sun Aug 18 01:45:48 2024
    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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Bart on Sun Aug 18 00:23:45 2024
    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.)

    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>

    The equivalent using 'switch' in one of my languages ...

    If you want an unlabelled switch, that’s covered in the above
    notebook, too.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Bart on Sun Aug 18 01:59:30 2024
    On Sun, 18 Aug 2024 01:45:48 +0100, Bart wrote:

    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:

    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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bart@21:1/5 to Lawrence D'Oliveiro on Sun Aug 18 12:32:08 2024
    On 18/08/2024 02:59, Lawrence D'Oliveiro wrote:
    On Sun, 18 Aug 2024 01:45:48 +0100, Bart wrote:

    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:

    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!

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Lawrence D'Oliveiro on Tue Aug 20 15:05:40 2024
    Lawrence D'Oliveiro <[email protected]d> writes:
    Here’s a little bit of Python code, from <https://gitlab.com/ldo/inotipy>:


    Which doesn't have anything to do with C. Take it elsewhere.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kenny McCormack@21:1/5 to Scott Lurndal on Tue Aug 20 15:34:50 2024
    In article <8h2xO.583703$qO%[email protected]>,
    Scott Lurndal <[email protected]> wrote:
    Lawrence D'Oliveiro <[email protected]d> writes:
    Heres a little bit of Python code, from <https://gitlab.com/ldo/inotipy>:


    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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)