Liste des Groupes | Revenir à cl c |
On 2024-07-11, Michael S <already5chosen@yahoo.com> wrote:On Wed, 10 Jul 2024 21:28:15 +0200
David Brown <david.brown@hesbynett.no> wrote:
On 10/07/2024 19:14, Michael S wrote:>On Wed, 10 Jul 2024 08:48:05 -0700
Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
bart <bc@freeuk.com> writes:
I earlier asked this:>
>
"So if arrays aren't passed by value in C, and they aren't
passed by reference, then how the hell ARE they passed?!"
They aren't. C allows lots of things to be passed as an
argument to a function: several varieties of numeric values,
structs, unions, and pointers, including both pointers to
object types and pointers to function types. C does not have a
way for a function to take an argument that is either an array
or a function. There is a way to take pointers to those
things, but not the things themselves. Arrays and functions
are second-class values in C.
I'd like to see an example of the language that permits
ahead-of-time compilation and has functions as first-class
values.
Haskell is the first the comes to mind for me, but you could pick
any compiled functional programming language.
I am by no means a Haskell expert, and I am not at all familiar
with the way the language is compiled. But it is quite clear that
it is an example of a language that has functions as first-class
objects, and which is ahead-of-time compiled. The example below
defines an int-to-int function "doubler", and also a
function-to-function function "doTwice", and a function quadrupler
that is defined as the result of applying the higher-order
function doTwice to doubler. These are all compiled to assembly.
<https://godbolt.org/z/Tb7hGYsdv>
module Example where
doubler :: Int -> Int
doubler x = 2 * x
doTwice :: (Int -> Int) -> (Int -> Int)
doTwice f x = f (f x)
quadrupler = doTwice doubler
shouldBeEighty = quadrupler 20
You can write much the same in C++ using lambdas (which are objects
and can be passed around and returned as such) and templates (which
are needed because the type of lambdas is hidden). Unfortunately,
this also means that the functions don't get individually generated
functions in assembly:
<https://godbolt.org/z/KvPWz3n8z>
auto doubler = [](int x) -> int { return 2 * x; };
auto doTwice = [](auto f) -> auto
{
return [f](int x) -> int { return f(f(x)); };
};
auto quadrupler = doTwice(doubler);
auto shouldBeEiqhty = quadrupler(20);
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;
}
}
Les messages affichés proviennent d'usenet.