• Threads across programming languages

    From Stefan Ram@21:1/5 to paavo@osa.pri.ee on Mon Apr 29 15:19:19 2024
    XPost: comp.lang.c

    paavo512 <paavo@osa.pri.ee> wrote or quoted:
    |Anyway, multithreading performance is a non-issue for Python so far as
    |the Python interpreter runs in a single-threaded regime anyway, under a |global GIL lock. They are planning to get rid of GIL, but this work is
    |still in development AFAIK. I'm sure it will take years to stabilize the |whole Python zoo without GIL.

    The GIL only prevents multiple Python statements from being
    interpreted simultaneously, but if you're waiting on inputs (like
    sockets), it's not active, so that could be distributed across
    multiple cores.

    With asyncio, however, you can easily handle the application
    for threads to "wait in parallel" for thousands of sockets in a
    single thread, and there are fewer opportunities for errors than
    with multithreading.

    Additionally, there are libraries like numpy that use true
    multithreading internally to distribute computational tasks
    across multiple cores. By using such libraries, you can take
    advantage of that. (Not to mention the AI libraries that have their
    work done in highly parallel fashion by graphics cards.)

    If you want real threads, you could probably work with Cython
    sometimes.

    Other languages like JavaScript seem to have an advantage there
    because they don't know a GIL, but with JavaScript, for example,
    it's because it always runs in a single thread overall. And in
    the languages where there are threads without a GIL, you quickly
    realize that programming correct non-trivial programs with
    parallel processing is error-prone.

    Often in Python you can use "ThreadPoolExecutor" to start
    multiple threads. If the GIL then becomes a problem (which is
    not the case if you're waiting on I/O), you can easily swap it
    out for "ProcessPoolExecutor": Then processes are used instead
    of threads, and there is no GIL for those.

    If four cores are available, by dividing up compute-intensive tasks
    using "ProcessPoolExecutor", you can expect a speedup factor of two
    to eight.

    With the Celery library, tasks can be distributed across multiple
    processes that can also run on different computers. See, for
    example, "Parallel Programming with Python" by Jan Palach.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paavo Helde@21:1/5 to Stefan Ram on Mon Apr 29 19:13:09 2024
    XPost: comp.lang.c

    On 29.04.2024 18:19, Stefan Ram wrote:
    paavo512 <paavo@osa.pri.ee> wrote or quoted:
    |Anyway, multithreading performance is a non-issue for Python so far as
    |the Python interpreter runs in a single-threaded regime anyway, under a |global GIL lock. They are planning to get rid of GIL, but this work is |still in development AFAIK. I'm sure it will take years to stabilize the |whole Python zoo without GIL.

    The GIL only prevents multiple Python statements from being
    interpreted simultaneously, but if you're waiting on inputs (like
    sockets), it's not active, so that could be distributed across
    multiple cores.

    With asyncio, however, you can easily handle the application
    for threads to "wait in parallel" for thousands of sockets in a
    single thread, and there are fewer opportunities for errors than
    with multithreading.

    In C++, async io is provided e.g. by the asio library.

    Just for waiting on thousands on sockets I believe a single select()
    call would be sufficient, no threads or asio is needed. But you probably
    meant something more.


    Additionally, there are libraries like numpy that use true
    multithreading internally to distribute computational tasks
    across multiple cores. By using such libraries, you can take
    advantage of that. (Not to mention the AI libraries that have their
    work done in highly parallel fashion by graphics cards.)

    If you want real threads, you could probably work with Cython
    sometimes.

    Huh, my goal is to avoid Python, not to work with it. Unfortunately this (avoiding Python) becomes harder all the time.


    Other languages like JavaScript seem to have an advantage there
    because they don't know a GIL, but with JavaScript, for example,
    it's because it always runs in a single thread overall. And in
    the languages where there are threads without a GIL, you quickly
    realize that programming correct non-trivial programs with
    parallel processing is error-prone.

    Been there, done that, worked through it ... 15 years ago. Nowadays
    non-trivial multi-threaded parallel processing in C++ seems pretty easy
    for me, one just needs to follow some principles and take care to get
    the details correct. I guess it's about the same as memory management in
    C, one can get it correct with taking some care. In C++ I can forget
    about memory management as it is largely automatic, but for
    multithreading I still need to take care.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Paavo Helde on Mon Apr 29 20:29:42 2024
    XPost: comp.lang.c

    On Mon, 29 Apr 2024 19:13:09 +0300, Paavo Helde wrote:

    Just for waiting on thousands on sockets I believe a single select()
    call would be sufficient ...

    We use poll(2) or epoll(2) nowadays. select(2) is antiquated.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Bonita Montero on Tue Apr 30 04:09:00 2024
    XPost: comp.lang.c

    On Tue, 30 Apr 2024 05:58:31 +0200, Bonita Montero wrote:

    Am 29.04.2024 um 22:31 schrieb Lawrence D'Oliveiro:

    On Mon, 29 Apr 2024 18:18:57 +0200, Bonita Montero wrote:

    But you need multithreading to have maximum throughput since you often
    process the data while other data is available.

    In a lot of applications, the bottleneck is the network I/O, or a GUI
    waiting for the next user event, that kind of thing. In this situation,
    multithreading is more trouble than it’s worth. This is why coroutines
    (in the form of async/await) have made a comeback over the last decade
    or so.

    Having a single thread and using state machines is more effortz.

    It would indeed. That’s why coroutines (async/await) are so handy.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Paavo Helde on Tue Apr 30 16:48:51 2024
    XPost: comp.lang.c

    Paavo Helde <eesnimi@osa.pri.ee> writes:
    On 29.04.2024 18:19, Stefan Ram wrote:
    paavo512 <paavo@osa.pri.ee> wrote or quoted:
    |Anyway, multithreading performance is a non-issue for Python so far as
    |the Python interpreter runs in a single-threaded regime anyway, under a
    |global GIL lock. They are planning to get rid of GIL, but this work is
    |still in development AFAIK. I'm sure it will take years to stabilize the
    |whole Python zoo without GIL.

    The GIL only prevents multiple Python statements from being
    interpreted simultaneously, but if you're waiting on inputs (like
    sockets), it's not active, so that could be distributed across
    multiple cores.

    With asyncio, however, you can easily handle the application
    for threads to "wait in parallel" for thousands of sockets in a
    single thread, and there are fewer opportunities for errors than
    with multithreading.

    In C++, async io is provided e.g. by the asio library.

    And the POSIX aio interfaces, on systems that support them.

    I used lio_listio heavily in Oracle's RDMS.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Wed May 1 07:09:09 2024
    XPost: comp.lang.c

    On Wed, 1 May 2024 06:29:40 -0000 (UTC), Blue-Maned_Hawk wrote:

    You don't need threads to get heisenbugs.

    They are particularly prone to them.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Bonita Montero on Wed May 1 07:09:31 2024
    XPost: comp.lang.c

    On Wed, 1 May 2024 06:53:21 +0200, Bonita Montero wrote:

    Am 29.04.2024 um 22:29 schrieb Lawrence D'Oliveiro:

    We use poll(2) or epoll(2) nowadays. select(2) is antiquated.

    Use Boost.ASIO.

    And what does that use?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Ross Finlayson on Thu May 2 06:48:42 2024
    XPost: comp.lang.c

    On Wed, 1 May 2024 20:09:48 -0700, Ross Finlayson wrote:

    So, the idea of the re-routine, is a sort of co-routine. That is, it
    fits the definition of being a co-routine, though as with that when its asynchronous filling of the memo of its operation is unfulfilled, it
    quits by throwing an exception, then is as expected to to called again,
    when its filling of the memo is fulfilled, thus that it returns.

    The normal, non-comedy way of handling this is to have the task await
    something variously called a “future” or “promise”: when that object is marked as completed, then the task is automatically woken again to fulfil
    its purpose.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Bonita Montero on Fri May 3 09:38:46 2024
    XPost: comp.lang.c

    On 02/05/2024 17:10, Bonita Montero wrote:
    Am 02.05.2024 um 15:53 schrieb David Brown:

    That is a /long/ way from treating functions as first-class objects.

    A C-style function is also a function-object in C++ because it has
    a calling operator.

    No it is not. C-style functions (or C++ functions for that matter) are
    not objects, and do not have calling operators. Built-in operators do
    not belong to a type, in the way that class operators do.


    But it is certainly a step in that direction, as are lambdas.

    Lambdas can be assigned to function<>-object to make them runtime -polymorphic. Otherwise they can be generic types, which are compile
    -time polymorphic - like the function-object for std::sort();


    You missed the point entirely. Lambdas can be used in many ways like functions, and it is possible for one function (or lambda) to return a different function, and can be used for higher-order functions
    (functions that have functions as parameters or return types). They do
    not mean that C++ can treat functions as first-class objects, but they
    /do/ mean that you can get many of the effects you might want if C++
    functions really were first-class objects.

    You also claimed that classes are first-class objects in C++.

    I never said that and having sth. like class Class in Java is
    beyond C++'s performance constraints.

    You repeatedly replied to Lawrence's posts confirming that you believed
    they were. (Re-read your posts in this thread.) I was fairly sure you
    were making completely unsubstantiated claims, but it was always
    possible you had thought of something interesting.

    I like C++, but it is absurd and unhelpful to claim it is something that
    it is not. Neither functions nor classes are first-class objects in
    C++. C++ is not, by any stretch of the imagination, a "fully featured functional programming language". It supports some functional
    programming techniques, which is nice, but that does not make it a
    functional programming language.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Bonita Montero on Fri May 3 11:18:06 2024
    XPost: comp.lang.c

    On 03/05/2024 09:58, Bonita Montero wrote:
    Am 03.05.2024 um 09:38 schrieb David Brown:

    No it is not.  C-style functions (or C++ functions for that matter)
    are not objects, and do not have calling operators.  Built-in
    operators do not belong to a type, in the way that class operators do.

    You can assign a C-style function pointer to an auto function-object.

    A C-style function /pointer/ is an object. A C-style /function/ is not.
    Do you understand the difference?

    That these function objects all have the same type doesn't metter.

    You missed the point entirely.  Lambdas can be used in many ways like
    functions, and it is possible for one function (or lambda) to return a
    different function, and can be used for higher-order functions
    (functions that have functions as parameters or return types).  They
    do not mean that C++ can treat functions as first-class objects, but
    they /do/ mean that you can get many of the effects you might want if
    C++ functions really were first-class objects.

    C-style functions and lambda-types are generically interchangeable.


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Michael S on Fri May 3 22:20:59 2024
    XPost: comp.lang.c

    On Fri, 3 May 2024 18:01:02 +0300, Michael S wrote:

    For C, I agree, mostly because C has no nested functions.

    GCC implements nested functions in the C compiler. Though oddly, not in C+
    +.

    I posted a C example using nested functions in the “Recursion, Yo” thread.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Michael S on Sat May 4 00:27:53 2024
    XPost: comp.lang.c

    On 03/05/2024 16:47, Michael S wrote:
    On Fri, 3 May 2024 17:20:00 +0200
    Bonita Montero <Bonita.Montero@gmail.com> wrote:

    Am 03.05.2024 um 17:05 schrieb Michael S:

    A typical scenario is that you started you python program while
    thinking that it wouldn't e CPU-intensive. And then it grew and
    became CPU-intensive.
    That's actually a good case, because it means that your program is
    used and is doing something worthwhile.

    I don't think it makes a big difference if Python has a GIL or
    not since it is interpreted and extremely slow with that anyway.


    64 times faster than slow wouldn't be fast, but could be acceptable.
    And 64 HW threads nowadays is almost low-end server, I have one at
    work, just in case.
    Also, I don't see why in the future Python could not be JITted.
    Javascript was also considered slow 15-20 years ago, now it's pretty
    fast.
    But then, my knowledge of Python is very shallow, Possibly, it's not
    JITted yet because of fundamental reasons rather than due to lack of
    demand.


    PyPy has been around for many years.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Michael S on Sun May 5 14:56:40 2024
    XPost: comp.lang.c

    On 04/05/2024 21:04, Michael S wrote:
    On Sat, 4 May 2024 00:27:53 +0100
    bart <bc@freeuk.com> wrote:

    On 03/05/2024 16:47, Michael S wrote:
    On Fri, 3 May 2024 17:20:00 +0200
    Bonita Montero <Bonita.Montero@gmail.com> wrote:

    Am 03.05.2024 um 17:05 schrieb Michael S:

    A typical scenario is that you started you python program while
    thinking that it wouldn't e CPU-intensive. And then it grew and
    became CPU-intensive.
    That's actually a good case, because it means that your program is
    used and is doing something worthwhile.

    I don't think it makes a big difference if Python has a GIL or
    not since it is interpreted and extremely slow with that anyway.


    64 times faster than slow wouldn't be fast, but could be acceptable.
    And 64 HW threads nowadays is almost low-end server, I have one at
    work, just in case.
    Also, I don't see why in the future Python could not be JITted.
    Javascript was also considered slow 15-20 years ago, now it's pretty
    fast.
    But then, my knowledge of Python is very shallow, Possibly, it's not
    JITted yet because of fundamental reasons rather than due to lack of
    demand.


    PyPy has been around for many years.

    I see.
    So, why PyPy didn't replace interpreter as a default engine?


    There are different Python implementations, useful for different
    situations. JIT is helpful if you need high performance running code
    and are happy to pay the time and memory resources (often very large)
    for doing the compilation. But often you don't need high performance,
    at least not from the Python code itself, and JIT is just a waste.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Paavo Helde on Mon May 6 15:13:16 2024
    Paavo Helde <eesnimi@osa.pri.ee> writes:

    On 04.05.2024 01:20, Lawrence D'Oliveiro wrote:

    On Fri, 3 May 2024 18:01:02 +0300, Michael S wrote:

    For C, I agree, mostly because C has no nested functions.

    GCC implements nested functions in the C compiler. Though oddly, not in C+ >> +.

    C++ already has functions nested in namespaces, namespaces nested in namespaces, functions nested in classes (static and non-static
    member functions), and classes nested in classes. It's already a
    lot of nesting, no need to complicate the matters more.

    C++ doesn't need nested functions because it has lambdas, which
    are effectively equivalent.

    (Disclaimer: I don't know if C++ calls them lambdas. I hope
    everyone understands to what I am referring.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paavo Helde@21:1/5 to Tim Rentsch on Tue May 7 08:41:01 2024
    On 07.05.2024 01:13, Tim Rentsch wrote:
    Paavo Helde <eesnimi@osa.pri.ee> writes:

    On 04.05.2024 01:20, Lawrence D'Oliveiro wrote:

    On Fri, 3 May 2024 18:01:02 +0300, Michael S wrote:

    For C, I agree, mostly because C has no nested functions.

    GCC implements nested functions in the C compiler. Though oddly, not in C+ >>> +.

    C++ already has functions nested in namespaces, namespaces nested in
    namespaces, functions nested in classes (static and non-static
    member functions), and classes nested in classes. It's already a
    lot of nesting, no need to complicate the matters more.

    C++ doesn't need nested functions because it has lambdas, which
    are effectively equivalent.

    Lambdas are better than nested functions as one can specify explicitly
    which variables are shared and how. One can be lazy and pass [&], but
    one doesn't have to.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Michael S on Mon May 13 00:43:38 2024
    XPost: comp.lang.c

    On Sun, 5 May 2024 12:37:18 +0300, Michael S wrote:

    As a code reader, I very much prefer C, where nested function are not
    allowed at all.

    The GNU C compiler allows them: see my example in the “Recursion, Yo” thread.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Lawrence D'Oliveiro on Mon May 13 15:04:50 2024
    XPost: comp.lang.c

    On Mon, 13 May 2024 00:43:38 -0000 (UTC)
    Lawrence D'Oliveiro <ldo@nz.invalid> wrote:

    On Sun, 5 May 2024 12:37:18 +0300, Michael S wrote:

    As a code reader, I very much prefer C, where nested function are
    not allowed at all.

    The GNU C compiler allows them: see my example in the “Recursion, Yo” thread.

    Which does not make it legal C. Or good ideea.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Paavo Helde on Mon May 13 19:43:37 2024
    Paavo Helde <eesnimi@osa.pri.ee> writes:

    On 07.05.2024 01:13, Tim Rentsch wrote:

    Paavo Helde <eesnimi@osa.pri.ee> writes:

    On 04.05.2024 01:20, Lawrence D'Oliveiro wrote:

    On Fri, 3 May 2024 18:01:02 +0300, Michael S wrote:

    For C, I agree, mostly because C has no nested functions.

    GCC implements nested functions in the C compiler. Though
    oddly, not in C++.

    C++ already has functions nested in namespaces, namespaces nested in
    namespaces, functions nested in classes (static and non-static
    member functions), and classes nested in classes. It's already a
    lot of nesting, no need to complicate the matters more.

    C++ doesn't need nested functions because it has lambdas, which
    are effectively equivalent.

    Lambdas are better than nested functions as one can specify explicitly
    which variables are shared and how. One can be lazy and pass [&], but
    one doesn't have to.

    To me that sounds like all the complications of nested functions,
    and more besides, and no real advantages. The choice of which
    variables to share is syntactic sugar, there is no difference
    in expressive power.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paavo Helde@21:1/5 to Tim Rentsch on Tue May 14 13:53:02 2024
    On 14.05.2024 05:43, Tim Rentsch wrote:
    Paavo Helde <eesnimi@osa.pri.ee> writes:

    On 07.05.2024 01:13, Tim Rentsch wrote:



    C++ doesn't need nested functions because it has lambdas, which
    are effectively equivalent.

    Lambdas are better than nested functions as one can specify explicitly
    which variables are shared and how. One can be lazy and pass [&], but
    one doesn't have to.

    To me that sounds like all the complications of nested functions,
    and more besides, and no real advantages. The choice of which
    variables to share is syntactic sugar, there is no difference
    in expressive power.

    Most of what programming languages do is syntactic sugar. For just
    writing Turing complete code one programming language would be enough.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to wij on Tue May 14 16:24:13 2024
    On 14/05/2024 13:46, wij wrote:
    On Tue, 2024-05-14 at 13:53 +0300, Paavo Helde wrote:
    On 14.05.2024 05:43, Tim Rentsch wrote:
    Paavo Helde <eesnimi@osa.pri.ee> writes:

    On 07.05.2024 01:13, Tim Rentsch wrote:



    C++ doesn't need nested functions because it has lambdas, which
    are effectively equivalent.

    Lambdas are better than nested functions as one can specify explicitly >>>> which variables are shared and how.  One can be lazy and pass [&], but >>>> one doesn't have to.

    To me that sounds like all the complications of nested functions,
    and more besides, and no real advantages.  The choice of which
    variables to share is syntactic sugar, there is no difference
    in expressive power.

    Most of what programming languages do is syntactic sugar. For just
    writing Turing complete code one programming language would be enough.


    The primary goal of high level language should be for reducing software development/maintenance cost.

    Yes. And the main way to do that is to reduce the risk of errors
    passing into later stages of development. A language (and the
    programmer using the language) should aim to make it easy to write good
    code, hard to write bad code, easy to see that good code is good, and
    easy to see that bad code is bad.

    "Syntactic sugar" is vital to this effort. And a key source of "power"
    of a language is not in what it allows you do to, but in what it stops
    you from doing, or allows you to restrict yourself. For example, often
    a correct program will work just as correctly, and just as efficiently,
    if all uses of "const" are removed. The "const" does not add to the
    things the language can do - it helps by restricting the errors you can
    make when using the language.

    So Tim is completely wrong to say that specifying the variables
    accessible in a lambda gives "no real advantages". It doesn't give the compiler's code /generator/ any more information than it can deduce
    itself from [&] or [=], but it gives more information to the compiler's
    code /checker/ and to human programmers - those are big advantages and
    greater expressive power.

    Cpp is just having too many 'syntactic sugars'
    (and keep on adding it) to be away from this goal, IMO.

    C++ is a very big language, and gains new features (in the language and standard library) every three years. While some features make it easier
    to write better code, backwards compatibility means it is rarely
    possible to remove features that are no longer necessary. Thus if you
    want to be able to read and understand all the syntax of C++, it gets
    more effort. But if you are in the position to be able to deal with C++
    code using only the features you find useful and like, then that is much
    less of an issue. It's primarily when dealing with smart-arse
    programmers like Bonita that it is a real problem. (But such
    programmers can also write smart-arse code in C and any other language
    they use.)

    Putting the 'expressivness' aside, I think cpp cannot complete with C and Assembly if measuring the compiled code size and speed. But I still like to program in cpp for my own reasons.


    If your C++ code is more than marginally slower than equivalent C code
    in situations where the speed is important, then you are using C++
    incorrectly. It's not uncommon for C++ to pull in a whole lot of extra
    library code, but that is rarely significant on PC's or other "big"
    computers.

    It is perhaps easier to accidentally write code that is big and slow in
    C++ than it is in C, but it is certainly not necessary.

    And while it occasionally makes sense to use assembly for the most time-critical parts of code, it is very common for clear, maintainable C
    or C++ code to be /faster/ than clear, maintainable assembly code.

    Unless you are dealing with something that makes use of processor
    instructions or features that are unknown to the C/C++ compiler, writing assembly code that is faster than C or C++ will often require such
    specific care for things like instruction scheduling, register pressure,
    cache prefetching, etc., than your results will be far from clear or maintainable. And by the time you've got it working, the end user has
    bought a new PC and the processor has different numbers of execution
    units and more specialised instructions. You can re-write much of the assembly, or you can re-compile your C/C++ with a different "-march=" flag.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paavo Helde@21:1/5 to wij on Tue May 14 23:34:43 2024
    On 14.05.2024 22:29, wij wrote:
    On Tue, 2024-05-14 at 16:24 +0200, David Brown wrote:


    So Tim is completely wrong to say that specifying the variables
    accessible in a lambda gives "no real advantages".  It doesn't give the
    compiler's code /generator/ any more information than it can deduce
    itself from [&] or [=], but it gives more information to the compiler's
    code /checker/ and to human programmers - those are big advantages and
    greater expressive power.

    Probably. I now still hesitate whether or not I should learn and adopt C++'s lambda expression. My consideration is that many new features after C++11
    are not really necessary and the burden may be greater than the gain for me.

    Lambda is in C++11, not after. Also note that some earlier things have
    been deprecated and removed from the later C++ versions, so instead of
    writing this good-and-old C++98 code like:

    endpoints.erase(std::remove_if(endpoints.begin(), endpoints.end(),
    std::not1(Ice::constMemFun(&EndpointI::datagram))),
    endpoints.end());

    one might now to have to use a lambda (or an extra function) instead:

    endpoints.erase(std::remove_if(endpoints.begin(), endpoints.end(),
    [](auto endpoint) {return !endpoint->datagram();}),
    endpoints.end());

    YMMV, but I like the lambda version more.



    Cpp is just having too many 'syntactic sugars'
    (and keep on adding it) to be away from this goal, IMO.

    C++ is a very big language, and gains new features (in the language and
    standard library) every three years.  While some features make it easier
    to write better code, backwards compatibility means it is rarely
    possible to remove features that are no longer necessary.  Thus if you
    want to be able to read and understand all the syntax of C++, it gets
    more effort.  But if you are in the position to be able to deal with C++
    code using only the features you find useful and like, then that is much
    less of an issue.

    I am not optimistic about the future of C++.


    It is perhaps easier to accidentally write code that is big and slow in
    C++ than it is in C, but it is certainly not necessary.

    My concern is that C++ codes typically consumes more memory much less proportional than the speed gain. Basically, time*space=constant, which is especially observable for computation intensive problems. I am more concerned about the cost of problem solving instead of plain code analysis.

    You have this feeling because with C++ one can solve much more complex
    tasks than in C. Solving more complex tasks often requires more run
    time, more memory, or both.

    Still, sometimes one can buy more speed by using more memory (cf quicksort).

    On the other hand, when processing very large arrays, using an
    unnecessarily large data type or too bloated structs can start to slow
    things down. But this has nothing to do with C++. If anything, C++ makes
    it easier to refactor the code to use a smaller datatype, or to have a templated version supporting multiple datatypes.

    Of course it is possible to write bloatware in C++. But I bet that when
    some program eats up all your computer memory, it will much more
    probably be a Java program, not C++ ;-)



    And while it occasionally makes sense to use assembly for the most
    time-critical parts of code, it is very common for clear, maintainable C
    or C++ code to be /faster/ than clear, maintainable assembly code.

    Unless you are dealing with something that makes use of processor
    instructions or features that are unknown to the C/C++ compiler, writing
    assembly code that is faster than C or C++ will often require such
    specific care for things like instruction scheduling, register pressure,
    cache prefetching, etc., than your results will be far from clear or
    maintainable.  And by the time you've got it working, the end user has
    bought a new PC and the processor has different numbers of execution
    units and more specialised instructions.  You can re-write much of the
    assembly, or you can re-compile your C/C++ with a different "-march=" flag.

    To me, there is no clear cut saying which (assembly or C/C++) is better just from the view point of common capabilities mutual to low/high level languages.
    (there are many capabilities C/C++ cannot do, typically involving hardware capabilities, virus, anti-interference, simulation,...)
    It all depends on what kind of application is desired.
    Generally, I feel software projects within 6-man-month are no difference from the language choice. One can also program assembly as fast.
    Those said, I retired earily (at about 37), I use C++ exclusively since then. Many are from my memory and what I received and my observations.

    In our current project codebase there were (are?) some historic pieces
    from coworkers before year 2000 who were also thinking assembler would
    be the best choice for their work. Their work has become obsolete 3
    times by now: when porting the code to Linux, when porting code to
    x86_64, and when porting code to ARM64. For the past 10 years we do not
    even compile the project in the original x86 mode any more.

    Guess what? Nobody in the team wanted to learn Linux, ARM and x86_64
    assemblers just for porting these small pieces of an existing program.
    The pieces were rewritten in C++ and the original assembler code was
    promptly forgotten. Good riddance!

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paavo Helde@21:1/5 to wij on Wed May 15 11:06:09 2024
    On 15.05.2024 03:31, wij wrote:
    On Tue, 2024-05-14 at 23:34 +0300, Paavo Helde wrote:

    Guess what? Nobody in the team wanted to learn Linux, ARM and x86_64
    assemblers just for porting these small pieces of an existing program.
    The pieces were rewritten in C++ and the original assembler code was
    promptly forgotten. Good riddance!

    Who would use assembly and consider porting to different, incompatible CPU/platforms?

    Of course the original developers did not consider porting the code to
    other platforms. Why not? I don't know. Lack of imagination, or not
    "planning for success"? Who knows.

    I have a better question: why should anybody choose to write a portion
    of software in assembler nowadays, if it can be written in a high level language instead?

    What is the real meaning of 'porting'? I think a C/C++ program for Window using
    its specific libraries is not easily ported to Linux where that libraries are not
    available. This kind of task is usually not really 'porting'.

    Porting means that the program could be used in the same way to achieve
    the same or similar results on another OS or hardware platform.
    Sometimes it is harder, sometimes easier. Adding a line of assembler or
    a vendor-trap typedef like DWORD is a sure way to make the porting
    harder. Using proper multi-platform libraries from the start will make
    the porting easier. Etc.

    Assembly has its bads, but considering the fact that writting assembly is basically the same as writting high level language except the compilation is done by human instead of automated by the compilation tools.
    The number of lines of assembly program is usually several times longer than high level language. But that is just appearance, the complexity is the same. Many of the extra works can be mechanically (or the like) solved.

    To be honest, I am a bit baffled we are having this kind of conversation
    so far into the 21-st century.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to wij on Wed May 15 11:20:45 2024
    On 14/05/2024 21:29, wij wrote:
    On Tue, 2024-05-14 at 16:24 +0200, David Brown wrote:
    On 14/05/2024 13:46, wij wrote:
    On Tue, 2024-05-14 at 13:53 +0300, Paavo Helde wrote:
    On 14.05.2024 05:43, Tim Rentsch wrote:
    Paavo Helde <eesnimi@osa.pri.ee> writes:

    On 07.05.2024 01:13, Tim Rentsch wrote:



    C++ doesn't need nested functions because it has lambdas, which
    are effectively equivalent.

    Lambdas are better than nested functions as one can specify explicitly >>>>>> which variables are shared and how.  One can be lazy and pass [&], but >>>>>> one doesn't have to.

    To me that sounds like all the complications of nested functions,
    and more besides, and no real advantages.  The choice of which
    variables to share is syntactic sugar, there is no difference
    in expressive power.

    Most of what programming languages do is syntactic sugar. For just
    writing Turing complete code one programming language would be enough. >>>>

    The primary goal of high level language should be for reducing software
    development/maintenance cost.

    Yes.  And the main way to do that is to reduce the risk of errors
    passing into later stages of development.  A language (and the
    programmer using the language) should aim to make it easy to write good
    code, hard to write bad code, easy to see that good code is good, and
    easy to see that bad code is bad.

    Sounds like Bjarne Stroustrup's tongue.

    I think it is a good aim for any programming language, so I am not
    surprised to see top language designers having similar opinions.

    (Whether or not you think a given language succeeds in these goals is
    another matter. And it's highly subjective, from experience,
    preferences, target applications and code type, and so on.)

    But I don't feel C++ is steering
    in that way. Since C++11 many features do not feel like what BS says in his book.

    OK. I think some are, some are not. There's no doubt, however, that
    some features added to C++ are obscure, hard to understand and use, but
    were made primarily to support improving features that are easier and
    commonly used. An example is rvalue references - they can often seem
    weird and it's not easy to know when they are a good idea or not. But
    they make classes like std::vector<>, which are commonly used, more
    efficient.


    "Syntactic sugar" is vital to this effort.  And a key source of "power"
    of a language is not in what it allows you do to, but in what it stops
    you from doing, or allows you to restrict yourself.  For example, often
    a correct program will work just as correctly, and just as efficiently,
    if all uses of "const" are removed.  The "const" does not add to the
    things the language can do - it helps by restricting the errors you can
    make when using the language.

    I agree what you say, but pretty much every high level language would say
    the same (how about BASIC?).

    I agree with that, which is pretty much the point - that's why we have
    high level languages.

    I am more concerned about the practical side.

    Sure.


    So Tim is completely wrong to say that specifying the variables
    accessible in a lambda gives "no real advantages".  It doesn't give the
    compiler's code /generator/ any more information than it can deduce
    itself from [&] or [=], but it gives more information to the compiler's
    code /checker/ and to human programmers - those are big advantages and
    greater expressive power.

    Probably. I now still hesitate whether or not I should learn and adopt C++'s lambda expression. My consideration is that many new features after C++11
    are not really necessary and the burden may be greater than the gain for me.

    I like lambdas on occasion. I haven't found much use for them in my C++ programming, but that is probably just the kind of work I do using C++.
    I have had more use of them in my Python coding.

    But they are like any other tool - a bit odd and hard to grasp when you
    are unfamiliar with them, then you get the idea and they are just
    another tool in the box, ready to use when they are the best fit for the
    task in hand. Use them when they make the code clearer, don't use them
    when they make the code hard to follow.


    Cpp is just having too many 'syntactic sugars'
    (and keep on adding it) to be away from this goal, IMO.

    C++ is a very big language, and gains new features (in the language and
    standard library) every three years.  While some features make it easier
    to write better code, backwards compatibility means it is rarely
    possible to remove features that are no longer necessary.  Thus if you
    want to be able to read and understand all the syntax of C++, it gets
    more effort.  But if you are in the position to be able to deal with C++
    code using only the features you find useful and like, then that is much
    less of an issue.

    I am not optimistic about the future of C++.

    I am - there are some things, like reflection and contracts, that I
    think will be /very/ nice. But I also expect to see many new features
    that I won't have much use for, as always. No one uses everything in
    big languages.

    (When I started in embedded development, I worked in assembly. You
    could know /everything/ about the microcontroller you were using - every
    single instruction in the processor, every peripheral on the chip.
    /Every/ instruction executed by the microcontroller was one you wrote explicitly. It was nice to know everything. But such times are past,
    like it or not.)


    It's primarily when dealing with smart-arse
    programmers like Bonita that it is a real problem.  (But such
    programmers can also write smart-arse code in C and any other language
    they use.)

    Putting the 'expressivness' aside, I think cpp cannot complete with C and >>> Assembly if measuring the compiled code size and speed. But I still like to >>> program in cpp for my own reasons.


    If your C++ code is more than marginally slower than equivalent C code
    in situations where the speed is important, then you are using C++
    incorrectly.  It's not uncommon for C++ to pull in a whole lot of extra
    library code, but that is rarely significant on PC's or other "big"
    computers.

    It is perhaps easier to accidentally write code that is big and slow in
    C++ than it is in C, but it is certainly not necessary.

    My concern is that C++ codes typically consumes more memory much less proportional than the speed gain.

    I think it is hard to define "typically". But I think you will have to
    justify your claims here with some examples. (I don't mean detailed
    code or analysis, just rough descriptions of your thought processes here.)

    It's useful to remember that just about anything that can be written in
    C, can be written in C++ with /very/ little overhead. If you are
    concerned that using a std::vector<> will chew up excess memory compared
    to a manual call to malloc(), you can make the malloc() call in C++.
    You can also make it a bit safer and easier to use by wrapping it in a
    class and using a std::unique_ptr<> to ensure it gets freed at the right
    time. And you get this with no measurable extra cost.

    Basically, time*space=constant,

    Um, no, that is not generally true.

    But sometimes you can make trade-offs between speed and space (either
    data space or code space). Again, if you can choose a particular
    balance in C, you can choose the same balance in C++ - though the
    default, simpler or more idiomatic C++ code might have a different
    balance than you might have chosen in C.

    which is
    especially observable for computation intensive problems. I am more concerned about the cost of problem solving instead of plain code analysis.

    And while it occasionally makes sense to use assembly for the most
    time-critical parts of code, it is very common for clear, maintainable C
    or C++ code to be /faster/ than clear, maintainable assembly code.

    Unless you are dealing with something that makes use of processor
    instructions or features that are unknown to the C/C++ compiler, writing
    assembly code that is faster than C or C++ will often require such
    specific care for things like instruction scheduling, register pressure,
    cache prefetching, etc., than your results will be far from clear or
    maintainable.  And by the time you've got it working, the end user has
    bought a new PC and the processor has different numbers of execution
    units and more specialised instructions.  You can re-write much of the
    assembly, or you can re-compile your C/C++ with a different "-march=" flag.

    To me, there is no clear cut saying which (assembly or C/C++) is better just from the view point of common capabilities mutual to low/high level languages.
    (there are many capabilities C/C++ cannot do, typically involving hardware capabilities, virus, anti-interference, simulation,...)

    Sure - there are times that assembly is essential. But usually you try
    to minimise that in your code.

    It all depends on what kind of application is desired.
    Generally, I feel software projects within 6-man-month are no difference from the language choice. One can also program assembly as fast.

    There is a vague rule of thumb that people experienced in a programming language can write at roughly the same rate in terms of lines of code
    per unit time, and that bug rates are roughly proportional to the number
    of lines of code. It is a statistical pattern, not a law, but it is
    generally the case that it is more efficient for programmers to use the
    highest level language that is suitable for the task at hand, at least
    as far as the coding is concerned. (Things like system design,
    algorithm design, etc., are mostly independent of the programming
    language - if these dominate the development time, then the language
    makes little difference.)

    Those said, I retired earily (at about 37), I use C++ exclusively since then. Many are from my memory and what I received and my observations.



    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Paavo Helde on Wed May 15 14:24:03 2024
    On Tue, 14 May 2024 13:53:02 +0300
    Paavo Helde <eesnimi@osa.pri.ee> wrote:

    On 14.05.2024 05:43, Tim Rentsch wrote:
    Paavo Helde <eesnimi@osa.pri.ee> writes:

    On 07.05.2024 01:13, Tim Rentsch wrote:



    C++ doesn't need nested functions because it has lambdas, which
    are effectively equivalent.

    Lambdas are better than nested functions as one can specify
    explicitly which variables are shared and how. One can be lazy
    and pass [&], but one doesn't have to.

    To me that sounds like all the complications of nested functions,
    and more besides, and no real advantages. The choice of which
    variables to share is syntactic sugar, there is no difference
    in expressive power.

    Most of what programming languages do is syntactic sugar. For just
    writing Turing complete code one programming language would be enough.



    As far as I am concerned, the two most important thing that programming languages do are:
    1 - helping programmer to not repeat himself
    2 - automation of common tasks, which is also sort helping programmer to
    not repeat, but in this case to not repeat somebody else rather than
    himself
    These two are nutrients. The reset is sugar that can or can not improve productivity during later phases of maintenance, but does nothing to
    improve productivity during initial development and debugging.
    You can be right that sugar constitutes the bulk of the volume of
    programming language, but it does not make it more important than vital
    things.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paavo Helde@21:1/5 to wij on Wed May 15 20:46:24 2024
    On 15.05.2024 17:38, wij wrote:

    You are right in your concern, C++ language does not particularly consume more
    run-time memory than C. I was concerned about the abuse of container classes. std::list is mostly the case. For others, I should say those 'data structure' containing links, e.g. std::set. Because the ratio of speed gain and memory consumption is likely very low. C++ programmer should notice this point.

    Container classes in C++ have been through extreme scrutiny and are as efficient in speed and memory as any equivalent general purpose C
    solutions one can come up with.

    I guess you are worried about backlinks in std::list. But this is the
    smallest worry, the bigger one is that each node is allocated
    separately, these allocations and deallocations are slow and the
    resulting data structure has bad memory locality, which makes it slow to traverse.

    However, happily there is no need to use std::list as there are
    std::deque and std::vector. In 25 years with C++, I have not yet found a
    use case for std::list. I know there are some, but I have not
    encountered those.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paavo Helde@21:1/5 to Bonita Montero on Wed May 15 20:48:30 2024
    On 15.05.2024 07:25, Bonita Montero wrote:
    Am 14.05.2024 um 22:34 schrieb Paavo Helde:

    endpoints.erase(std::remove_if(endpoints.begin(), endpoints.end(),
        [](auto endpoint) {return !endpoint->datagram();}),
        endpoints.end());

    Better auto &endpoint.

    You are right. In the actual code there is `const auto&`, but I removed
    it from the post for brevity.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Michael S on Fri May 17 22:17:34 2024
    XPost: comp.lang.c

    On Mon, 13 May 2024 15:04:50 +0300, Michael S wrote:

    On Mon, 13 May 2024 00:43:38 -0000 (UTC) Lawrence D'Oliveiro
    <ldo@nz.invalid> wrote:

    On Sun, 5 May 2024 12:37:18 +0300, Michael S wrote:

    As a code reader, I very much prefer C, where nested function are not
    allowed at all.

    The GNU C compiler allows them: see my example in the “Recursion, Yo”
    thread.

    Which does not make it legal C. Or good ideea.

    Worthwhile comparing, though: the one using nested functions is 99 source lines; the one doing it in strictly standard C is 128 source lines. That’s nearly 30% more code to do the same thing.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Bonita Montero on Tue May 21 16:39:13 2024
    Bonita Montero <Bonita.Montero@gmail.com> writes:

    Am 14.05.2024 um 04:43 schrieb Tim Rentsch:

    To me that sounds like all the complications of nested functions,
    and more besides, and no real advantages. The choice of which
    variables to share is syntactic sugar, there is no difference
    in expressive power.

    Lambdas can reduce a lot of redundant code. [...]

    Your example is isomorphic to using nested functions.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Paavo Helde on Tue May 21 16:34:48 2024
    Paavo Helde <eesnimi@osa.pri.ee> writes:

    On 15.05.2024 03:31, wij wrote:
    [...]
    Assembly has its bads, but considering the fact that writting
    assembly is basically the same as writting high level language
    except the compilation is done by human instead of automated by
    the compilation tools. [...]

    Not so. It is well documented, and has been for something like
    fifty years, that writing code in a high-level language is about
    five times as productive as writing in assembly. There are very
    few programs that need even one percent of the code written in
    assembly.

    To be honest, I am a bit baffled we are having this kind of
    conversation so far into the 21-st century.

    You are a master of understatement.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Michael S on Tue May 21 19:26:11 2024
    Michael S <already5chosen@yahoo.com> writes:

    On Tue, 14 May 2024 13:53:02 +0300
    Paavo Helde <eesnimi@osa.pri.ee> wrote:

    On 14.05.2024 05:43, Tim Rentsch wrote:
    [comparing lambdas and nested functions]

    To me that sounds like all the complications of nested functions,
    and more besides, and no real advantages. The choice of which
    variables to share is syntactic sugar, there is no difference
    in expressive power.

    Most of what programming languages do is syntactic sugar. For
    just writing Turing complete code one programming language would
    be enough.

    As far as I am concerned, the two most important thing that
    programming languages do are:
    1 - helping programmer to not repeat himself
    2 - automation of common tasks, which is also sort helping
    programmer to not repeat, but in this case to not repeat somebody
    else rather than himself

    These two are nutrients. The reset is sugar that can or can not
    improve productivity during later phases of maintenance, but does
    nothing to improve productivity during initial development and
    debugging. You can be right that sugar constitutes the bulk of
    the volume of programming language, but it does not make it more
    important than vital things.

    Two comments. One, I think your list of two things is short
    changing some other attributes that are important, but this
    question is a much larger topic so for now I will leave it there.
    Two, I think it's important to understand that by the term
    "syntactic sugar" I mean only a thin syntactic layer over
    existing functionality. To illustrate, a while() statement can
    be viewed as syntactic sugar over a for() statement, but nested
    functions are not just syntactic sugar over ordinary C functions,
    or even over methods in C++. (I am using "nested functions" as
    more or less synonymous with lambda expressions.) Whether
    something is or isn't syntactic sugar is not the same as whether
    it adds something useful to the language; for example, I know
    that while() statements can be written using for(), but having
    while() in the language still adds linguistic utility, even
    though it's just syntactic sugar.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Paavo Helde on Tue May 21 20:27:35 2024
    Paavo Helde <eesnimi@osa.pri.ee> writes:

    On 14.05.2024 05:43, Tim Rentsch wrote:

    Paavo Helde <eesnimi@osa.pri.ee> writes:

    On 07.05.2024 01:13, Tim Rentsch wrote:



    C++ doesn't need nested functions because it has lambdas, which
    are effectively equivalent.

    Lambdas are better than nested functions as one can specify explicitly
    which variables are shared and how. One can be lazy and pass [&], but
    one doesn't have to.

    To me that sounds like all the complications of nested functions,
    and more besides, and no real advantages. The choice of which
    variables to share is syntactic sugar, there is no difference
    in expressive power.

    Most of what programming languages do is syntactic sugar.

    You must mean something different by "syntactic sugar" than I
    do.

    For just writing Turing complete code one programming language
    would be enough.

    That statement is true but irrelevant. C++ and PostScript
    are both Turing complete, but it's absurd to suggest that
    there are no significant differences between them.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paavo Helde@21:1/5 to Tim Rentsch on Wed May 22 11:43:15 2024
    On 22.05.2024 06:27, Tim Rentsch wrote:
    Paavo Helde <eesnimi@osa.pri.ee> writes:

    On 14.05.2024 05:43, Tim Rentsch wrote:

    Paavo Helde <eesnimi@osa.pri.ee> writes:

    On 07.05.2024 01:13, Tim Rentsch wrote:



    C++ doesn't need nested functions because it has lambdas, which
    are effectively equivalent.

    Lambdas are better than nested functions as one can specify explicitly >>>> which variables are shared and how. One can be lazy and pass [&], but >>>> one doesn't have to.

    To me that sounds like all the complications of nested functions,
    and more besides, and no real advantages. The choice of which
    variables to share is syntactic sugar, there is no difference
    in expressive power.

    Most of what programming languages do is syntactic sugar.

    You must mean something different by "syntactic sugar" than I
    do.

    Just to clarify, for example many programming languages have syntax for defining functions or subroutines, which IMO can be viewed as syntactic
    sugar over JMP/GOTO which could be used instead.

    What the heck, even having named variables is syntactic sugar over
    numeric memory slots. I recall the programs written for programmable calculators in 1980-s did not provide such a luxury as variable names.


    For just writing Turing complete code one programming language
    would be enough.

    That statement is true but irrelevant. C++ and PostScript
    are both Turing complete, but it's absurd to suggest that
    there are no significant differences between them.

    Absolutely agree, and most what makes them different is syntactic sugar.
    Adding numbers happens by the same CPU operations both in C++ and
    PostScript, but there is an enormous difference in how one has to write
    the orders to get these numbers added.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Paavo Helde on Sat Jun 1 21:03:49 2024
    Paavo Helde <eesnimi@osa.pri.ee> writes:

    On 22.05.2024 06:27, Tim Rentsch wrote:

    Paavo Helde <eesnimi@osa.pri.ee> writes:

    On 14.05.2024 05:43, Tim Rentsch wrote:

    Paavo Helde <eesnimi@osa.pri.ee> writes:

    On 07.05.2024 01:13, Tim Rentsch wrote:



    C++ doesn't need nested functions because it has lambdas, which
    are effectively equivalent.

    Lambdas are better than nested functions as one can specify explicitly >>>>> which variables are shared and how. One can be lazy and pass [&], but >>>>> one doesn't have to.

    To me that sounds like all the complications of nested functions,
    and more besides, and no real advantages. The choice of which
    variables to share is syntactic sugar, there is no difference
    in expressive power.

    Most of what programming languages do is syntactic sugar.

    You must mean something different by "syntactic sugar" than I
    do.

    Just to clarify, for example many programming languages have syntax
    for defining functions or subroutines, which IMO can be viewed as
    syntactic sugar over JMP/GOTO which could be used instead.

    What the heck, even having named variables is syntactic sugar over
    numeric memory slots. I recall the programs written for programmable calculators in 1980-s did not provide such a luxury as variable names.

    The problem here is that this notion of what "syntactic sugar"
    means would make the term almost meaningless. It is well-known
    that Turing completeness can be based on a very small number of
    primitive operations, and in fact, that number can be one. It's
    ridiculous to say all programming languages are just syntactic
    sugar over a single operation.

    Furthermore, this notion of "syntactic sugar" is at odds with
    widespread and common usage. Look up "Syntactic sugar" on
    Wikipedia.

    For just writing Turing complete code one programming language
    would be enough.

    That statement is true but irrelevant. C++ and PostScript
    are both Turing complete, but it's absurd to suggest that
    there are no significant differences between them.

    Absolutely agree, and most what makes them different is syntactic
    sugar.

    That is utter nonsense. No one else thinks that.

    Adding numbers happens by the same CPU operations both in C++ and
    PostScript, but there is an enormous difference in how one has to
    write the orders to get these numbers added.

    That's completely beside the point. To give one example, C++
    has exceptions, and C does not. There is no simple and direct
    mapping from C++ exceptions to the C language. There is no
    modest syntactic layer that could be put on top of C so that
    it would then have exceptions. The gap is semantic, not just
    syntactic. What you are saying is that they are operationally
    equivalent. Sure, but the transformation to get from one to
    the other is a lot more than just syntax. That is the point
    of the phrase SYNTACTIC sugar - it means only a modest difference
    that is purely syntactic, and not involving significant semantic
    disparities.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to wij on Mon Jun 3 19:30:05 2024
    wij <wyniijj5@gmail.com> writes:

    On Tue, 2024-05-14 at 16:24 +0200, David Brown wrote:

    On 14/05/2024 13:46, wij wrote:

    On Tue, 2024-05-14 at 13:53 +0300, Paavo Helde wrote:

    On 14.05.2024 05:43, Tim Rentsch wrote:

    Paavo Helde <eesnimi@osa.pri.ee> writes:

    On 07.05.2024 01:13, Tim Rentsch wrote:



    C++ doesn't need nested functions because it has lambdas, which
    are effectively equivalent.

    Lambdas are better than nested functions as one can specify explicitly >>>>>> which variables are shared and how. One can be lazy and pass [&], but >>>>>> one doesn't have to.

    To me that sounds like all the complications of nested functions,
    and more besides, and no real advantages. The choice of which
    variables to share is syntactic sugar, there is no difference
    in expressive power.

    Most of what programming languages do is syntactic sugar. For just
    writing Turing complete code one programming language would be enough.

    The primary goal of high level language should be for reducing software
    development/maintenance cost.

    Yes. And the main way to do that is to reduce the risk of errors
    passing into later stages of development. A language (and the
    programmer using the language) should aim to make it easy to write good
    code, hard to write bad code, easy to see that good code is good, and
    easy to see that bad code is bad.

    Sounds like Bjarne Stroustrup's tongue. But I don't feel C++ is steering
    in that way. Since C++11 many features do not feel like what BS says in his book.

    "Syntactic sugar" is vital to this effort. And a key source of "power"
    of a language is not in what it allows you do to, but in what it stops
    you from doing, or allows you to restrict yourself. For example, often
    a correct program will work just as correctly, and just as efficiently,
    if all uses of "const" are removed. The "const" does not add to the
    things the language can do - it helps by restricting the errors you can
    make when using the language.

    I agree what you say, but pretty much every high level language would say
    the same (how about BASIC?). I am more concerned about the practical side.

    So Tim is completely wrong to say that specifying the variables
    accessible in a lambda gives "no real advantages". It doesn't give the
    compiler's code /generator/ any more information than it can deduce
    itself from [&] or [=], but it gives more information to the compiler's
    code /checker/ and to human programmers - those are big advantages and
    greater expressive power.

    Besides being self-centered, rude, arrogant, and generally careless
    in both his thinking and his writing, David Brown has misunderstood
    the meaning of my comments above.

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