Path: ...!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: bart Newsgroups: comp.lang.c Subject: =?UTF-8?Q?Re=3A_technology_discussion_=E2=86=92_does_the_world_need?= =?UTF-8?B?IGEgIm5ldyIgQyA/?= Date: Thu, 11 Jul 2024 11:17:04 +0100 Organization: A noiseless patient Spider Lines: 87 Message-ID: References: <87h6d2uox5.fsf@nosuchdomain.example.com> <20240707164747.258@kylheku.com> <877cdur1z9.fsf@bsb.me.uk> <871q42qy33.fsf@bsb.me.uk> <87ed82p28y.fsf@bsb.me.uk> <87r0c1nzjj.fsf@bsb.me.uk> <86ikxd8czu.fsf@linuxsc.com> <20240710201454.0000527e@yahoo.com> <20240711111357.00007712@yahoo.com> <20240711012852.856@kylheku.com> <20240711121502.0000614e@yahoo.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Injection-Date: Thu, 11 Jul 2024 12:17:05 +0200 (CEST) Injection-Info: dont-email.me; posting-host="92757c0b3eb137c08e71ba54311788f0"; logging-data="2532087"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/HXj0mREuL2q3TpTSxx9Qr" User-Agent: Mozilla Thunderbird Cancel-Lock: sha1:kvMTEuahxCQ3DL0fbuMoUB4f/7A= Content-Language: en-GB In-Reply-To: <20240711121502.0000614e@yahoo.com> Bytes: 4802 On 11/07/2024 10:15, Michael S wrote: > On Thu, 11 Jul 2024 08:41:14 -0000 (UTC) > Kaz Kylheku <643-408-1753@kylheku.com> wrote: > >> On 2024-07-11, Michael S wrote: >>> I fail to see a material difference between first class function >>> values in Haskell and C++ and first class function pointer values >>> in C: >>> >>> int doubler(int x) { >>> return x*2; >>> } >>> int doTwice(int (*foo)(int), int x) { >>> return foo(foo(x)); >>> } >>> int quadrupler(int x) { >>> return doTwice(doubler, x); >>> } >>> >>> I am willing to believe that the difference exists, but your >>> example is too basic to demonstrate it. >> >> First class functions could do something like this: >> >> // multiplier takes a coefficient and returns a pointer to >> // function >> >> int (*multiplier(int coefficient))(int) { >> // fantasy lambda syntax. Return type int is written after >> // parameter list. >> return lambda(int x) int { >> return coefficient * x; >> } >> } >> >> int (*doubler)(int) = multiplier(2); >> >> int x = doubler(42); // x becomes 84 >> >> Even though the lambda is returned out of multiplier, whose execution >> terminates, when the returned function is invoked, it can refer to the >> coefficient, which is captured in a lexical closure. >> >> With a C-like typedef, we can declutter the definition of mutiplier: >> >> typedef int (*int_int_fn)(int); >> >> int_int_fn multiplier(int coefficient) { >> return lambda(int x) int { >> return coefficient * x; >> } >> } >> > > Thank you. > Your example confirms my suspicion that the difference between first > and second class of functions doesn't become material until language > supports closures. > There are multiple classes of functions. Closures are part of it but there are several versions of closures too: Reference Closure Normal functions - - Function pointers Y - Anonymous functions Y - Anonymous functions Y 1 Anonymous functions Y 2 Anonymous functions Y ... C supports the first two, as does my static language. My dynamic language supports the first 3 (and can emulate the next couple of levels) With closures, they can have different capabilities (as you discover when you manage to implement something that runs the simpler Wikipedia examples, then move on to the next which fails). For example, in managing to still work after the containing function in the above example returns. Or in being able to update that 'coefficient' variable in a still-active enclosing function. Whatever you do, there will exist a more elaborate, subtler example that will fail. But it will also be one that few can understand or predict anyway.