# PicoLisp Explored: The SET function

·

In this series, we will further explore functions and concepts of PicoLisp that have not been covered in the beginner's tutorial.

Today we will talk about the `set` function. Although its purpose is simple (setting values to variables), the usage can be confusing if you are not aware of the internal data representation in PicoLisp. So let's go through it and try to understand what is going on.

Some knowledge of the internal representation of data will be helpful, so consider to read the article about concepts and data types first if you haven't done so.

### The `set` function

From the docs:

`(set 'var 'any ..) -> any`

Stores new values `any` in the `var` arguments.

Examples:

``````    : (set 'L '(A B C)  (cdr L) 999)
-> 999
: L
-> (A 999 C)
``````

### Teaser: Playing around in the REPL

Let's take a look at the example: First we set `(A B C)` to the `L` symbol, and then we write 999 in its `cdr`. We know that `(cdr L)` is `(B C)`.

Question: Why do we get `(A 999 C)` as result, and not `(A 999)` (as one might expect)?

Let's define `L` as `(A B C)` and then set `L` to `999`.

``````:(setq L '(A B C))
-> (A B C)
: (set L 999)
-> 999
``````

What do you expect as result?

``````: L
-> (999 B C)
``````

Only the first item in the list `L` is changed. Now the `cdr`:

``````:(cdr L)
-> (B C)
:(set (cdr L) 888)
-> 888
``````

Again, what do you expect? This is the result:

``````: L
-> (999 888 C)
``````

Only the first item of the `cdr` is changed.

Now let's see what happens if we modify the `car` of a list of symbols: `'(A B C)`.

``````:(setq L '(A B C))
-> (A B C)
:(set (car L) 999)
-> 999
: L
-> (A B C)
``````

The first item of `L` is still `A`! Why? Because the symbol `A` has changed, not `L`:

``````: A
-> 999
``````

Obviously, there is a difference between `(set (car L) 999)` and `(set L 999)`. But what exactly is different?

Maybe you already see the point. In any case, let's go back to the basics to really understand what is happening here.

### Concepts and Data Types revisited

We remember: PicoLisp consists only of "cells" where each cell has a CAR and a CDR.

``````         +-----+-----+
| CAR | CDR |
+-----+-----+
``````

A `symbol` has a value VAL, which is in the CDR of the symbol. The pointer to the symbol points at the CDR part of the cell.

``````            Symbol
|
V
+-----+-----+
|  /  | VAL |
+-----+-----+
``````

Now let's have a look at lists. Lists are constructs that have the value in the CAR and a pointer to the next cell in the CDR.

``````      |
V
+-----+-----+
| any |  |  |
+-----+--+--+
|
V
+-----+-----+
| any |  |  |
+-----+--+--+
|
V
...
``````

The important thing to understand is that `set` takes the new value and writes it to the "position of the arrow".

### Visualizing the cells

It is easier to understand if we directly see the cell structure. Let's re-visit the very first example.

``````:(setq L '(A B C))
: (set L 999)
: L
-> (999 B C)
``````

L is a list, which means that the pointer points at the CAR. So what is actually set, is this:

The rest of the list is the same, especially the pointers to the next cell.

Now back to the second example, where we `set` a new value to `(cdr L)`. `(cdr L)` is also a list, where its first element is `B`. `B` actually is a symbol which is stored in its own cell, so the `car` of the first list contains a pointer to the `B` cells. So if we now execute:

``````:(set (cdr L) 888)
-> 888
``````

then the pointer to the `B`-cell is overwritten by `888`. Again, the pointer to the next cell is unchanged:

Now let's revisit the third example from above:

``````:(setq A 7 B 2 C 3)
-> 7
:(setq L '(A B C))
-> (A B C)
``````

The items`(A B C)` are each symbols which have some value assigned. Their value is not directly stored in the cell (as would be the case for numbers), but in a separate cell. This means that `(car L)` actually contains a pointer to the symbol `A`.

Let's consider a symbol `A` with value 7. Then the cells will look like this:

``````            |
V
+-----+-----+
A  |  |  |  7  |
+--+--+-----+
|
V
+-----+-----+
|  |  |  65 |   ASCII "A" = 65
+--+--+-----+
``````

The pointer from the list is pointing to the CDR, which contains the value of `A`. Now let's execute:

``````:(set (car L) 111)
-> 111
``````

Which value are we actually setting? Well, this one:

Since we only change the value of `A`, the structure of `L` and `A` remain unchanged. `L`still points to `A`, only that it now has a different value.

What happens if we try to do `(set (car L) 111)` if the first item of `L` is not a symbol?

``````:(setq L '(1 2 3)
!? (set (car L) 111)
1 -- Variable expected
``````

We get an error becaus integers are stored directly in the cell. Therefore there is no`car` which could be addressed.

### Wrap-up

As you can see, even a simple function such as `set` is much easier to understand with some knowledge of the internal cell representation in PicoLisp.

We will see many examples of the usage of `set` in the Rosetta Code examples as it is a widely used function, for example in the next post about the 100 Doors riddle.