In real world applications, some functions are quite complex and so may have many parameters.
At application level, this is currently well supported through a set of options that may be passed though the command line. Such an an example might be:

gcc -s -O2 -mregparm=3 myapp.c

But surprisingly, at language level, the support for complex instructions or functions call gets very weak. In C or C++, one will have to add ... in the prototype to specify that some more parameters may be provided, but then the type of the parameters must be guessed, and cannot be safely controled by the called function at run time. This is crazy since there are many more reasons to missuse a complex function than a simple one.
Moreover, in complex functions call, different sets of arguments may be provided, so one needs to add identifiers in the middle of the parameters list to specify what kind of parameters are coming next. Using C or C++, this will be done through providing integer constants, but again, the called function will have no safe way to check that the calling sequence is valid.

The most common way of using meta programming is to write functions that will scan the arguments provided, check their type and write the proper set of simple instructions that do the complex function.
Such a function will look very similar to the main function of any application, with a loop that scans arguments one after the other.


Another example is the 'expression' function in expression2.pli. The 'expression' function is used to build an object of type Expression though calling a single function and providing many arguments to it that will specify all the content of the new expression.



Such an example can be found in setfield.pli
Setfield is responsible for trying to compile expressions such as:

a size := 12

as

a 'size :=' 12

As a result, in an Array, the size is viewed as a simple field that can be red of written event if it's not.

The C++ template notion is an attempt to improve the C preprocessor macros notion.

Much more is achieved by Pliant meta programming mechanism.
Such an example can be found in array.pli

Now if you like the C++ template notion, go on, write a pliant 'template' function that does the same. No problem, with Pliant we don't have to extend the language in order to add these kind of features: they are all applications of the Pliant meta-programming feature.


In any language, there are some features that cannot be implemented as functions because the arguments must not be computed sequentially before calling the function itself. Some languages provide lazy computation which helps with this kind of functions, but there is a cost on every function call because the mechanism appends everywhere, not only when usefull. Pliant meta programming allow to change the way arguments are computed whenever, and only, when required.

Such an example is shunt.pli
Roughly speaking we can say that shunt c1 v1 c2 v2 ... vn  is the same as the C expression c1 ? v1 : c2 ? v2 : ... vn.


Another much more complicated and powerfull example is the Pliant 'thread' function.
Pliant 'thread' function is much more powerfull than the one found in classical languages because it will check what local variables of the calling function are also used in the thread, create a structure that can store the set of values and write the program that makes the copies before creating the new thread. An example



The example is the '%' function in intn.pli

When dealing with big integers, an expression such as a^b%c must be computed through calling a 'power_modulus' function that will perform the modulus at every stage of the a^b computation, because if not, the intermediate number a^b might be so big that it overflows the computer memory, not talking about speed issue.

So, in the example, the '%' function checks if the last instruction that computed it's first argument is a call to the '^' function. If yes, then it changes the call to the '^' function by a call to the 'power_modulus' function.

This example is very interesting because it proves that with Pliant, you can build powerfull libraries. By powerfull i mean libraries with a small set of intelligent functions that will rewrite the code on the fly in order to build an optimized program rather that a large set of functions that relies completely on the user to select the right one.


The '%' sample could have been expressed as an optimizing function that scans the instruction set at code generation time, and rewrites it when it finds a sequence '^' followed by '%', but it would have been a bit more complicated.

Todo: an example that removes x+0 or 0+x sequences.