PicoLisp Explored: The SET function
Tags: picolisp, lisp, functional
Published: 2021-11-21 12:44:28

In this series, we will further explore functions and concepts of PicoLisp that have not been covered in the [beginner's tutorial](https://picolisp-blog.hashnode.dev/series/getting-started).

-------------------------------

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](https://picolisp-blog.hashnode.dev/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:

![thishaschanged.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1630342323017/uPaYh1sgz.png)

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:

![cdrchanged.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1630342903457/k41eUSAS0.png)

---------------------------------------

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:

![carL.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1630343740488/1rDybCF81.png)

**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](https://rosettacode.org/wiki/100_doors) riddle.

-------------------------

### Sources:

- https://software-lab.de/doc/index.html  
- https://software-lab.de/doc/ref.html