How to resolve the algorithm First-class functions step by step in the C programming language
How to resolve the algorithm First-class functions step by step in the C programming language
Table of Contents
Problem Statement
A language has first-class functions if it can do each of the following without recursively invoking a compiler or interpreter or otherwise metaprogramming:
Write a program to create an ordered collection A of functions of a real number. At least one function should be built-in and at least one should be user-defined; try using the sine, cosine, and cubing functions. Fill another collection B with the inverse of each function in A. Implement function composition as in Functional Composition. Finally, demonstrate that the result of applying the composition of each function in A and its inverse in B to a value, is the original value. (Within the limits of computational accuracy). (A solution need not actually call the collections "A" and "B". These names are only used in the preceding paragraph for clarity.)
First-class Numbers
Let's start with the solution:
Step by Step solution about How to resolve the algorithm First-class functions step by step in the C programming language
Function Pointers and Function Composition
This code demonstrates the use of function pointers and function composition in C programming.
Function Pointers:
- A function pointer is a variable that stores the address of a function.
- The
typedef
statementtypedef double (*Class2Func)(double)
declares a typeClass2Func
to represent a function that takes a double and returns a double.
Function Composition:
- Function composition is the process of applying one function to the output of another function.
- The code composes functions in two ways:
- Using a function as an argument: The function
Function1
takes a function pointerf2
as an argument and applies it to a valueval
. - Using a function returning a function: The function
WhichFunc
returns a function pointer based on the inputidx
.
Function Lists:
- The code defines two function lists,
funcListA
andfuncListB
, which contain function pointers to various mathematical functions.
Composing Functions:
- The function
InvokeComposed
composes two functionsf1
andf2
and invokes the composed function with a given value. - The function
Compose
returns aComposition
struct that stores the two composed functionsf1
andf2
. - The function
CallComposed
takes aComposition
struct and a value and applies the composed function to the value.
Example Usage:
- The
main
function calls theFunction1
function to apply the function selected byWhichFunc
to the value 3.0. - It then composes functions from the
funcListA
andfuncListB
lists and calls the composed functions with the value 0.9.
Second Variant Using Function Pointer Arithmetic:
This second code snippet also demonstrates function composition but using a different approach involving function pointer arithmetic.
- The function
dummy
serves as a template for creating composed functions. - The
composite
function allocates memory to store a copy ofdummy
and modifies the function pointers within that copy to refer to the functionsf
andg
. - The
cube
function is a simple cubic function. - The
cbrt
function returns the cube root of a number (not always available inmath.h
). - Three function lists are defined:
A
,B
, andC
, whereC
contains functions composed fromA
andB
. - The
main
function loops through these lists and prints the values of composed functions applied to various input values.
Source code in the c programming language
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
/* declare a typedef for a function pointer */
typedef double (*Class2Func)(double);
/*A couple of functions with the above prototype */
double functionA( double v)
{
return v*v*v;
}
double functionB(double v)
{
return exp(log(v)/3);
}
/* A function taking a function as an argument */
double Function1( Class2Func f2, double val )
{
return f2(val);
}
/*A function returning a function */
Class2Func WhichFunc( int idx)
{
return (idx < 4) ? &functionA : &functionB;
}
/* A list of functions */
Class2Func funcListA[] = {&functionA, &sin, &cos, &tan };
Class2Func funcListB[] = {&functionB, &asin, &acos, &atan };
/* Composing Functions */
double InvokeComposed( Class2Func f1, Class2Func f2, double val )
{
return f1(f2(val));
}
typedef struct sComposition {
Class2Func f1;
Class2Func f2;
} *Composition;
Composition Compose( Class2Func f1, Class2Func f2)
{
Composition comp = malloc(sizeof(struct sComposition));
comp->f1 = f1;
comp->f2 = f2;
return comp;
}
double CallComposed( Composition comp, double val )
{
return comp->f1( comp->f2(val) );
}
/** * * * * * * * * * * * * * * * * * * * * * * * * * * */
int main(int argc, char *argv[])
{
int ix;
Composition c;
printf("Function1(functionA, 3.0) = %f\n", Function1(WhichFunc(0), 3.0));
for (ix=0; ix<4; ix++) {
c = Compose(funcListA[ix], funcListB[ix]);
printf("Compostion %d(0.9) = %f\n", ix, CallComposed(c, 0.9));
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
typedef double (*f_dbl)(double);
#define TAGF (f_dbl)0xdeadbeef
#define TAGG (f_dbl)0xbaddecaf
double dummy(double x)
{
f_dbl f = TAGF;
f_dbl g = TAGG;
return f(g(x));
}
f_dbl composite(f_dbl f, f_dbl g)
{
size_t len = (void*)composite - (void*)dummy;
f_dbl ret = malloc(len);
char *ptr;
memcpy(ret, dummy, len);
for (ptr = (char*)ret; ptr < (char*)ret + len - sizeof(f_dbl); ptr++) {
if (*(f_dbl*)ptr == TAGF) *(f_dbl*)ptr = f;
else if (*(f_dbl*)ptr == TAGG) *(f_dbl*)ptr = g;
}
return ret;
}
double cube(double x)
{
return x * x * x;
}
/* uncomment next line if your math.h doesn't have cbrt() */
/* double cbrt(double x) { return pow(x, 1/3.); } */
int main()
{
int i;
double x;
f_dbl A[3] = { cube, exp, sin };
f_dbl B[3] = { cbrt, log, asin}; /* not sure about availablity of cbrt() */
f_dbl C[3];
for (i = 0; i < 3; i++)
C[i] = composite(A[i], B[i]);
for (i = 0; i < 3; i++) {
for (x = .2; x <= 1; x += .2)
printf("C%d(%g) = %g\n", i, x, C[i](x));
printf("\n");
}
return 0;
}
C0(0.2) = 0.2
C0(0.4) = 0.4
C0(0.6) = 0.6
C0(0.8) = 0.8
C0(1) = 1
C1(0.2) = 0.2
C1(0.4) = 0.4
C1(0.6) = 0.6
C1(0.8) = 0.8
C1(1) = 1
C2(0.2) = 0.2
C2(0.4) = 0.4
C2(0.6) = 0.6
C2(0.8) = 0.8
C2(1) = 1
You may also check:How to resolve the algorithm Chinese remainder theorem step by step in the PARI/GP programming language
You may also check:How to resolve the algorithm Comma quibbling step by step in the Objeck programming language
You may also check:How to resolve the algorithm Paraffins step by step in the Kotlin programming language
You may also check:How to resolve the algorithm Call a foreign-language function step by step in the V (Vlang) programming language
You may also check:How to resolve the algorithm Case-sensitivity of identifiers step by step in the Raku programming language