60 PicoLisp Functions You Should Know - 4: Control Flow

60 PicoLisp Functions You Should Know - 4: Control Flow

Loops and conditional statement


4 min read

Conditonal Statements

Next, we will explore conditional statements. Let's start with the if statement. It is quite straightforward:

: (if (> 4 3) (println 'OK) (println 'Bad))
-> OK

First comes the condition, then what is supposed to happen if the statement is fulfilled, then what happens if it is not fulfilled.

If we have more than one condition, we can connect them with and and or.

: (if (and (> 4 2)(> 4 3)) (println 'OK) (println 'Bad))
-> OK
: (if (or (> 4 2)(> 4 5)) (println 'OK) (println 'Bad))
-> OK

To negate a condition, you can use not, but usually it is more efficient to use the negated form of ifwhich is ifn. Other logical operators are xor, nor and nand. If you're not familiar with logical operators, consider to study basic Boolean Algebra before going on.

Besides if, there are some alternative control flow options that might be more elegant in some specific use cases (in principle, they could be replaced by nested if-clauses and Boolean Algebra). For details, refer to the documentation:

  • ifn is the negated form of if, i. e. the function is executed if the condition evaluates to NIL.

  • when is very similar to if, except that it accepts more than just one function to execute if the condition evaluates to non-NIL. The negated form of when is unless.

  • cond: Multi-way conditional: If any of the conditions evaluates to non-NIL, the program is executed and the result returned. Otherwise (all conditions evaluate to NIL), NIL is returned. The negated form of cond is nond.


  1. Let's start with for-Loops. In the easiest form, for takes a symbol and an integer. Then it is counted from 1 until the integer value is reached. Alternatively, a list can be used. For each iteration, the next item in the list is used.

    : (for N 5 (printsp N))
    1 2 3 4 5 -> 5
    : (for X (1 a 2 b) (printsp X))
    1 a 2 b -> b
  2. The while loop is executed as long as the condition is evaluated to non-NIL. Example: Read console input as long as its not NIL and print out the output.

    Notice the @ symbol: it is a very useful symbol that stores the value of the last evaluation (it also has some other meanings, read here if you want to know more).

    : (while (read)
    (println 'got: @) )
    got: abc
    got: 1234
    -> 1234
  3. do is a so-called counting loop, which means that it runs a defined number of times. The number of repetitions is set as argument:

    : (do 4 (printsp 'OK))
    OK OK OK OK -> OK

    Additionally, it is possible to set an exit condition to exit the loop if the condition is fulfilled. For example:

    : (do 2 (printsp 'OK) (T (= 3 3) (printsp 'done)))
    OK done -> done

    The loop is exited already after the first iteration, because the exit condition (T (= 3 3) (printsp 'done)) reads like: "If (3=3) is true, then stop the loop and print 'done'". Another example:

    : (do 2 (printsp 'OK) (T (< 3 3) (printsp 'done)))
    OK OK -> NIL

    Here the exit condition (< 3 3) is never true, so the iteration runs two times and then returns NIL.

  4. loopworks very similar to do, except that it has no defined number of iterations. See the following example:

    • The variable N is set to 3, then the loop is started.
    • The value of N is printed.
    • The ending condition reads like "Is it true, that (N-1) equals zero?".
    • If it is true, it returns "done" and exits the loop.

      : (let N 3
       (prinl N)
       (T (=0 (dec 'N)) 'done) ) )
      -> done

Now we have covered the most basic use cases of input/output-functions and loops. In many cases, there are further options available that we didn't cover here. For further information, you can always refer to the official documentation.


Cover Pic: Tine Ivanič on Unsplash