60 PicoLisp Functions You Should Know - 3: Input/Output

60 PicoLisp Functions You Should Know - 3: Input/Output

Hello, World!


5 min read

Welcome back, let's continue our 60 most common PicoLisp functions series!

Today we will talk about Input and Output functions and how to print the notorious "Hello World" string we have all been waiting for.

All examples can be executed in the PicoLisp REPL. If you want to follow along, type pil + in the console to open the REPL. Check here for further basic commands.


To print output in PicoLisp, there are a number of functions depending on the need: With or without spaces between the arguments, with or without new lines...

Let's start with a simple low-level text output: prin prints all arguments without adding any spaces or new lines. prinl works the same way, except that a new line is added to the end (the "l" stands for "line").

Let's call each function two times in a row to see the difference:

: (prin "Hello World") (prin ( 1 "abc" (d e (f)) 999 ghi))
Hello World1abcdef999ghi

: (prinl "Hello World") (prinl (1 "abc" (d e (f)) 999 ghi))
Hello World

As you can see, the printout of the list (1 "abc" (d e (f)) 999 ghi)) is returned without any spaces or parentheses: 1abcdef999ghi. The inner structure of the list is lost. By looking at the output, we have no idea where one list item ends and the next one begins, and if the structure is linear or nested.

If we want to keep this information, i. e. if we need to print complete Lisp expressions that can be passed over to other functions, use print and its variations: If you need a space after the printing output, you can use printsp, for new-line use println.

Notice the differences:

: (print "Hello World") (print (1 "abc" (d e (f)) 999 ghi))
"Hello World"(1 "abc" (d e (f)) 999 ghi)

: (printsp "Hello World") (printsp (1 "abc" (d e (f)) 999 ghi))
"Hello World" (1 "abc" (d e (f)) 999 ghi

: (println "Hello World") (println (1 "abc" (d e (f)) 999 ghi))
"Hello World"
(1 "abc" (d e (f)) 999 ghi)

This time the list structure is maintained during the printing process.

Reading from console and files

The read function is called read. According to the documentation, it reads from the current input channel. But what is our current input channel?

If we use the REPL, then the current input channel is the console. However, if we call a PicoLisp script, then the current input channel is the script's file. Thus, if we want to write a script that reads from the console, we need to change the current input channel.

We will come back to this point later when we talk about scripts. For now, let's stick with the REPL.

See the following example of the read command:

: (list (read) (read) (read))
-> (123 abcd hello)

: (list (read) (read) (read))
-> (A B C)

As you can see, we take three parameters from the console and make a list out of them using the list function. Space and new line both are recognized as delimitors.

To read only a single character, use char:

: (char)                   # Read character from console
A                          # (typed 'A' and a space/return)
-> "A"

To read in a line, use line. You can additionally hand over a NIL or T flag. If the flag is NIL a list of single-character strings is returned, otherwise it is returned as one string.

: (line)             # equivalent to (line NIL)
-> ("a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l")

: (line T)
-> "abcdefghijkl"

Additionally, you can add cnt arguments that specify how the input should be grouped. If the NIL flag is used, the input is grouped the single-character sublists, while the T flag groups to substrings:

: (line NIL 1 2 3)
-> (("a") ("b" "c") ("d" "e" "f") "g" "h" "i" "j" "k" "l")

: (line T 1 2 3)
-> ("a" "bc" "def" "g" "h" "i" "j" "k" "l")

Next let's check how to read from a file in the REPL. Create a file "input.txt" and write some arbitrary content inside, such as:


hello world
this is a test

Now we change the input channel to the file by (in <filename>) and repeat the example from above - i.e., read in the first three items and make a list:

: (in "input.txt" (list (read)(read)(read)(read)))
-> (hello world this is)

We get the first four words back. Like in the console example above, space, and new-line worked as delimitors.

Writing Output to a File

Similarily, we can write to a file "output.txt" by using (out <filename>).

: (out "output.txt" (println 123 '(a b c) 'def))
-> def

Now we will find a file called "output.txt" in our current folder. Let's check its content:

$ cat output.txt
123 (a b c) def

It worked!

External Libraries

An external library is basically a file with a collection of pre-defined functions bundled together. The pil21installation comes with some library files which are located in the lib folder of your pil21 installation (of course you can also create your own).

To read in external library files, the function load is used:

(load "@lib/http.l" "@lib/xhtml.l")

The @ stands for the relative path to your pil21-Installation folder.

As an example, let's take a look into the lib/math.l file.


We see a setq for the variables pi and pi/2. Now let's load math.l into our REPL and see if we can access these:

: pi     # pi is not known
-> NIL

: (load "@lib/math.l")
-> atan2
: pi      # pi is known
-> 3141593

It works!

You probably expected pi to be 3.141593 instead of 3141593. As briefly mentioned in the Arithmetic Functions post, PicoLisp calculates internally with fixed point integers and a defined scale. We will come back to that point in one of the next posts.

These were the basics of input and output functions in PicoLisp. We will continue with conditionals and loops in the next section.


Cover: grade5eisnor.weebly.com/inputoutput-machine..