# Transform CLEF expressions into functions

Clef expressions are NOT functions. In short,

• clef expressions are evaluated (the order of argument does not matter)

eval( expr, x_=1, y_=2, ...);

• while functions are called, as usual (the order of argument does matter !)

f(1,2)


It is however possible to transform expressions into functions, as soon as you specify the order of the placeholders. (the opposite is true, if the function accept lazy arguments, cf Overloading functions).

## make_function

Given any expression with placeholder x_, y_, z_, …, make_function transform them into a regular function. If we say

auto f = make_function( clef_expression, placeholder_1, placeholder_2, placeholder_3, ...)


then f is

a function (x1,x2,x3) --> RESULT


where RESULT is:

• the result of the complete evaluation of the expression if the list of placeholder exhausts the placeholders of the expression.

• otherwise a clef_expression of the remaining placeholders, returning a function.

### Short notation with >> operator

For function of one variable, the make_function notation can be simplified into

// same
auto f = make_function( 2*x_ + y_ + 1, x_);
auto f = x_ >> 2*x_ + y_ + 1;

// same
auto f = make_function ( make_function( 2*x_ + y_ + 1, y_), x_);
auto f = x_ >> (y_ >> 2*x_ + y_ + 1) ;


Warning

The notation

x_ >> y_ >> expression


is banned because it conflicts with the standard priority of >>. Use parenthesis.

## clef::function

The class nda::clef::function stored a function of a given signature It is similar to std::function but it can be constructed from an expression and an ordered list of placeholders.

clef::function can be assigned with the = operator, Cf example below.

Note

Like std::function, it stores the expression polymorphically, by erasing its type. This might lead to some performance penalty in some case, even though tests do not show that at present…

## Examples

#include <nda/clef.hpp>
#include <iostream>
using namespace nda::clef;

int main() {
placeholder<0> x_;
placeholder<1> y_;
{ // with one variable
auto f = make_function(2 * x_ + 1, x_);
std::cout << f(3) << std::endl;
std::function<double(double)> F(f);
}
{ // with two variables
auto f = make_function(2 * x_ + y_ + 1, x_, y_);
std::cout << f(3, 4) << std::endl;
std::function<double(double, double)> F(f);
}
{ // Make a function partially
auto f = make_function(2 * x_ + y_ + 1, x_);
// f is a lazy expression expression with placeholder y_, returning a function...
auto f1 = eval(f, y_ = 1); // f1 is a function x-> 2*x + 2
std::cout << f1(10) << std::endl;
}
}

7
11
22