Functions Using PicoLisp .

Drakopoulos Anastasios

Summary. This article describes the use of functions in PicoLisp.


Functions are indispensable to programming. Little can be done without the use of functions. The language can be enriched and become more powerful using functions. PicoLisp supports the use of functions in a simple though productive way. Considering the fact that everything is a list and that data and programs coincide, functions become a great tool for programming. The simplicity employed by PicoLisp is applied to functions too. The general pattern of the list that defines a function is the following:
(de argumens-list program-list)

After the symbol “de” follows the list of arguments and after that list the program follows. But when should you use a function? Functions prevent the useless repetition of code. When you want to execute some procedures many times, you can and should define a function. Defining a function means that we define a part of code with parameters. These parameters make the function flexible enough to be applied in many different cases and contexts. In this way we prevent repetition of code saving time and labor. Additionally , creating a function is the first step for the creation of libraries. When you define a function it could be useful for many programs in the future. Thus you could include it into a library. Then you can load this library and use all the functions included into it to many programs. It is very useful and this fact could increase your productivity as a programmer dramatically. A function is defined once but it is used infinitely many times. Thus when you define a function you should create it in order to complete a concrete task. In this way you should be able to use it many times under different contexts.

Function Definition I.

You should follow the pattern:
(de arguments-list program-list)
The argument are used for communication with the function caller while the program-lists are used to complete a concrete task. Into the program-list you can use any PicoLisp function you like. Consider the following trivial example.
(de my-plus(x y) (+ x y))
The function “my-plus” accepts two numbers as arguments and returns their sum. In the same way we could define the following functions for the arithmetic operations:
(de my-sub(x y) (- x y))
(de my-mult(x y) (* x y))
(de my-div(x y) (/ x y))
You could call the previous functions as follows:
: (my-plus 2 3) -> 5
: (my-sub 5 2) -> 3
: (my-mult 2 3) -> 6
: (my-div 6 2) -> 3
One could ask: if we want to add/subtract/multiply/divide infinitely many integers? How we have to define the corresponding functions? The solution is simple:
(de my-plus-m @ (pass +))
(de my-sub-m @ (pass -))
(de my-mult-m @ (pass *))
(de my-div-m @ (pass /))
That simple!
Examples of these functions calls follow:
: (my-plus-m 1 2 3 4) -> 10
: (my-plus-m 12 6) -> 18
: (my-sub-m 10 2 3 4) -> 1
: (my-sub-m 10 2 3) -> 5
: (my-mult-m 2 3 4) -> 24
: (my-mult-m 1 2 3 5) -> 30
: (my-div-m 100 2 5 2) -> 5
The symbol “@” means that our function can accept infinitely many arguments. This fact means that we have defined a function that can be called by a different number of arguments each time. The function “pass” means that all the arguments given will be passed as arguments to the primitive functions +,-,*,/ of PicoLisp and the results will be returned. Be careful ! PicoLisp's simplicity may be addictive!

Function Definition II.

You can define a function using the simple “setq” function instead of “de”, as follows:
: (setq a-fun '((x)(println x)))
And you can use it as follows:
: (a-fun "hello") -> "hello"
When you key in a function name with the right arguments into parentheses, then the expression is evaluated and the results are returned as in the following example:
: (a-fun "hello") -> "hello"
But if you key in the name of the function only, then its definition is returned as in the following example:
: a-fun -> ((x) (println x))
And here the magic of PicoLisp begins! A list is returned and we can use the “car” and “cdr” functions to take some parts of it:
: (car a-fun) -> (x)
: (cdr a-fun) -> ((println x))
Its almost amazing! The first part [extracted with car] of the list is its list of arguments while the rest of the list [extracted with cdr] is the program-list. Alternatively you could use “rest” function instead of “cdr”. Additionally you could take all the arguments of a function while inside the function's body using “rest” function as in the following example:
: (de b-fun @ (rest))
If you call the previous function the list of its arguments is returned as follows:
: (b-fun 1 2 3 4) -> (1 2 3 4)
: (b-fun "hello" 11 22 "my friend" 33 44) -> ("hello" 11 22 "my friend" 33 44)
In case you want to access a specific argument of a function you can use the “arg” function as in the following example:
: (de c-fun @ (println "arg1 = " (arg 1) ) (println "arg2 = " (arg 2)) (println "arg3 = " (arg 3)))
Calling the previous function after its definition we get the following results:
: (c-fun "hello" 222 "my friend")
"arg1 = " "hello"
"arg2 = " 222
"arg3 = " "my friend"
-> "my friend"
In case we want to suppress the last echo “my friend” we have to add a NIL symbol at the end of function's body as follows:
: (de c-fun @ (println "arg1 = " (arg 1) ) (println "arg2 = " (arg 2)) (println "arg3 = " (arg 3)) NIL )
In this case, calling this function we get the following results:
: (c-fun "hello" 222 "my friend")
"arg1 = " "hello"
"arg2 = " 222
"arg3 = " "my friend"
-> NIL