Defining FunctionsMost of the time during programming is spent defining functions (or methods). In the following we will concentrate on functions, but most will be true for methods as well except for using dm instead of de.
Functions with no argumentThe notorious "Hello world" function must be defined:
: (de hello () (prinl "Hello world") ) -> helloThe '()' in the first line indicates a function without arguments. The body of the function is in the second line, consisting of a single statement. The last line is the return value of 'de', which here is the defined symbol. From now on we will omit the return values of examples when they are unimportant.
>Now you can call this function this way:
: (hello) Hello world
Functions with one argumentA function with an argument might be defined this way:
: (de hello (X) (prinl "Hello " X) ) # hello redefinedPicoLisp informs you that you have just redefined the function. This might be a useful warning in case you forgot that a bound symbol with that name already existed.
: (hello "world") Hello world
: (hello "Alex") Hello Alex
Preventing arguments evaluation and variable number of argumentsNormally, PicoLisp evaluates the arguments before it passes them to a function:
: (hello (+ 1 2 3)) Hello 6
: (setq A 1 B 2) # Set 'A' to 1 and 'B' to 2 -> 2 : (de foo (X Y) # 'foo' returns the list of its arguments (list X Y) ) -> foo : (foo A B) # Now call 'foo' with 'A' and 'B' -> (1 2) # -> We get a list of 1 and 2, the values of 'A' and 'B'In some cases you don't want that. For some functions (setq for example) it is better if the function gets all arguments unevaluated, and can decide for itself what to do with them.
For such cases you do not define the function with a list of parameters, but give it a single atomic parameter instead. PicoLisp will then bind all (unevaluated) arguments as a list to that parameter.
: (de foo X (list (car X) (cadr X)) ) # 'foo' lists the first two arguments : (foo A B) # Now call it again -> (A B) # -> We don't get '(1 2)', but '(A B)' : (de foo X (list (car X) (eval (cadr X))) ) # Now evaluate only the second argument : (foo A B) -> (A 2) # -> We get '(A 2)'
Mixing evaluated arguments and variable number of unevaluated argumentsAs a logical consequence, you can combine these principles. To define a function with 2 evaluated and an arbitrary number of unevaluated arguments:
: (de foo (X Y . Z) # Evaluate only the first two args (list X Y Z) ) : (foo A B C D E) -> (1 2 (C D E)) # -> Get the value of 'A' and 'B' and the remaining list
Variable number of evaluated argumentsMore common, in fact, is the case where you want to pass an arbitrary number of evaluated arguments to a function. For that, PicoLisp recognizes the symbol <code>@</code> as a single atomic parameter and remembers all evaluated arguments in an internal frame. This frame can then be accessed sequentially with the args, next, arg and rest functions.
: (de foo @ (list (next) (next)) ) # Get the first two arguments : (foo A B) -> (1 2)Again, this can be combined:
: (de foo (X Y . @) (list X Y (next) (next)) ) # 'X' and 'Y' are fixed arguments : (foo A B (+ 3 4) (* 3 4)) -> (1 2 7 12) # All arguments are evaluatedThese examples are not very useful, because the advantage of a variable number of arguments is not used. A function that prints all its evaluated numeric arguments, each on a line followed by its squared value:
: (de foo @ (while (args) # Check if there are some args left (println (next) (* (arg) (arg))) ) ) # Call the last arg (next) returned : (foo (+ 2 3) (- 7 1) 1234 (* 9 9)) 5 25 6 36 1234 1522756 81 6561 -> 6561This next example shows the behaviour of 'args' and 'rest':
: (de foo @ (while (args) (next) (println (arg) (args) (rest)) ) ) : (foo 1 2 3) 1 T (2 3) 2 T (3) 3 NIL NILFinally, it is possible to pass all these evaluated arguments to another function, using pass:
: (de foo @ (pass println 9 8 7) # First print all arguments preceded by 9, 8, 7 (pass + 9 8 7) ) # Then add all these values : (foo (+ 2 3) (- 7 1) 1234 (* 9 9)) 9 8 7 5 6 1234 81 # Printing ... -> 1350 # Return the result