logo2022
PicoLisp
a pragmatic programming language

Why PicoLisp?

PicoLisp is quite different from other Lisps. The main reason is its focus on data.

Most Lisps focus on code. They stress functions and macros this way and that, and an efficient compilation to machine code. This results in many different data types, handled in non-orthogonal ways, often with different sets of functions. And the result of the compilation (the machine code) is no longer Lisp and thus breaks the equivalence of code and data.

In programming, the ultimate purpose is to manipulate data, not functions. Code and data are equivalent in Lisp, so you get the function manipulations for free anyway, but the focus should be on data.

PicoLisp has one single internal data type: The "cell".

On the language level it has only three data types: Numbers, symbols and cons pairs. They are all built from cells.

What may sound like a restriction is actually a big advantage. The simple internal structure results in high start-up and execution speeds. Cells can be manipulated freely in any conceivable way, giving full control to the programmer.

Symbols are "real" in PicoLisp. They have an identity, a physical existence. You can virtually grab a symbol at its address, and manipulate its value and properties (remember that Lisp used to be the "symbol manipulation language").

The orthogonality of the language allows very powerful and compact code. The implementation of a given algorithm is often more expressive and succinct than in other Lisps.

The whole system is open. Nothing is "hidden behind the scenes". The internal state can be inspected (and understood!) interactively, down to the cell and even byte level.

The PicoLisp interpreter is implemented in PicoLisp itself. It is written in a subset of PicoLisp, which - when executed - generates LLVM-IR (intermediate representation), which in turn gets assembled by LLVM for the desired target architecture.

On top of its simple machinery, PicoLisp supports namespaces, coroutines, an object-oriented database, a Web GUI, dynamic native C-calls, an integrated vi-style editor, and is installable in Android as the PilBox PilBox App}.

In summary, PicoLisp is useful to get practical work done. Since its beginnings in 1988 PicoLisp has been used in commercial projects. The author and his company did all their projects over the years exclusively in PicoLisp.

Some Examples
Factorial:
   : (de fact (N)
      (if (=0 N)
         1
         (* N (fact (dec N))) ) )
   -> fact

   : (fact 6)
   -> 720


Non-recursive factorial:
   : (apply * (range 1 6))
   -> 720
   : (apply * (range 1 40))
   -> 815915283247897734345611269596115894272000000000


Fibonacci generator coroutine:
   : (co 'fibo
      (let (A 0  B 1)
         (loop
            (yield
               (swap 'B (+ (swap 'A B) B)) ) ) ) )
   -> 1
   : (co 'fibo T)
   -> 1
   $: (co 'fibo T)
   -> 2
   $: (co 'fibo T)
   -> 3
   $: (co 'fibo T)
   -> 5
   $: (co 'fibo T)
   -> 8


Dot Product:
   : (sum * (1 2 3) (4 5 6))
   -> 32


Combine a list of 4 bytes into a 32-bit number:
   : (sum >> (-24 -16 -8 0) (127 3 4 255))
   -> 2130904319
   : (hex @)
   -> "7F0304FF"


Group subsequent elements of multiple lists into sublists:
   : (mapcar list '(a b c) (1 2 3) '(X Y Z))
   -> ((a 1 X) (b 2 Y) (c 3 Z))


Collect subsequent elements of multiple lists into a single list:
   : (mapcan list '(a b c) (1 2 3) '(X Y Z))
   -> (a 1 X b 2 Y c 3 Z)


Group same symbols independent of case:
   : (by lowc group '(Abc dEf ghI DeF GHI abc))
   -> ((Abc abc) (dEf DeF) (ghI GHI))


Sort symbols by name length:
   : (by length sort (all))
   -> (NIL ! $ % & * + - / : ; < = > ? @ A B C ...


Filter every third and fifth element from a list:
   : (filter prog2
      (range 1 30)
      '(NIL NIL T NIL T .) )
   -> (3 5 8 10 13 15 18 20 23 25 28 30)


In other Lisps, 'and', 'or' etc. are macros and thus cannot be applied. In PicoLisp they are normal functions:
   : (apply and (1 NIL 3))
   -> NIL
   : (apply and (1 2 3))
   -> 3
   : (mapcar and (1 NIL 3) (1 2 3))
   -> (1 NIL 3)
   : (mapcar or (1 NIL NIL) '(NIL 2 NIL) '(NIL NIL 3))
   -> (1 2 3)


List all open file descriptors of this process:
   : (dir (pack "/proc/" *Pid "/fd"))
   -> ("0" "1" "2" "3")  # "3" is from 'dir' itself


Native call to get the current user name:
   : (%@ "getlogin" 'S)
   -> "u0_a353"


Install PicoLisp

on Linux
The easiest way is to grab a (slightly outdated) package from your system, e.g.

  $ sudo apt install picolisp

The best way is to grab the latest version - [pil21.tgz] - unpack it, and follow the instructions from the INSTALL file.

on Windows Subsystem for Linux (WSL)
See here: Install PicoLisp on Windows 10

on macOS
Installing PicoLisp on MacOS is now possible too, as Pil21 is based on LLVM (and no longer on Gnu ASM).

An alternative repository provides code that can be built on macOS with the following instructions.

https://picolisp.com/wiki/?home

20feb23    abu