abu@software-lab.de

Perfection is attained
not when there is nothing left to add
but when there is nothing left to take away
(Antoine de Saint-Exupéry)

The Pico Lisp Reference

(c) Software Lab. Alexander Burger

This document describes the concepts, data types, and kernel functions of the Pico Lisp system.

This is not a Lisp tutorial. For an introduction to Lisp, a traditional Lisp book like "Lisp" by Winston/Horn (Addison-Wesley 1981) is recommended. Note, however, that there are significant differences between Pico Lisp and Maclisp (and even greater differences to Common Lisp).

Please take a look at the Pico Lisp Tutorial for an explanation of some aspects of Pico Lisp, and scan through the list of Frequently Asked Questions (FAQ).


Introduction

Pico Lisp is the result of a language design study, trying to answer the question "What is a minimal but useful architecture for a virtual machine?". Because opinions differ about what is meant by "minimal" and "useful", there are many answers to that question, and people might consider other solutions more "minimal" or more "useful". But from a practical point of view, Pico Lisp proved to be a valuable answer to that question.

First of all, Pico Lisp is a virtual machine architecture, and then a programming language. It was designed in a "bottom up" way, and "bottom up" is also the most natural way to understand and to use it: Form Follows Function.

Pico Lisp was used in several commercial and research programming projects since 1988. Its internal structures are simple enough, allowing an experienced programmer always to fully understand what's going on under the hood, and its language features, efficiency and extensibility make it suitable for almost any practical programming task.

In a nutshell, emphasis was put on four design objectives. The Pico Lisp system should be

Simple
The internal data structure should be as simple as possible. Only one single data structure is used to build all higher level constructs.
Unlimited
There are no limits imposed upon the language due to limitations of the virtual machine architecture. That is, there is no upper bound in symbol name length, number digit counts, stack depth, or data structure and buffer sizes, except for the total memory size of the host machine.
Dynamic
Behavior should be as dynamic as possible ("run"-time vs. "compile"-time). All decisions are delayed till runtime where possible. This involves matters like memory management, dynamic symbol binding, and late method binding.
Practical
Pico Lisp is not just a toy of theoretical value. It is used since 1988 in actual application development, research and production.


The Pico Lisp Machine

An important point in the Pico Lisp philosophy is the knowledge about the architecture and data structures of the internal machinery. The high-level constructs of the programming language directly map to that machinery, making the whole system both understandable and predictable.

This is similar to assembly language programming, where the programmer has complete control over the machine.


The Cell

The Pico Lisp virtual machine is both simpler and more powerful than most current (hardware) processors. At the lowest level, it is constructed from a single data structure called "cell":


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

A cell is a pair of machine words, which traditionally are called CAR and CDR in the Lisp terminology. These words can represent either a numeric value (scalar) or the address of another cell (pointer). All higher level data structures are built out of cells.

The type information of higher level data is contained in the pointers to these data. Assuming the implementation on a byte-addressed physical machine, and a pointer size of typically 4 bytes, each cell has a size of 8 bytes. Therefore, the pointer to a cell must point to an 8-byte boundary, and its bit-representation will look like:


      xxxxxxxxxxxxxxxxxxxxxxxxxxxxx000

(the 'x' means "don't care"). For the individual data types, the pointer is adjusted to point to other parts of a cell, in effect setting some of the lower three bits to non-zero values. These bits are then used by the interpreter to determine the data type.

In any case, bit(0) - the least significant of these bits - is reserved as a mark bit for garbage collection.

Initially, all cells in the memory are unused (free), and linked together to form a "free list". To create higher level data types at runtime, cells are taken from that free list, and returned by the garbage collector when they are no longer needed. All memory management is done via that free list; there are no additional buffers, string spaces or special memory areas (With two exceptions: A certain fixed area of memory is set aside to contain the executable code and global variables of the interpreter itself, and a standard push down stack for return addresses and temporary storage. Both are not directly accessible by the programmer).


Data Types

On the virtual machine level, Pico Lisp supports

They are all built from the single cell data structure, and all runtime data cannot consist of any other types than these three.

The following diagram shows the complete data type hierarchy, consisting of the three base types and the symbol variations:


                    cell
                     |
            +--------+--------+
            |        |        |
         Number    Symbol    List
                     |
                     |
   +--------+--------+--------+
   |        |        |        |
  NIL   Internal Transient External


Numbers

A number can represent a signed integral value of arbitrary size. The CARs of one or more cells hold the number's "digits" (each in the machine's word size), to store the number's binary representation.


         Number
         |
         V
      +-----+-----+     +-----+-----+     +-----+-----+
      |'DIG'|  ---+---> |'DIG'|  ---+---> |'DIG'|  /  |
      +-----+-----+     +-----+-----+     +-----+-----+

The first cell holds the least significant digit. The least significant bit of that digit represents the sign.

The pointer to a number points into the middle of the CAR, with an offset of 2 from the cell's start address. Therefore, the bit pattern of a number will be:


      xxxxxxxxxxxxxxxxxxxxxxxxxxxxx010

Thus, a number is recognized by the interpreter when bit(1) is non-zero.


Symbols

A symbol is more complex than a number. Each symbol has a value, and optionally a name and an arbitrary number of properties. The CAR of a symbol cell is also called VAL, and the CDR points to the symbol's tail. As a minimum, a symbol consists of a single cell, and has no name or properties:


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

That is, the symbol's tail is empty (points to NIL, as indicated by the '/' character).

The pointer to a symbol points to the CDR of the cell, with an offset of 4 from the cell's start address. Therefore, the bit pattern of a symbol will be:


      xxxxxxxxxxxxxxxxxxxxxxxxxxxxx100

Thus, a symbol is recognized by the interpreter when bit(2) is non-zero. In addition, it is possible that bit(1) is also set for a symbol (This is the case for external symbols).

A property is a key-value-pair, represented as a cell in the symbol's tail. This is called a "property list". The property list may be terminated by a number representing the symbol's name. In the following example, a symbol with the name "abc" has three properties:


            Symbol
            |
            V
      +-----+-----+
      | VAL |  ---+---+
      +-----+-----+   | tail
                      |
         +------------+
         |
         V                                                      name
         +-----+-----+     +-----+-----+     +-----+-----+     +-----+-----+
         |  |  |  ---+---> | KEY |  ---+---> |  |  |  ---+---> |'cba'|  /  |
         +--+--+-----+     +-----+-----+     +--+--+-----+     +-----+-----+
            |                                   |
            V                                   V
            +-----+-----+                       +-----+-----+
            | VAL | KEY |                       | VAL | KEY |
            +-----+-----+                       +-----+-----+

Each property in a symbol's tail is either a symbol (then it represents a boolean value), or a cell with the property key in its CDR and the property value in its CAR. In both cases, the key should be a symbol, because searches in the property list are performed using pointer comparisons.

The name of a symbol is stored as a number at the end of the tail. It contains the characters of the name in UTF-8 encoding, using between one and three 8-bit-bytes per character. The first byte of the first character is stored in the lowest 8 bits of the number.

All symbols have the above structure, but depending on scope and accessibility there are actually four types of symbols: NIL, internal, transient and external symbols.


NIL

NIL is a special symbol which exists exactly once in the whole system. It is used

For that, NIL has a special structure:


      NIL:  /
            |
            V
      +-----+-----+-----+-----+
      |  /  |  /  |  /  |  /  |
      +-----+--+--+-----+-----+

The reason for that structure is NIL's dual nature both as a symbol and as a list:

These requirements are fulfilled by the above structure.


Internal Symbols

Internal Symbols are all those "normal" symbols, as they are used for function definitions and variable names. They are "interned" into a hashed list structure, so that it is possible to find an internal symbol by searching for its name.

There cannot be two different internal symbols with the same name.

Initially, a new internal symbol's VAL is NIL.


Transient Symbols

Transient symbols are only interned into a hashed list structure for a certain time (e.g. while reading the current source file), and are released after that. That means, a transient symbol cannot be accessed then by its name, and there may be several transient symbols in the system having the same name.

Transient symbols are used

Initially, a new transient symbol's VAL is that symbol itself.

A transient symbol without a name can be created with the box or new functions.


External Symbols

External symbols reside in a database file, and are loaded into memory - and written back to the file - dynamically as needed, and transparent to the programmer.

The interpreter recognizes external symbols, because in addition to the symbol bit(2), also bit(1) is set:


      xxxxxxxxxxxxxxxxxxxxxxxxxxxxx110

There cannot be two different external symbols with the same name. External symbols are maintained in hash structures while they are loaded into memory, and have their external location (disk block, network URL, etc.) directly coded into their names.

Initially, a new external symbol's VAL is NIL, unless otherwise specified at creation time.


Lists

A list is a sequence of one or more cells, holding numbers, symbols, or lists. Lists are used in Pico Lisp to emulate composite data structures like arrays, trees, stacks or queues.

In contrast to lists, numbers and symbols are collectively called "Atoms".

Typically, the CDR of each cell in a list points to the following cell, except for the last cell which points NIL. If, however, the CDR of the last cell points to an atom, that cell is called a "dotted pair" (because of its I/O syntax with a dot '.' between the two values).


Memory Management

The Pico Lisp interpreter has complete knowledge of all data in the system, due to the type information associated with every pointer. Therefore, an efficient garbage collector mechanism can easily be implemented. Pico Lisp employs a simple but fast mark-and-sweep garbage collector.

As the collection process is very fast (in the order of milliseconds per megabyte), it was not necessary to develop more complicated, time-consuming and error-prone garbage collection algorithms (e.g. incremental collection). A compacting garbage collector is also not necessary, because the single cell data type cannot cause heap fragmentation.


Programming Environment

Lisp was chosen as the programming language, because of its clear and simple structure.

In some previous versions, a Forth-like syntax was also implemented on top of a similar virtual machine (Lifo). Though that language was more flexible and expressive, the traditional Lisp syntax proved easier to handle, and the virtual machine can be kept considerably simpler. Pico Lisp inherits the major advantages of classical Lisp systems like

In the following, some concepts and peculiarities of the Pico Lisp language and environment are described.


Invocation

When Pico Lisp is invoked from the command line, an arbitrary number of arguments may follow the command name.

By default, each argument is the name of a file to be executed by the interpreter. If, however, the argument's first character is a hyphen '-', then the rest of that argument is taken as a function call (without the surrounding parentheses). A hyphen by itself as an argument stops evaluation of the rest of the command line (it may be processed later using the argv function). This mechanism corresponds to calling (load T).

As a convention, Pico Lisp source files have the extension ".l".

Note that the Pico Lisp executable itself does not expect or accept any command line flags or options. They are reserved for application programs.

The simplest and shortest invocation of Pico Lisp does nothing, and exits immediately by calling bye:


$ bin/picolisp -bye
$

In interactive mode, the Pico Lisp interpreter (see load) will also exit when an empty line is entered:


$ bin/picolisp
:                       # Typed RETURN
$

To start up the standard Pico Lisp environment, several files should be loaded. The most commonly used things are in "lib.l" and in a bunch of other files, which are in turn loaded by "ext.l". Thus, a typical call would be:


$ bin/picolisp lib.l ext.l

The recommended way, however, is to call the "p" shell script, which includes "lib.l" and "ext.l". Given that your current project is loaded by some file "myProject.l" and your startup function is main, your invocation would look like:


$ ./p myProject.l -main

For interactive development and debugging it is recommended also to load "dbg.l", to get the vi-style command line editor, single-stepping, tracing and other debugging utilities.


$ ./p dbg.l myProject.l -main

In any case, the directory part of the first file name supplied on the command line is remembered internally as the Pico Lisp Home Directory. This path is later automatically substituted for any leading "@" character in file name arguments to I/O functions (see path).


Input/Output

In Lisp, each internal data structure has a well-defined external representation in human-readable format. All kinds of data can be written to a file, and restored later to their original form by reading that file.

In normal operation, the Pico Lisp interpreter continuously executes an infinite "read-eval-print loop". It reads one expression at a time, evaluates it, and prints the result to the console. Any input into the system, like data structures and function definitions, is done in a consistent way no matter whether it is entered at the console or read from a file.

Comments can be embedded in the input stream with the hash # character. Everything up to the end of that line will be ignored by the reader.


: (* 1 2 3)  # This is a comment
-> 6

Here is the I/O syntax for the individual Pico Lisp data types:


Numbers

A number consists of an arbitrary number of digits ('0' through '9'), optionally preceded by a sign character ('+' or '-'). Legal number input is:


: 7
-> 7
: -12345678901245678901234567890
-> -12345678901245678901234567890

Fixed-point numbers can be input by embedding a decimal point '.', and setting the global variable *Scl appropriately:


: *Scl
-> 0

: 123.45
-> 123
: 456.78
-> 457

: (setq *Scl 3)
-> 3
: 123.45
-> 123450
: 456.78
-> 456780

Thus, fixed-point input simply scales the number to an integer value corresponding to the number of digits in *Scl.

Formatted output of scaled fixed-point values can be done with the format function:


: (format 1234567890 2)
-> "12345678.90"
: (format 1234567890 2 "." ",")
-> "12,345,678.90"


Symbols

The reader is able to recognize the individual symbol types from their syntactic form. A symbol name should - of course - not look like a legal number (see above).

In general, symbol names are case-sensitive. car is not the same as CAR.


NIL

Besides for standard normal form, NIL is also recognized as (), [] or "".


: NIL
-> NIL
: ()
-> NIL
: ""
-> NIL

Output will always appear as NIL.


Internal Symbols

Internal symbol names can consist of any printable (non-whitespace) character, except for the following meta characters:


   "  '  (  )  [  ]  `  ~

As a rule, anything not recognized by the reader as another data type will be returned as an internal symbol.


Transient Symbols

A transient symbol is anything surrounded by double quotes '"'. With that, it looks - and can be used - like a string constant in other languages. However, it is a real symbol, and may be assigned a value or a function definition, and properties.

Initially, a transient symbol's value is that symbol itself, so that it does not need to be quoted for evaluation:


: "This is a string"
-> "This is a string"

However, care must be taken when assigning a value to a transient symbol. This may cause unexpected behavior:


: (setq "This is a string" 12345)
-> 12345
: "This is a string"
-> 12345

The name of a transient symbol can contain any character. A double quote character can be escaped with a backslash '\', and a backslash itself has to be escaped with another backslash. Control characters can be written with a preceding hat '^' character.


: "We^Ird\\Str\"ing"
-> "We^Ird\\Str\"ing"
: (chop @)
-> ("W" "e" "^I" "r" "d" "\\" "S" "t" "r" "\"" "i" "n" "g")

The hash table for transient symbols is cleared automatically before and after loading a source file, or it can be reset explicitly with the ==== function. With that mechanism, it is possible to create symbols with a local access scope, not accessible from other parts of the program.

A special case of transient symbols are anonymous symbols. These are symbols without name (see box, box? or new). They print as a dollar sign ($) followed by a decimal digit string (actually their machine address).


External Symbols

External symbol names are surrounded by braces ('{' and '}'). The characters of the symbol's name itself identify the physical location of the external object. This is currently the number of the starting block in the database file, encoded in base-64 notation (characters '0' through '9', ':' through ';', 'A' through 'Z' and 'a' through 'z'). Later versions might include other formats like Internet URL's.


Lists

Lists are surrounded by parentheses ('(' and ')').

(A) is a list consisting of a single cell, with the symbol A in its CAR, and NIL in its CDR.

(A B C) is a list consisting of three cells, with the symbols A, B and C respectively in their CAR, and NIL in the last cell's CDR.

(A . B) is a "dotted pair", a list consisting of a single cell, with the symbol A in its CAR, and B in its CDR.

Pico Lisp has built-in support for reading and printing simple circular lists. If the dot in a dotted-pair notation is immediately followed by a closing parenthesis, it indicates that the CDR of the last cell points back to the beginning of that list.


: (let L '(a b c) (conc L L))
-> (a b c .)
: (cdr '(a b c .))
-> (b c a .)
: (cddddr '(a b c .))
-> (b c a .)

A similar result can be achieved with the function circ. Such lists must be used with care, because many functions won't terminate or will crash when given such a list.


Read-Macros

Read-macros in Pico Lisp are special forms that are recognized by the reader, and modify its behavior. Note that they take effect immediately while reading an expression, and are not seen by the eval in the main loop.

The most prominent read-macro in Lisp is the single quote character ', which expands to a call of the quote function. Note that the single quote character is also printed instead of the full function name.


: '(a b c)
-> (a b c)
: '(quote . a)
-> 'a
: (cons 'quote 'a)   # (quote . a)
-> 'a
: (list 'quote 'a)   # (quote a)
-> '(a)

A comma (,) will cause the reader to collect the following data item into the global variable *Uni, and to return a previously inserted equal item if present. This makes it possible to create a unique list of references to data which do normally not follow the rules of pointer equality.

A single backquote character ` will cause the reader to evaluate the following expression, and return the result.


: '(a `(+ 1 2 3) z)
-> (a 6 z)

A tilde character ~ inside a list will cause the reader to evaluate the following expression, and splice the result into the list.


: '(a b c ~(list 'd 'e 'f) g h i)
-> (a b c d e f g h i)

Brackets ('[' and ']') can be used as super parentheses. A closing bracket will match the innermost opening bracket, or all currently open parentheses.


: '(a (b (c (d]
-> (a (b (c (d))))
: '(a (b [c (d]))
-> (a (b (c (d))))

Finally, reading the sequence '{}' will result in a new anonymous symbol with value NIL, equivalent to a call to box without arguments.


: '({} {} {})
-> ($134599965 $134599967 $134599969)
: (mapcar val @)
-> (NIL NIL NIL)


Evaluation

Pico Lisp tries to evaluate any expression encountered in the read-eval-print loop. Basically, it does so by applying the following three rules:


: 1234
-> 1234        # Number evaluates to itself
: *Pid
-> 22972       # Symbol evaluates to its VAL
: (+ 1 2 3)
-> 6           # List is evaluated as a function call

For the third rule, however, things get a bit more involved. First - as a special case - if the CAR of the list is a number, the whole list is returned as it is:


: (1 2 3 4 5 6)
-> (1 2 3 4 5 6)

This is not really a function call but just a convenience to avoid having to quote simple data lists.

Otherwise, if the CAR is a symbol or a list, Pico Lisp tries to obtain an executable function from that, by either using the symbol's value, or by evaluating the list.

What is an executable function? Or, said in another way, what can be applied to a list of arguments, to result in a function call? A legal function in Pico Lisp is

either
a number. When a number is used as a function, it is simply taken as a pointer to executable code that will be called with the list of (unevaluated) arguments as its single parameter. It is up to that code to evaluate the arguments, or not. Some functions do not evaluate their arguments (e.g. quote) or evaluate only some of their arguments (e.g. setq).
or
a lambda expression. A lambda expression is a list, whose CAR is either a symbol or a list of symbols, and whose CDR is a list of expressions. Note: In contrast to other Lisp implementations, the symbol LAMBDA itself does not exist in Pico Lisp but is implied from context.

A few examples should help to understand the practical consequences of these rules. In the most common case, the CAR will be a symbol defined as a function, like the * in:


: (* 1 2 3)    # Call the function '*'
-> 6

Inspecting the VAL of *, however, gives


: *            # Get the VAL of the symbol '*'
-> 67291944

The VAL of * is a number. In fact, it is the numeric representation of a C-function pointer, i.e. a pointer to executable code. This is the case for all built-in functions of Pico Lisp.

Other functions in turn are written as Lisp expressions:


: (de foo (X Y)            # Define the function 'foo'
   (* (+ X Y) (+ X Y)) )
-> foo
: (foo 2 3)                # Call the function 'foo'
-> 25
: foo                      # Get the VAL of the symbol 'foo'
-> ((X Y) (* (+ X Y) (+ X Y)))

The VAL of foo is a list. It is the list that was assigned to foo with the de function. It would be perfectly legal to use setq instead of de:


: (setq foo '((X Y) (* (+ X Y) (+ X Y))))
-> ((X Y) (* (+ X Y) (+ X Y)))
: (foo 2 3)
-> 25

If the VAL of foo were another symbol, that symbol's VAL would be used instead to search for an executable function.

As we said above, if the CAR of the evaluated expression is not a symbol but a list, that list is evaluated to obtain an executable function.


: ((intern (pack "c" "a" "r")) (1 2 3))
-> 1

Here, the intern function returns the symbol car whose VAL is used then. It is also legal, though quite dangerous, to use the code-pointer directly:


: car
-> 67306152
: ((* 2 33653076) (1 2 3))
-> 1

When an executable function is defined in Lisp itself, we call it a lambda expression. A lambda expression always has a list of executable expressions as its CDR. The CAR, however, must be a either a list of symbols, or a single symbol, and it controls the evaluation of the arguments to the executable function according to the following rules:

When the CAR is a list of symbols
For each of these symbols an argument is evaluated, then the symbols are bound simultaneously to the results. The body of the lambda expression is executed, then the VAL's of the symbols are restored to their original values. This is the most common case, a fixed number of arguments is passed to the function.
Otherwise, when the CAR is the symbol @
All arguments are evaluated and the results kept internally in a list. The body of the lambda expression is executed, and the evaluated arguments can be accessed sequentially with the args, next, arg and rest functions. This allows to define functions with a variable number of evaluated arguments.
Otherwise, when the CAR is a single symbol
The symbol is bound to the whole unevaluated argument list. The body of the lambda expression is executed, then the symbol is restored to its original value. This allows to define functions with unevaluated arguments. Any kind of interpretation and evaluation of the argument list can be done inside the expression body.

In all cases, the return value is the result of the last expression in the body.


: (de foo (X Y Z)                   # CAR is a list of symbols
   (list X Y Z) )                   # Return a list of all arguments
-> foo
: (foo (+ 1 2) (+ 3 4) (+ 5 6))
-> (3 7 11)                         # all arguments are evaluated


: (de foo X                         # CAR is a single symbol
   X )                              # Return the argument
-> foo
: (foo (+ 1 2) (+ 3 4) (+ 5 6))
-> ((+ 1 2) (+ 3 4) (+ 5 6))        # the whole unevaluated list is returned


: (de foo @                         # CAR is the symbol '@'
   (list (next) (next) (next)) )    # Return the first three arguments
-> foo
: (foo (+ 1 2) (+ 3 4) (+ 5 6))
-> (3 7 11)                         # all arguments are evaluated

Note that these forms can also be combined. For example, to evaluate only the first two arguments, bind the results to X and Y, and bind all other arguments (unevaluated) to Z:


: (de foo (X Y . Z)                 # CAR is a list with a dotted-pair tail
   (list X Y Z) )                   # Return a list of all arguments
-> foo
: (foo (+ 1 2) (+ 3 4) (+ 5 6))
-> (3 7 ((+ 5 6)))                  # two arguments are evaluated

Or, a single argument followed by a variable number of arguments:


: (de foo (X . @)                   # CAR is a dotted-pair with '@'
   (println X)                      # print the first evaluated argument
   (while (args)                    # while there are more arguments
      (println (next)) ) )          # print the next one
-> foo
: (foo (+ 1 2) (+ 3 4) (+ 5 6))
3                                   # X
7                                   # Next arg
11
-> 11


Interrupt

During the evaluation of an expression, the Pico Lisp interpreter can be interrupted at any time by hitting Ctrl-C. It will then enter the breakpoint routine, as if ! were called.

Hitting RETURN at that point will continue evaluation, while (quit) will abort evaluation and return the interpreter to the top level. See also debug, e, ^ and *Dbg


Error Handling

When a runtime error occurs, execution is stopped and an error handler is entered.

The error handler resets the I/O channels to the console, and displays the location (if possible) and the reason of the error, followed by an error message. That message is also stored in the global *Msg. If the VAL of the global *Err is non-NIL it is executed as a prg body. If the standard input is from a terminal, a read-eval-print loop (with a question mark "?" as prompt) is entered (the loop is exited when an empty line is input). Then all pending finally expressions are executed, all variable bindings restored, and all files closed. If the standard input is not from a terminal, the interpreter terminates. Otherwise it is reset to its top-level state.

If the VAL of the global *Rst is non-NIL, no interactive read-eval-print loop will be entered, and that VAL will be executed instead - after the above cleanup was done - as a prg body.


: (de foo (A B) (badFoo A B))       # 'foo' calls an undefined symbol
-> foo
: (foo 3 4)                         # Call 'foo'
!? (badFoo A B)                     # Error handler entered
badFoo -- Undefined
? A                                 # Inspect 'A'
-> 3
? B                                 # Inspect 'B'
-> 4
?                                   # Empty line: Exit
:


@ Result

In certain situations, the result of the last evaluation is stored in the VAL of the symbol @. This can be very convenient, because it often makes the assignment to temporary variables unnecessary.

load
In read-eval loops, the last three results which were printed at the console are available in @@@, @@ and @, in that order (i.e the latest result is in @).


: (+ 1 2 3)
-> 6
: (/ 128 4)
-> 32
: (- @ @@)        # Subtract the last two results
-> 26

Flow functions
Flow- and logic-functions store the result of evaluating their conditional expression in @.


: (while (read) (println 'got: @))
abc            # User input
got: abc       # print result
123            # User input
got: 123       # print result
NIL
-> 123

: (setq L (1 2 3 4 5 1 2 3 4 5))
-> (1 2 3 4 5 1 2 3 4 5)
: (and (member 3 L) (member 3 (cdr @)) (set @ 999))
-> 999
: L
-> (1 2 3 4 5 1 2 999 4 5)

These functions include and, case, cond, nond, do, for, if, if2, ifn, loop, nand, nor, or, prog1, prog2, state, unless, until, when, while, and the bodies of *Run tasks.

@ is generally local to functions and methods, its value is automatically saved upon function entry and restored at exit.


Comparing

In Pico Lisp, it is legal to compare data items of arbitrary type. Any two items are either

Identical
They are the same memory object (pointer equality). For example, two internal symbols with the same name are identical.
Equal
They are equal in every respect (structure equality), but need not to be identical. Examples are numbers with the same value, transient symbols with the same name or lists with equal elements.
Or they have a well-defined ordinal relationship
Numbers are comparable by their numeric value, strings by their name, and lists recursively by their elements (if the CAR's are equal, their CDR's are compared). For differing types, the following rule applies: Numbers are less than symbols, and symbols are less than lists. As special cases, NIL is always less than anything else, and T is always greater than anything else.

To demonstrate this, sort a list of mixed data types:


: (sort '("abc" T (d e f) NIL 123 DEF))
-> (NIL 123 DEF "abc" (d e f) T)

See also max, min, rank, <, =, > etc.


OO Concepts

Pico Lisp comes with built-in object oriented extensions. There seems to be a common agreement upon three criteria for object orientation:

Encapsulation
Code and data are encapsulated into objects, giving them both a behavior and a state. Objects communicate by sending and receiving messages.
Inheritance
Objects are organized into classes. The behavior of an object is inherited from its class(es) and superclass(es).
Polymorphism
Objects of different classes may behave differently in response to the same message. For that, classes may define different methods for each message.

Pico Lisp implements both objects and classes with symbols. Object-local data are stored in the symbol's property list, while the code (methods) and links to the superclasses are stored in the symbol's VAL (encapsulation).

In fact, there is no formal difference between objects and classes (except that objects usually are anonymous symbols containing mostly local data, while classes are named internal symbols with an emphasis on method definitions). At any time, a class may be assigned its own local data (class variables), and any object can receive individual method definitions in addition to (or overriding) those inherited from its (super)classes.

Pico Lisp supports multiple inheritance. The VAL of each object is a (possibly empty) association list of message symbols and method bodies, concatenated with a list of classes. When a message is sent to an object, it is searched in the object's own method list, and then (with a left-to-right depth-first search) in the tree of its classes and superclasses. The first method found is executed and the search stops. The search may be explicitly continued with the extra and super functions.

Thus, which method is actually executed when a message is sent to an object depends on the classes that the object is currently linked to (polymorphism). As the method search is fully dynamic (late binding), an object's type (i.e. its classes and method definitions) can be changed even at runtime!

While a method body is being executed, the global variable This is set to the current object, allowing the use of the short-cut property functions =:, : and ::.


Database

On the lowest level, a Pico Lisp database is simply a collection of external symbols. They reside in a database file, and are dynamically swapped in and out of memory. Only one database file (pool) can be open at any time (pool).

The symbols in the database can be used to store arbitrary information structures. In typical use, some symbols represent nodes of search trees, by holding keys, values, and links to subtrees in their VAL's. Such a search tree in the database is called index.

For the most part, other symbols in the database are objects derived from the +Entity class.

Entities depend on objects of the +Relation class hierarchy. Relation-objects manage the property values of entities, they define the application database model and are responsible for the integrity of mutual object references and index trees.

Relations are stored as properties in the entity classes, their methods are invoked as daemons whenever property values in an entity are changed. When defining an +Entity class, relations are defined - in addition to the method definitions of a normal class - with the rel function. Predefined relation classes include


Pilog (Pico Lisp Prolog)

A declarative language is built on top of Pico Lisp, that has the semantics of Prolog, but uses the syntax of Lisp.

For an explanation of Prolog's declarative programming style, an introduction like "Programming in Prolog" by Clocksin/Mellish (Springer-Verlag 1981) is recommended.

Facts and rules can be declared with the be function. For example, a Prolog fact 'likes(john,mary).' is written in Pilog as:


(be likes (John Mary))

and a rule 'likes(john,X) :- likes(X,wine), likes(X,food).' is in Pilog:


(be likes (John @X) (likes @X wine) (likes @X food))

As in Prolog, the difference between facts and rules is that the latter ones have conditions and usually contain variables. A variable in Pilog is any symbol starting with an at-mark ("@").

The cut operator of Prolog (usually written as an exclamation mark (!)) is the symbol T in Pilog.

Pilog can be called from Lisp and vice versa:

An interactive query can be done with the ? function:


(? (likes John @X))

This will print all solutions, waiting for user input after each line. If a non-empty line (not just a RETURN key, but for example a dot (.) followed by RETURN) is entered, it will terminate.


Naming Conventions

It was necessary to introduce - and adhere to - a set of conventions for Pico Lisp symbol names. Because all (internal) symbols have a global scope (there are no packages or name spaces), and each symbol can only have either a value or function definition, it would otherwise be very easy to introduce name conflicts. Besides this, source code readability is increased when the scope of a symbol is indicated by its name.

These conventions are not hard-coded into the language, but should be so into the head of the programmer. Here are the most commonly used ones:

For historical reasons, the global constant symbols T and NIL do not obey these rules, and are written in upper case.

For example, a local variable could easily overshadow a function definition:


: (de max-speed (car)
   (.. (get car 'speeds) ..) )
-> max-speed

Inside the body of max-speed (and all other functions called during that execution) the kernel function car is redefined to some other value, and will surely crash if something like (car Lst) is executed. Instead, it is safe to write:


: (de max-speed (Car)            # 'Car' with upper case first letter
   (.. (get Car 'speeds) ..) )
-> max-speed

Note that there are also some strict naming rules (as opposed to the voluntary conventions) that are required by the corresponding kernel functionalities, like:

With that, the last of the above conventions (local functions start with an underscore) is not really necessary, because true local scope can be enforced with transient symbols.


Breaking Traditions

Pico Lisp does not try very hard to be compatible with traditional Lisp systems. If you are used to some other Lisp dialects, you may notice the following differences:

Case Sensitivity
Pico Lisp distinguishes between upper case and lower case characters in symbol names. Thus, CAR and car are different symbols, which was not the case in traditional Lisp systems.
QUOTE
In traditional Lisp, the QUOTE function returns its first unevaluated argument. In Pico Lisp, on the other hand, quote returns all (unevaluated) argument(s).
LAMBDA
The LAMBDA function, in some way at the heart of traditional Lisp, is completely missing (and quote is used instead).
PROG
The PROG function of traditional Lisp, with its GOTO and RETURN functionality, is also missing. Pico Lisp's prog function is just a simple sequencer (as PROGN ins some Lisps).
Function/Value
In Pico Lisp, a symbol cannot have a value and a function definition at the same time. Though this is a disadvantage at first sight, it allows a completely uniform handling of functional data.


Function Reference

This section provides a reference manual for the kernel functions, and some extensions. The first part is a thematically grouped list of indexes into the second part, which contains the function specifications in alphabetical order.

Though Pico Lisp is a dynamically typed language (resolved at runtime, as opposed to statically (compile-time) typed languages), many functions can only accept and/or return a certain set of data types. For each function, the expected argument types and return values are described with the following abbreviations:

The primary data types:

Other (derived) data types

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z Other

Symbol Functions
new sym str char name sp? pat? fun? intern extern ==== box? str? ext? touch zap length size format chop pack glue text pre? sub? low? upp? lowc uppc fold val set setq def de dm xchg on off onOff zero one default let let? use push push1 pop cut del queue fifo idx lup
Property Access
put get prop =: : :: putl getl wipe meta
Predicates
atom pair lst? num? sym? flg? sp? pat? fun? box? str? ext? bool not == n== = <> =0 =T n0 nT < <= > >= match
Arithmetics
+ - * / % */ inc dec >> lt0 ge0 gt0 abs bit? & | x| sqrt seed rand max min length size format
List Processing
car cdr caar cadr cdar cddr caaar caadr cadar caddr cdaar cdadr cddar cdddr cadddr cddddr nth con cons conc circ rot list need make made chain link copy mix append delete delq replace strip split reverse flip trim clip head tail stem fin last member memq mmeq sect diff index offset assoc asoq rank sort length size val set xchg push push1 pop cut queue fifo idx get fill apply
Control Flow
load args next arg rest pass quote as lit eval run def de dm box new type isa method meth send try super extra with bind job let let? use and or nand nor xor bool not nil t prog prog1 prog2 if if2 ifn when unless cond nond, case state while until loop do at for catch throw finally ! e $ sys call tick kill quit fork bye
Mapping
apply pass all maps map mapc maplist mapcar mapcon mapcan filter seek find pick cnt sum maxi mini fish by
Input/Output
path in out pipe ctl any sym str load hear tell key poll peek char skip eof from till line format read print println printsp prin prinl space flush rewind rd pr wr rpc wait sync echo info dir lines open close port listen accept host connect nagle udp
Database
pool journal id seq lieu lock begin commit rollback mark free dbck rel
Pilog
be goal prove -> unify ?
Debugging
stat debug trace
System Functions
argv opt gc raw die protect heap env up stk stat date time usec stamp pwd cd ctty info dir call tick kill quit fork bye
Globals
NIL *DB *Solo ^ @ @@ @@@ This T *Dbg *PPid *Pid *Scl *Class *Run *Led *Err *Rst *Msg *Uni *Adr *Fork *Bye


A

(abs 'num) -> num
Returns the absolute value of the num argument.


: (abs -7)
-> 7
: (abs 7)
-> 7

(accept 'cnt) -> cnt | NIL
Accepts a connection on descriptor cnt (as received by port), and returns the new socket descriptor cnt. The global variable *Adr is set to the IP address of the client. See also listen, connect and *Adr.


: (setq *Socket
   (accept (port 6789)) )        # Accept connection at port 6789
-> 4

(all 'fun) -> any
Applies fun to all internal symbols in the system. Returns the result of the last application.


: (all printsp)  # Print the names of all internal symbols
delWord +PwField +Fmt tail char cons month ..
.. conc cond -> cond

# Find all symbols starting with an underscore character
: (make (all '((X) (and (= "_" (car (chop X))) (link X)))))
-> (_ed _isa _delL _delR _dbg _del _query _scan _hex _boxSend _put)

(and 'any ..) -> any
Logical AND. The expressions any are evaluated from left to right. If NIL is encountered, NIL is returned immediately. Else the result of the last expression is returned.


: (and (= 3 3) (read))
abc  # User input
-> abc
: (and (= 3 4) (read))
-> NIL

(any 'sym) -> any
Parses any from the name of sym. See also sym and str.


: (any "(a b # Comment^Jc d)")
-> (a b c d)
: (any "\"A String\"")
-> "A String"

(append 'lst ..) -> lst
Appends all argument lists. See also conc.


: (append '(a b c) (1 2 3))
-> (a b c 1 2 3)
: (append (1) (2) (3) 4)
-> (1 2 3 . 4)

(apply 'fun 'lst ['any ..]) -> any
Applies fun to lst. If additional any arguments are given, they are applied as leading elements of lst.


: (apply + (1 2 3))
-> 6
: (apply * (5 6) 3 4)
-> 360
: (apply '((X Y Z) (* X (+ Y Z))) (3 4 5))
-> 27

(arg ['cnt]) -> any
Can only be used inside functions with a variable number of arguments (with @). If cnt is not given, the value that was returned from the last call to next) is returned. Otherwise, the cnt'th remaining argument is returned. See also args, next, rest and pass.


: (de foo @ (println (next) (arg)))    # Print argument twice
-> foo
: (foo 123)
123 123
-> 123
: (de foo @
   (println (arg 1) (arg 2))
   (println (next))
   (println (arg 1) (arg 2)) )
-> foo
: (foo 'a 'b 'c)
a b
a
b c
-> c

(args) -> flg
Can only be used inside functions with a variable number of arguments (with @). Returns T when there are more arguments to be fetched from the internal list. See also next, arg, rest and pass.


: (de foo @ (println (args)))       # Test for arguments
-> foo
: (foo)                             # No arguments
NIL
-> NIL
: (foo NIL)                         # One argument
T
-> T
: (foo 123)                         # One argument
T
-> T

(argv [sym ..] [. sym]) -> lst|sym
If called without arguments, argv returns a list of strings containing all remaining command line arguments. Otherwise, the sym arguments are subsequently bound to the command line arguments. A hyphen "-" can be used to stop loading further arguments. See also Invocation and opt.


$ ./p -"println 'Ok" - abc 123
Ok
: (argv)
-> ("abc" "123")
: (argv A B)
-> "123"
: A
-> "abc"
: B
-> "123"
: (argv . Lst)
-> ("abc" "123")
: Lst
-> ("abc" "123")

(as 'any1 . any2) -> any2 | NIL
Returns any2 unevaluated when any1 evaluates to non-NIL. Otherwise NIL is returned. (as Flg A B C) is equivalent to (and Flg '(A B C)). See also quote.


: (as (= 3 3) A B C)
-> (A B C)

(asoq 'any 'lst) -> lst
Searches an association list. Returns the first element from lst with any as its CAR, or NIL if no match is found. == is used for comparison (pointer equality). See also assoc, delq, memq and mmeq.


: (asoq 999 '((999 1 2 3) (b . 7) ("ok" "Hello")))
-> NIL
: (asoq 'b '((999 1 2 3) (b . 7) ("ok" "Hello")))
-> (b . 7)

(assoc 'any 'lst) -> lst
Searches an association list. Returns the first element from lst with its CAR equal to any, or NIL if no match is found.


: (assoc "b" '((999 1 2 3) ("b" . 7) ("ok" "Hello")))
-> ("b" . 7)
: (assoc 999 '((999 1 2 3) ("b" . 7) ("ok" "Hello")))
-> (999 1 2 3)
: (assoc 'u '((999 1 2 3) ("b" . 7) ("ok" "Hello")))
-> NIL

(at '(cnt1 . cnt2) . prg) -> any
Increments cnt1 (destructively), and returns NIL when it is less than cnt2. Otherwise, prg is executed and cnt1 is reset to zero. Returns the result of prg.


: (do 11 (prin ".") (at (0 . 3) (prin "!")))
...!...!...!..-> NIL

(atom 'any) -> flg
Returns T when the argument any is an atom (a number or a symbol). See also pair.


: (atom 123)
-> T
: (atom 'a)
-> T
: (atom NIL)
-> T
: (atom (123))
-> NIL


B

(be sym . any) -> sym
Declares a Pilog fact or rule for the sym argument, by concatenating the any argument to the T property of sym. See also goal and prove.


: (be likes (John Mary))
-> likes
: (be likes (John @X) (likes @X wine) (likes @X food))
-> likes
: (get 'likes T)
-> (((John Mary)) ((John @X) (likes @X wine) (likes @X food)))
: (? (likes John @X))
 @X=Mary
-> NIL

(begin) -> T
Opens a nested transaction. Not needed for normal single-level transaction processing with commit and rollback.


: (pool "db")
-> T
: (put '{1} 'str "Hello")        # Set property in first level
-> "Hello"
: (begin)                        # Start second level
-> T
: (put '{1} 'str "abc")          # Set another value
-> "abc"
: (get '{1} 'str)
-> "abc"
: (rollback)                     # Rollback second level
-> NIL
: (get '{1} 'str)                # Value is restored
-> "Hello"
: (rollback)                     # Rollback top level
-> T
: (get '{1} 'str)                # Value is cleared
-> NIL

(bind 'sym|lst . prg) -> any
Binds value(s) to symbol(s). The first argument sym must evaluate to a symbol, a list of symbols, or to a list of symbol-value pairs. The values of these symbols are saved (and the symbols bound to the values in the last case), prg is executed, then the symbols are restored to their original values. During execution of prg, the values of the symbols can be temporarily modified. The return value is the result of prg. See also let, job and use.


: (setq X 123)                               # X is 123
-> 123
: (bind 'X '((setq X "Hello") (println X)))  # Set X to "Hello", print it
"Hello"
-> "Hello"
: (bind '((X . 3) (Y . 4)) '((println X Y) (* X Y)))
3 4
-> 12
: X
-> 123                                       # X is restored to 123

(bit? 'num ..) -> num | NIL
Returns the first num argument when all bits which are 1 in the first argument are also 1 in all following arguments. See also &, | and x|.


: (bit? 7 15 255)
-> 7
: (bit? 1 3)
-> 1
: (bit? 1 2)
-> NIL

(bool 'any) -> flg
Returns T when the argument any is non-NIL. This function is only needed when T is strictly required for a "true" condition (Usually, any non-NIL value is considered to be "true"). See also flg?.


: (and 3 4)
-> 4
: (bool (and 3 4))
-> T

(box 'any) -> sym
Creates and returns a new anonymous symbol. The initial value is set to the any argument. See also new and box?.


: (show (box '(A B C)))
$134425627 (A B C)
-> $134425627

(box? 'any) -> sym | NIL
Returns the argument any when it is an anonymous symbol, otherwise NIL. See also box, str? and ext?.


: (box? (new))
-> $134563468
: (box? 123)
-> NIL
: (box? 'a)
-> NIL
: (box? NIL)
-> NIL

(by 'fun1 'fun2 'lst ..) -> lst
Applies fun1 to each element of lst. When additional lst arguments are given, their elements are also passed to fun1. Each result of fun1 is CONSed with its corresponding argument form the original lst, and collected into a list which is passed to fun2. For the list returned from fun2, the CAR elements returned by fun1 are (destructively) removed from each element.


: (let (A 1 B 2 C 3) (by val sort '(C A B)))
-> (A B C)
: (by '((N) (bit? 1 N)) group (3 11 6 2 9 5 4 10 12 7 8 1))
-> ((3 11 9 5 7 1) (6 2 4 10 12 8))

(bye 'cnt|NIL)
Executes all pending finally expressions, then the VAL of the global variable *Bye (should be a prg), closes all open files, and exits the Pico Lisp interpreter. The process return value is cnt, or 0 if the argument is missing or NIL.


: (setq *Bye '((println 'Ok) (println 'bye)))
-> ((println 'Ok) (println 'bye))
: (bye)
Ok
bye
$


C

(caaar 'lst) -> any
List access shortcut: Equivalent to (car (car (car 'lst))).


: (caaar '(((1 2) 3) 4))
-> 1

(caadr 'lst) -> any
List access shortcut: Equivalent to (car (car (cdr 'lst))).


: (caadr '(1 (2 3)))
-> 2

(caar 'lst) -> any
List access shortcut: Equivalent to (car (car 'lst)).


: (caar '((1 2) (3 4)))
-> 1

(cadar 'lst) -> any
List access shortcut: Equivalent to (car (cdr (car 'lst))).


: (cadar '((1 2 3)))
-> 2

(cadddr 'lst) -> any
List access shortcut: Equivalent to (car (cdr (cdr (cdr 'lst)))), or the fourth element of lst.


: (cadddr (1 2 3 4 5 6))
-> 4

(caddr 'lst) -> any
List access shortcut: Equivalent to (car (cdr (cdr 'lst))), or the third element of lst.


: (caddr (1 2 3 4 5 6))
-> 3

(cadr 'lst) -> any
List access shortcut: Equivalent to (car (cdr 'lst)), or the second element of lst.


: (cadr (1 2 3 4 5 6))
-> 2

(call 'any ..) -> flg
Calls an external system command. The any arguments specify the command and its arguments. Returns T if the command was executed successfully.


: (when (call 'test "-r" "file.l")  # Test if file exists and is readable
   (load "file.l")                  # Load it
   (call 'rm "file.l") )            # Remove it

(car 'lst) -> any
List access: Returns the first element of lst.


: (car (1 2 3 4 5 6))
-> 1

(case 'any (any1 . prg1) (any2 . prg2) ..) -> any
Multi-way branch: any is evaluated and compared to the CAR elements anyN of each clause. If one of them is a list, any is in turn compared to all elements of that list. T is a catch-all for any value. If a comparison succeeds, prgN is executed, and the result returned. Otherwise NIL is returned.


: (case (char 66) ("A" (+ 1 2 3)) (("B" "C") "Bambi") ("D" (* 1 2 3)))
-> "Bambi"

(catch 'sym . prg) -> any
Sets up the environment for a non-local jump with throw. sym is used by throw as a jump label (with T being a catch-all for any label). If throw is called during the execution of prg, the value thrown is returned immediately. Otherwise, the result of prg is returned. See also finally.


: (catch 'Ok (println 1) (throw 'Ok 999) (println 2))
1
-> 999

(cd 'any) -> sym
Changes the current directory to any. The old directory is returned on success, otherwise NIL. See also dir and pwd.


: (when (cd "lib")
   (println (sum lines (dir)))
   (cd @) )
10955

(cdaar 'lst) -> any
List access shortcut: Equivalent to (cdr (car (car 'lst))).


: (cdaar '(((1 2 3))))
-> (2 3)

(cdadr 'lst) -> any
List access shortcut: Equivalent to (cdr (car (cdr 'lst))).


: (cdadr '((1 2) (3 4)))
-> (4)

(cdar 'lst) -> any
List access shortcut: Equivalent to (cdr (car 'lst)).


: (cdar '((1 2) (3 4)))
-> (2)

(cddar 'lst) -> any
List access shortcut: Equivalent to (cdr (cdr (car 'lst))).


: (cddar '((1 2 3 4)))
-> (3 4)

(cddddr 'lst) -> any
List access shortcut: Equivalent to (cdr (cdr (cdr (cdr 'lst)))). Returns all but the first four elements of lst.


: (cddddr (1 2 3 4 5 6))
-> (5 6)

(cdddr 'lst) -> any
List access shortcut: Equivalent to (cdr (cdr (cdr 'lst))). Returns all but the first three elements of lst.


: (cdddr (1 2 3 4 5 6))
-> (4 5 6)

(cddr 'lst) -> any
List access shortcut: Equivalent to (cdr (cdr 'lst)). Returns all but the first two elements of lst.


: (cddr (1 2 3 4 5 6))
-> (3 4 5 6)

(cdr 'lst) -> any
List access: Returns all but the first element of lst.


: (cdr (1 2 3 4 5 6))
-> (2 3 4 5 6)

(chain 'lst ..) -> lst
Concatenates (destructively) one or several new list elements lst to the end of the list in the current make environment. This operation is efficient also for long lists, because a pointer to the last element of the list is maintained. chain returns the last linked argument. See also link and made.


: (make (chain (list 1 2 3) NIL (cons 4)) (chain (list 5 6)))
-> (1 2 3 4 5 6)

(char) -> sym
(char 'cnt) -> sym
(char T) -> sym
(char 'sym) -> cnt
When called without arguments, the next character from the current input stream is returned as a single-character transient symbol, or NIL upon end of file. When called with a number cnt, a character with the corresponding unicode value is returned. As a special case, T is accepted to produce a byte value greater than any first byte in a unicode character (used as a top value in comparisons). Otherwise, when called with a symbol sym, the numeric unicode value of the first character of the name of that symbol is returned. See also peek, skip, key, line, till and eof.


: (char)                   # Read character from console
A                          # (typed 'A' and a space/return)
-> "A"
: (char 100)               # Convert unicode to symbol
-> "d"
: (char T)                 # Special case, catch all
-> # (not printable)
: (char "d")               # Convert symbol to unicode
-> 100

(chop 'any) -> lst
Returns any as a list of single-character strings. If any is NIL or a symbol with no name, NIL is returned. A list argument is returned unchanged.


: (chop 'car)
-> ("c" "a" "r")
: (chop "Hello")
-> ("H" "e" "l" "l" "o")

(circ 'any ..) -> lst
Produces a circular list of all any arguments by consing them to a list and then connecting the CDR of the last cell to the first cell. See also list.


: (circ 'a 'b 'c)
-> (a b c .)

(clip 'lst) -> lst
Returns a copy of lst with all white space characters or NIL elements removed from both sides. See also trim.


: (clip '(NIL 1 NIL 2 NIL))
-> (1 NIL 2)
: (clip '(" " a " " b " "))
-> (a " " b)

(close 'cnt) -> flg
Closes a file descriptor cnt, and returns non-NIL when successful. See also open, listen and connect.


: (close 2)                            # Close standard error
-> T

(cnt 'fun 'lst ..) -> cnt
Applies fun to each element of lst. When additional lst arguments are given, their elements are also passed to fun. Returns the count of non-NIL values returned from fun.


: (cnt cdr '((1 . T) (2) (3 4) (5)))
-> 2

(commit ['any] [exe1] [exe2]) -> flg
Closes a transaction, by writing all new or modified external symbols to the database, and by removing all deleted symbols from the database. For nested transactions, only the changes since the last call to begin are taken into account. A non-NIL any argument forces modifications of the current transaction level to be written out, even if this is not the top level. When any is anything other than T, it is implicitly sent (with all modified objects) via the tell mechanism to all family members. If exe1 or exe2 are given, they are executed as pre- or post-expressions while the database is locked and protected. Returns T when the topmost transaction is closed. See also rollback.


: (pool "db")
-> T
: (put '{1} 'str "Hello")
-> "Hello"
: (commit)
-> T

(con 'lst 'any) -> any
Connects any to the first cell of lst, by (destructively) storing any in the CDR of lst.


: (setq C (1 . a))
-> (1 . a)
: (con C '(b c d))
-> (b c d)
: C
-> (1 b c d)

(conc 'lst ..) -> lst
Concatenates all argument lists (destructively). See also append.


: (setq  A (1 2 3)  B '(a b c))
-> (a b c)
: (conc A B)                        # Concatenate lists in 'A' and 'B'
-> (1 2 3 a b c)
: A
-> (1 2 3 a b c)                    # Side effect: List in 'A' is modified!

(cond (('any1 . prg1) ('any2 . prg2) ..)) -> any
Multi-way conditional: If any of the anyN conditions evaluates to non-NIL, prgN is executed and the result returned. Otherwise (all conditions evaluate to NIL), NIL is returned. See also nond, if, if2 and when.


: (cond
   ((= 3 4) (println 1))
   ((= 3 3) (println 2))
   (T (println 3)) )
2
-> 2

(connect 'any 'cnt) -> cnt | NIL
Tries to establish a TCP/IP connection to a server listening at host any, port cnt. any may be either a hostname or a standard internet address in numbers-and-dots notation. Returns a socket descriptor cnt, or NIL if the connection cannot be established. See also listen and nagle.


: (connect "localhost" 4444)
-> 3

(cons 'any 'any) -> lst
Constructs a new list cell with the first argument in the CAR and the second argument in the CDR.


: (cons 1 2)
-> (1 . 2)
: (cons 'a '(b c d))
-> (a b c d)
: (cons '(a b) '(c d))
-> ((a b) c d)

(copy 'any) -> any
Copies the argument any. For lists, the top level cells are copied, while atoms are returned unchanged.


: (=T (copy T))               # Atoms are not copied
-> T
: (setq L (1 2 3))
-> (1 2 3)
: (== L L)
-> T
: (== L (copy L))             # The copy is not identical to the original
-> NIL
: (= L (copy L))              # But the copy is equal to the original
-> T

(ctl 'sym . prg) -> any
Waits until a write (exclusive) lock (or a read (shared) lock if the first character of sym is "+") can be set on the file sym, then executes prg and releases the lock. If the files does not exist, it will be created. When sym is NIL, a shared lock is tried on the current innermost I/O channel, and when it is T, an exclusive lock is tried instead. See also in, pipe and out. Note: It is not recommended to lock a file by name and then do I/O on the same file, as this may give unexpected results on some operating systems.


$ echo 9 >count                           # Write '9' to file "count"
$ ./p dbg.l
: (ctl ".ctl"                             # Exclusive control, using ".ctl"
   (in "count"
      (let Cnt (read)                     # Read '9'
         (out "count"
            (println (dec Cnt)) ) ) ) )   # Write '8'
-> 8
:
$ cat count                               # Check "count"
8

(ctty 'sym|pid) -> flg
When called with a symbolic argument, ctty changes the current TTY device to sym. Otherwise, the local console is prepared for serving the remote Pico Lisp process pid. See also raw.


: (ctty "/dev/tty")
-> T

(cut 'cnt 'var) -> lst
Pops the first cnt elements (CAR) from the stack in var. See also pop and del.


: (setq S '(1 2 3 4 5 6 7 8))
-> (1 2 3 4 5 6 7 8)
: (cut 3 'S)
-> (1 2 3)
: S
-> (4 5 6 7 8)


D

(date ['T]) -> dat
(date 'dat) -> (y m d)
(date 'y 'm 'd) -> dat | NIL
(date '(y m d)) -> dat | NIL
Calculates a calendar date, represented as the number of days since first of March in the year 0. When called without arguments, the current date is returned. When called with a T argument, the current Coordinated Universal Time (UTC) is returned. When called with a single number dat, it is taken as a date and a list with the corresponding year, month and day is returned. When called with three numbers (or a list of three numbers) for the year, month and day, the corresponding date is returned (or NIL if they do not represent a legal date). See also time.


: (date)                         # Today
-> 730589
: (date 2000 6 12)               # 12-06-2000
-> 730589
: (date 2000 22 5)               # Illegal date
-> NIL
: (date (date))                  # Today's year, month and day
-> (2000 6 12)
: (- (date) (date 2000 1 1))     # Number of days since first of January
-> 163

(dbck ['cnt] 'flg) -> any
Performs a low-level integrity check of the current (or cnt'th) database file, and returns NIL (or the number of blocks and symbols if flg is non-NIL) if everything seems correct. Otherwise, a string indicating an error is returned. As a side effect, possibly unused blocks (as there might be when a rollback is done before commiting newly allocated (new) external symbols) are appended to the free list.


: (pool "db")
-> T
: (dbck)
-> NIL

(de sym . any) -> sym
Assigns a definition to the sym argument, by setting its VAL to the any argument. If the symbol has already another value, a "redefined" message is issued. de is the standard way to define a function.


: (de foo (X Y) (* X (+ X Y)))  # Define a function
-> foo
: (foo 3 4)
-> 21

: (de *Var . 123)  # Define a variable value
: *Var
-> 123

(debug 'sym) -> T
(debug 'sym 'cls) -> T
(debug '(sym . cls)) -> T
Inserts a ! breakpoint function call at the beginning and all top-level expressions of the function or method body of sym, to allow a stepwise execution. Typing (d) at a breakpoint will also debug the current subexpression, and (e) will evaluate the current subexpression. The current subexpression is stored in the global variable ^. See also *Dbg.


: (de tst (N)                    # Define tst
   (println (+ 3 N)) )
-> tst
: (debug 'tst)                   # Set breakpoints
-> T
: (pp 'tst)
(de tst (N)
   (! println (+ 3 N)) )         # Breakpoint '!'
-> tst
: (tst 7)                        # Execute
(println (+ 3 N))                # Stopped at beginning of 'tst'
! (d)                            # Debug subexpression
-> T
!                                # Continue
(+ 3 N)                          # Stopped in subexpression
! N                              # Inspect variable 'N'
-> 7
!                                # Continue
10                               # Output of print statement
-> 10                            # Done
: (unbug 'tst)
-> T
: (pp 'tst)                      # Restore to original
(de tst (N)
   (println (+ 3 N)) )
-> tst

(dec 'num) -> num
(dec 'var ['num]) -> num
The first form returns the value of num decremented by 1. The second form decrements the VAL of var by 1, or by num. (dec 'num) is equivalent to (- 'num 1) and (dec 'var) is equivalent to (set 'var (- var 1)).


: (dec -1)
-> -2
: (dec 7)
-> 6
: (setq N 7)
-> 7
: (dec 'N)
-> 6
: (dec 'N 3)
-> 3

(def 'sym 'any) -> sym
(def 'sym 'sym 'any) -> sym
The first form assigns a definition to the first sym argument, by setting its VAL's to any. The second form defines a property value any for the second argument's sym key. If any of these values existed and was changed in the process, a "redefined" message is issued.


: (def 'b '((X Y) (* X (+ X Y))))
-> b
: (def 'b 999)
# b redefined
-> b

(default sym 'any ..) -> any
Stores new values any in the sym arguments only if their current values are NIL. Otherwise, their values are left unchanged. default is used typically in functions to initialize optional arguments.


: (de foo (A B)               # Function with two optional arguments
   (default  A 1  B 2)        # The default values are 1 and 2
   (list A B) )
-> foo
: (foo 333 444)               # Called with two arguments
-> (333 444)
: (foo 333)                   # Called with one arguments
-> (333 2)
: (foo)                       # Called without arguments
-> (1 2)

(del 'any 'var) -> any
Deletes any from the list in the value of var. (del 'any 'var) is equivalent to (set 'var (delete 'any var)). See also delete, cut and pop.


: (setq S '((a b c) (d e f)))
-> ((a b c) (d e f))
: (del '(d e f) 'S)
-> ((a b c))
: (del 'b S)
-> (a c)

(delete 'any 'lst) -> lst
Deletes any from lst. If any is contained more than once in lst, only the first occurrence is deleted. See also delq.


: (delete 2 (1 2 3))
-> (1 3)
: (delete (3 4) '((1 2) (3 4) (5 6) (3 4)))
-> ((1 2) (5 6) (3 4))

(delq 'any 'lst) -> lst
Deletes any from lst. If any is contained more than once in lst, only the first occurrence is deleted. == is used for comparison (pointer equality). See also delete, asoq, memq and mmeq.


: (delq 'b '(a b c))
-> (a c)
: (delq 2 (1 2 3))
-> (1 2 3)

(die 'cnt . prg) -> any
If the execution of prg does not finish within cnt seconds, the current process will receive a SIGTERM signal. See also bye and protect.


: (die 6 (finally (msg 'Bye) (loop)))
Bye
$

(diff 'lst 'lst) -> lst
Returns the difference of the lst arguments. See also sect.


: (diff (1 2 3 4 5) (2 4))
-> (1 3 5)
: (diff (1 2 3) (1 2 3))
-> NIL

(dir ['any]) -> lst
Returns a list of all filenames in the directory any. Names starting with a dot '.' are ignored. See also cd and info.


: (filter '((F) (tail '(. c) (chop F))) (dir "src/"))
-> ("main.c" "subr.c" "gc.c" "io.c" "big.c" "sym.c" "tab.c" "flow.c" ..

(dm sym . fun) -> sym
(dm (sym . cls) . fun) -> sym
(dm (sym sym [. cls]) . fun) -> sym
Defines a method for the message sym in the current class, implicitly given by the value of the global variable *Class, or - in the second form - for the explicitly given class cls. In the third form, the class object is obtained by geting sym from *Class (or cls if given).


: (dm start> ()
   (super)
   (mapc 'start> (: fields))
   (mapc 'start> (: arrays)) )

(do 'flg|num ['any | (NIL 'any . prg) | (T 'any . prg) ..]) -> any
Counted loop with multiple conditional exits: The body is executed at most num times (or never (if the first argument is NIL), or an infinite number of times (if the first argument is T)). If a clause has NIL or T as its CAR, the clause's second element is evaluated as a condition and - if the result is NIL or non-NIL, respectively - the prg is executed and the result returned. Otherwise (if count drops to zero), the result of the last expression is returned. See also loop and for.


: (do 4 (printsp 'Ok))
Ok Ok Ok Ok -> Ok
: (do 4 (printsp 'Ok) (T (= 3 3) (printsp 'done)))
Ok done -> done


E

(e . prg) -> any
Used in a breakpoint. Evaluates prg in the execution environment, or the currently executed expression if prg is not given. See also debug, !, ^ and *Dbg.


: (! + 3 4)
(+ 3 4)
! (e)
-> 7

(echo ['cnt ['cnt]] | ['sym ..]) -> sym
Reads the current input channel, and writes to the current output channel. If cnt is given, only that many bytes are actually echoed. In case of two cnt arguments, the first one specifies the number of bytes to skip in the input stream. Otherwise, if one or more sym arguments are given, the echo process stops as soon as one of the symbol's names is encountered in the input stream (in that case, the name will be read (and returned), but not written). Returns non-NIL if the operation was successfully completed.


: (in "x.l" (echo))                    # Display file on console
 ..

: (out "x2.l" (in "x.l" (echo)))       # Copy file "x.l" to "x2.l"

(env ['lst] | ['sym 'val] ..) -> lst
Return a list of symbol-value pairs of all dynamically bound symbols if called without arguments, or of the symbols in lst, or the explicitly given sym-val pairs. See also stk, bind and job.


: (env)
-> NIL
: (let (A 1 B 2) (env))
-> ((A . 1) (B . 2))
: (let (A 1 B 2) (env '(A B)))
-> ((B . 2) (A . 1))
: (let (A 1 B 2) (env 'X 7 '(A B) 'Y 8))
-> ((Y . 8) (B . 2) (A . 1) (X . 7))

(eof ['flg]) -> flg
Returns the end-of-file status of the current input channel. If flg is non-NIL, the channel's status is forced to end-of-file, so that the next call to eof will return T, and calls to char, peek, line, from, till, read or skip will return NIL. Note that eof cannot be used with the binary rd function.


: (in "file" (until (eof) (println (line T))))
...

(eval 'any ['cnt]) -> any
Evaluates any. Note that because of the standard argument evaluation, any is actually evaluated twice. If a binding environment offset cnt is given, the second evaluation takes place in the corresponding environment. See also run and up.


: (eval (list '+ 1 2 3))
-> 6
: (setq X 'Y  Y 7)
-> 7
: X
-> Y
: Y
-> 7
: (eval X)
-> 7

(ext? 'any) -> sym | NIL
Returns the argument any when it is an existing external symbol, otherwise NIL. See also sym?, box?, str?, extern and lieu.


: (ext? *DB)
-> {1}
: (ext? 'abc)
-> NIL
: (ext? "abc")
-> NIL
: (ext? 123)
-> NIL

(extern 'sym) -> sym | NIL
Creates or finds an external symbol. If a symbol with the name sym is already extern, it is returned. Otherwise, a new external symbol is returned. NIL is returned if sym does not exist in the database. See also intern and ext?.


: (extern "A1b")
-> {A1b}
: (extern "{A1b}")
-> {A1b}

(extra ['any ..]) -> any
Can only be used inside methods. Sends the current message to the current object This, this time starting the search for a method at the remaining branches of the inheritance tree of the class where the current method was found.


(dm key> (C)            # 'key>' method of the '+Uppc' class
   (uppc (extra C)) )   # Convert 'key>' of extra classes to upper case


F

(fifo 'var ['any]) -> any
Implements a first-in-first-out structure using a circular list. When called with an any argument, it will be concatenated to end of the structure. Otherwise, the first element is removed from the structure and returned. See also queue, push, pop, rot and circ.


: (fifo 'X 1)
-> 1
: (fifo 'X 2)
-> 2
: (fifo 'X 3)
-> 3
: X
-> (3 1 2 .)
: (fifo 'X)
-> 1
: (fifo 'X)
-> 2
: X
-> (3 .)

(fill 'any ['sym|lst]) -> any
Fills a pattern any, by substituting sym, or all symbols in lst, or - if no second argument is given - each pattern symbol in any (see pat?), with its current value. In that case, @ itself is not considered a pattern symbol. See also match.


: (setq  @X 1234  @Y (1 2 3 4))
-> (1 2 3 4)
: (fill '@X)
-> 1234
: (fill '(a b (c @X) ((@Y . d) e)))
-> (a b (c 1234) (((1 2 3 4) . d) e))
: (let X 2 (fill (1 X 3) 'X))
-> (1 2 3)

(filter 'fun 'lst ..) -> lst
Applies fun to each element of lst. When additional lst arguments are given, their elements are also passed to fun. Returns a list of all elements of lst where fun returned non-NIL. See also fish.


: (filter num? (1 A 2 (B) 3 CDE))
-> (1 2 3)

(fin 'any) -> num|sym
Returns any if it is an atom, otherwise the CDR of its last cell. See also last and tail.


: (fin 'a)
-> a
: (fin '(a . b))
-> b
: (fin '(a b . c))
-> c
: (fin '(a b c))
-> NIL

(finally exe . prg) -> any
prg is executed, then exe is evaluated, and the result of prg is returned. exe will also be evaluated if prg does not terminate normally due to a runtime error or a call to throw. See also bye, catch, quit and Error Handling.


: (finally (prinl "Done!")
   (println 123)
   (quit)
   (println 456) )
123
Done!
: (catch 'A
   (finally (prinl "Done!")
      (println 1)
      (throw 'A 123)
      (println 2) ) )
1
Done!
-> 123

(find 'fun 'lst ..) -> any
Applies fun to successive elements of lst until non-NIL is returned. Returns that element, or NIL if fun did not return non-NIL for any element of lst. When additional lst arguments are given, their elements are also passed to fun. See also seek, pick.


: (find pair (1 A 2 (B) 3 CDE))
-> (B)
: (find '((A B) (> A B)) (1 2 3 4 5 6) (6 5 4 3 2 1))
-> 4
: (find > (1 2 3 4 5 6) (6 5 4 3 2 1))  # shorter
-> 4

(fish 'fun 'any) -> lst
Applies fun to each element - and recursively to all sublists - of lst. Returns a list of all items where fun returned non-NIL. See also filter.


: (fish gt0 '(a -2 (1 b (-3 c 2)) 3 d -1))
-> (1 2 3)
: (fish sym? '(a -2 (1 b (-3 c 2)) 3 d -1))
-> (a b c d)

(flg? 'any) -> flg
Returns T when the argument any is either NIL or T. See also bool. (flg? X) is equivalent to (or (not X) (=T X)).


: (flg? (= 3 3))
-> T
: (flg? (= 3 4))
-> T
: (flg? (+ 3 4))
-> NIL

(flip 'lst) -> lst
Returns lst (destructively) reversed. See also reverse.


: (flip (1 2 3 4))
-> (4 3 2 1)

(flush) -> flg
Flushes the current output stream by writing all buffered data. A call to flush for standard output is done automatically before a call to key. Returns T when successful. See also rewind.


: (flush)
-> T

(fold 'any ['cnt]) -> sym
Folding to a canonical form: If any is not a symbol, NIL is returned. Otherwise, a new transient symbol with all digits and all letters of any, converted to lower case, is returned. If the cnt argument is given, the result is truncated to that length (or not truncated if cnt is zero). Otherwise cnt defaults to 24. See also lowc.


: (fold " 1A 2-b/3")
-> "1a2b3"
: (fold " 1A 2-B/3" 3)
-> "1a2"

(for sym|(sym2 . sym) 'lst ['any | (NIL 'any . prg) | (T 'any . prg) ..]) -> any
(for (sym|(sym2 . sym) 'any1 'any2 [. prg]) ['any | (NIL 'any . prg) | (T 'any . prg) ..]) -> any
Conditional loop with local variable(s) and multiple conditional exits: In the first form, the value of sym is saved, sym is subsequently bound to the elements of lst, and the body is executed each time. In the second form, the value of sym is saved, and sym is bound to any1. If sym2 is given, it is treated as a counter variable, first bound to 1 and then incremented for each execution of the body. While the condition any2 evaluates to non-NIL, the body is repeatedly executed and, if prg is given, sym is re-bound to the result of its evaluation. If a clause has NIL or T as its CAR, the clause's second element is evaluated as a condition and - if the result is NIL or non-NIL, respectively - the prg is executed and the result returned. If the body is never executed, NIL is returned. See also do and loop.


: (for (N 1 (>= 8 N) (inc N)) (printsp N))
1 2 3 4 5 6 7 8 -> 8
: (for (L (1 2 3 4 5 6 7 8) L) (printsp (pop 'L)))
1 2 3 4 5 6 7 8 -> 8
: (for X (1 a 2 b) (printsp X))
1 a 2 b -> b
: (for ((I . L) '(a b c d e f) L (cddr L)) (println I L))
1 (a b c d e f)
2 (c d e f)
3 (e f)
-> (e f)
: (for (I . X) '(a b c d e f) (println I X))
1 a
2 b
3 c
4 d
5 e
6 f
-> f

(fork) -> pid | NIL
Forks a child process. Returns NIL in the child, and the child's process ID pid in the parent. In the child, the VAL of the global variable *Fork (should be a prg) is executed. See also pipe and tell.


: (unless (fork) (do 5 (println 'Ok) (wait 1000)) (bye))
-> NIL
Ok                                              # Child's output
: Ok
Ok
Ok
Ok

(format 'num ['cnt ['sym1 ['sym2]]]) -> sym
(format 'sym ['cnt ['sym1 ['sym2]]]) -> num
Converts a number num to a string, or a string sym to a number. In both cases, optionally a precision cnt, a decimal-separator sym1 and a thousands-separator sym2 can be supplied. Returns NIL if the conversion is unsuccessful. See also Numbers.


: (format 123456789)                   # Integer conversion
-> "123456789"
: (format 123456789 2)                 # Fixed point
-> "1234567.89"
: (format 123456789 2 ",")             # Comma as decimal-separator
-> "1234567,89"
: (format 123456789 2 "," ".")         # and period as thousands-separator
-> "1.234.567,89"
:
: (format "123456789")                 # String to number
-> 123456789
: (format "1234567.89" 4)              # scaled to four digits
-> 12345678900
: (format "1.234.567,89")              # separators not recognized
-> NIL
: (format "1234567,89" 4 ",")
-> 12345678900
: (format "1.234.567,89" 4 ",")        # thousands-separator not recognized
-> NIL
: (format "1.234.567,89" 4 "," ".")
-> 12345678900

(free 'cnt) -> (sym . lst)
Returns, for the cnt'th database file, the next available symbol sym (i.e. the first symbol greater than any symbol in the database), and the list lst of free symbols. See also seq, zap and dbck.


: (pool "x")      # A new database
-> T
: (new T)         # Create a new symbol
-> {2}
: (new T)         # Create another symbol
-> {3}
: (commit)        # Commit changes
-> T
: (zap '{2})      # Delete the first symbol
-> {2}
: (free 1)        # Show free list
-> ({4})          # {3} was the last symbol allocated
: (commit)        # Commit the deletion of {2}
-> T
: (free 1)        # Now {2} is in the free list
-> ({4} {2})

(from 'any ..) -> sym
Skips the current input channel until one of the strings any is found, and starts subsequent reading from that point. The found any argument, or NIL (if none is found) is returned. See also till and echo.


: (and (from "val='") (till "'" T))
test val='abc'
-> "abc"

(fun? 'any) -> any
Returns NIL when the argument any is neither a number suitable for a code-pointer, nor a list suitable for a lambda expression (function). Otherwise a number is returned for a code-pointer, T for a function without arguments, and a single formal parameter or a list of formal parameters for a function.


: (fun? 1000000000)              # Might be a code pointer
-> 1000000000
: (fun? 100000000000000)         # Too big for a code pointer
-> NIL
: (fun? 1000000001)              # Cannot be a code pointer (odd)
-> NIL
: (fun? '((A B) (* A B)))        # Lambda expression
-> (A B)
: (fun? '((A B) (* A B) . C))    # Not a lambda expression
-> NIL
: (fun? '(1 2 3 4))              # Not a lambda expression
-> NIL
: (fun? '((A 2 B) (* A B)))      # Not a lambda expression
-> NIL


G

(gc ['cnt]) -> cnt | NIL
Forces a garbage collection. When cnt is given, so many millions of free cells are reserved, increasing the heap size if necessary.


: (gc)
-> NIL
: (stat)
2 3%
-> 53299
: (gc 4)
-> 4
: (stat)
5 1%
-> 53322

(ge0 'any) -> num | NIL
Returns num when the argument is a number and greater or equal zero, otherwise NIL. See also gt0, lt0, =0 and n0.


: (ge0 -2)
-> NIL
: (ge0 3)
-> 3
: (ge0 0)
-> 0

(get 'sym1|lst ['sym2|cnt ..]) -> any
Fetches a value any from the properties of a symbol, or from a list. From the first argument sym1|lst, values are retrieved in successive steps by either extracting the value (if the next argument is zero) or a property (if the next argument is a symbol) from a symbol, the asoqed element (if the next argument is a symbol), the n'th element (if the next argument is a positive number) or the n'th CDR (if the next argument is a negative number) from a list. See also put and :.


: (put 'X 'a 1)
-> 1
: (get 'X 'a)
-> 1
: (put 'Y 'link 'X)
-> X
: (get 'Y 'link)
-> X
: (get 'Y 'link 'a)
-> 1
: (get '((a (b . 1) (c . 2)) (d (e . 3) (f . 4))) 'a 'b)
-> 1
: (get '((a (b . 1) (c . 2)) (d (e . 3) (f . 4))) 'd 'f)
-> 4
: (get '(X Y Z) 2)
-> Y
: (get '(X Y Z) 2 'link 'a)
-> 1

(getl 'sym1|lst1 ['sym2|cnt ..]) -> lst
Fetches the complete property list lst from a symbol. That symbol is sym1 (if no other arguments are given), or a symbol found by applying the get algorithm to sym1|lst1 and the following arguments. See also putl and maps.


: (put 'X 'a 1)
-> 1
: (put 'X 'b 2)
-> 2
: (put 'X 'flg T)
-> T
: (getl 'X)
-> (flg (2 . b) (1 . a))

(glue 'any 'lst) -> sym
Builds a new transient symbol (string) by packing the any argument between the individual elements of lst. See also text.


: (glue "," '(a b c d))
-> "a,b,c,d"

(goal '([sym 'any ..] . lst) ['sym 'any ..]) -> lst
Constructs a Pilog query list from the list of clauses lst. The head of the argument list may consist of a sequence of symbols and expressions, which are used together with the optional sym and any arguments to form an initial environment. See also prove.


: (goal '((likes John @X)))
-> (((1 (0) NIL ((likes John @X)) NIL T)))
: (goal '(@X 'John (likes @X @Y)))
-> (((1 (0) NIL ((likes @X @Y)) NIL ((0 . @X) 1 . John) T)))

(gt0 'any) -> num | NIL
Returns num when the argument is a number and greater than zero, otherwise NIL. See also ge0, lt0, =0 and n0.


: (gt0 -2)
-> NIL
: (gt0 3)
-> 3


H

(head 'cnt|lst 'lst) -> lst
Returns a new list made of the first cnt elements of lst. If cnt is negative, it is added to the length of lst. If the first argument is a lst, head is a predicate function returning that argument list if it is equal to the head of the second argument, and NIL otherwise. See also tail.


: (head 3 '(a b c d e f))
-> (a b c)
: (head 0 '(a b c d e f))
-> NIL
: (head 10 '(a b c d e f))
-> (a b c d e f)
: (head -2 '(a b c d e f))
-> (a b c d)
: (head '(a b c) '(a b c d e f))
-> (a b c)

(heap 'flg) -> cnt
Returns the number of free cells currently available (if flg is NIL), or the total number of cells in the system (if flg is non-NIL).


: (heap)
-> 126999
: (heap T)
-> 262144

(hear 'num|sym) -> any
Uses the file descriptor num, or opens the file sym, as an asynchronous command input channel. Any executable list received via this channel will be executed in the background. As this mechanism is also used for inter-family communication (see tell), hear is usually only called explicitly by a top level parent process.


: (hear "fifo/cmd")
-> "fifo/cmd"

(host 'any) -> sym
Returns the hostname corresponding to the given IP address. See also *Adr.


: (host "217.160.106.89")
-> "software-lab.biz"


I

(id 'num 'num) -> sym
(id 'sym [NIL]) -> num
(id 'sym T) -> (num . num)
Converts two numbers to an external symbol, or an external symbol to a number or a pair of numbers.


: (id 1 2)
-> {1-2}
: (id '{1-2})
-> 2
: (id '{1-2} T)
-> (1 . 2)

(idx 'var 'any 'flg) -> lst
(idx 'var 'any) -> lst
(idx 'var) -> lst
Maintains an index tree in var, and checks for the existence of any. If any is contained in var, the corresponding subtree is returned, otherwise NIL. In the first form, any is destructively inserted into the tree if flg is non-NIL, or deleted from the tree if flg is NIL. The second form only checks for existence, but does not change the index tree. In the third form (when called with a single var argument) the contents of the tree are returned as a sorted list. If all elements are inserted in sorted order, the tree degenerates into a linear list. See also lup, sort and member.


: (idx 'X 'd T)                              # Insert data
-> NIL
: (idx 'X 2 T)
-> NIL
: (idx 'X '(a b c) T)
-> NIL
: (idx 'X 17 T)
-> NIL
: (idx 'X 'A T)
-> NIL
: (idx 'X 'd T)
-> (d (2 NIL 17 NIL A) (a b c))              # 'd' already existed
: (idx 'X T T)
-> NIL
: X                                          # View the index tree
-> (d (2 NIL 17 NIL A) (a b c) NIL T)
: (idx 'X 'A)                                # Check for 'A'
-> (A)
: (idx 'X 'B)                                # Check for 'B'
-> NIL
: (idx 'X)
-> (2 17 A d (a b c) T)                      # Get list
: (idx 'X 17 NIL)                            # Delete '17'
-> (17 NIL A)
: X
-> (d (2 NIL A) (a b c) NIL T)               # View it again
: (idx 'X)
-> (2 A d (a b c) T)                         # '17' is deleted

(if 'any1 'any2 . prg) -> any
Conditional execution: If the condition any1 evaluates to non-NIL, any2 is evaluated and returned. Otherwise, prg is executed and the result returned. See also cond, when and if2.


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

(if2 'any1 'any2 'any3 'any4 'any5 . prg) -> any
Four-way conditional execution for two conditions: If both conditions any1 and any2 evaluate to non-NIL, any3 is evaluated and returned. Otherwise, any4 or any5 is evaluated and returned if any1 or any2 evaluate to non-NIL, respectively. If none of the conditions evaluate to non-NIL, prg is executed and the result returned. See also if and cond.


: (if2 T T 'both 'first 'second 'none)
-> both
: (if2 T NIL 'both 'first 'second 'none)
-> first
: (if2 NIL T 'both 'first 'second 'none)
-> second
: (if2 NIL NIL 'both 'first 'second 'none)
-> none

(ifn 'any1 'any2 . prg) -> any
Conditional execution ("If not"): If the condition any1 evaluates to NIL, any2 is evaluated and returned. Otherwise, prg is executed and the result returned.


: (ifn (= 3 4) (println 'Ok) (println 'Bad))
Ok
-> Ok

(in 'any . prg) -> any
Opens any as input channel during the execution of prg. The current input channel will be saved and restored appropriately. If the argument is NIL, standard input is used. If the argument is a symbol, it is used as a file name (opened for reading and writing if the first character is "+"). If it is a number, it is used as the descriptor of an open file. Otherwise (if it is a list), it is taken as a command with arguments, and a pipe is opened for input. See also call, load, out, pipe and ctl.


: (in "a" (list (read) (read) (read)))    # Read three items from file "a"
-> (123 (a b c) def)

(inc 'num) -> num
(inc 'var ['num]) -> num
The first form returns the value of num incremented by 1. The second form increments the VAL of var by 1, or by num. (inc 'num) is equivalent to (+ 'num 1) and (inc 'var) is equivalent to (set 'var (+ var 1)).


: (inc 7)
-> 8
: (inc -1)
-> 0
: (zero N)
-> 0
: (inc 'N)
-> 1
: (inc 'N 7)
-> 8
: N
-> 8

: (setq L (1 2 3 4))
-> (1 2 3 4)
: (inc (cdr L))
-> 3
: L
-> (1 3 3 4)

(index 'any 'lst) -> cnt | NIL
Returns the cnt position of any in lst, or NIL if it is not found. See also offset.


: (index 'c '(a b c d e f))
-> 3
: (index '(5 6) '((1 2) (3 4) (5 6) (7 8)))
-> 3

(info 'any) -> (cnt|T dat . tim)
Returns information about a file with the name any: The current size cnt in bytes, and the modification date and time (UTC). For directories, T is returned instead of the a size. See also dir, date, time and lines.


$ ls -l x.l
-rw-r--r--   1 abu      users         208 Jun 17 08:58 x.l
$ ./p dbg.l
: (info "x.l")
-> (208 730594 . 32315)
: (stamp 730594 32315)
-> "2000-06-17 08:58:35"

(intern 'sym) -> sym
Creates or finds an internal symbol. If a symbol with the name sym is already intern, it is returned. Otherwise, sym is interned and returned. See also zap, extern and ====.


: (intern "abc")
-> abc
: (intern 'car)
-> car
: ((intern (pack "c" "a" "r")) (1 2 3))
-> 1

(isa 'cls|typ 'any) -> flg
Returns T when any is an object that inherits from cls or type. See also type.


: (isa '+Address Obj)
-> T
: (isa '(+Male +Person) Obj)
-> NIL


J

(job 'lst . prg) -> any
Executes a job within its own environment (as specified by symbol-value pairs in lst). The current values of all symbols are saved, the symbols are bound to the values in lst, prg is executed, then the (possibly modified) symbol values are (destructively) stored in the environment list, and the symbols are restored to their original values. The return value is the result of prg. Typically used in a *Run task. See also env, bind, let, use and state.


: (de tst ()
   (job '((A . 0) (B . 0))
      (println (inc 'A) (inc 'B 2)) ) )
-> tst
: (tst)
1 2
-> 2
: (tst)
2 4
-> 4
: (tst)
3 6
-> 6
: (pp 'tst)
(de tst NIL
   (job '((A . 3) (B . 6))
      (println (inc 'A) (inc 'B 2)) ) )
-> tst

(journal) -> T
Reads journal data from the current input channel, and writes all changes to the database. See also pool.


: (in "db.log" (journal))
-> T


K

(key ['cnt]) -> sym
Returns the next character from standard input as a single-character transient symbol. The console is set to raw mode. While waiting for a key press, a select system call is executed for all file descriptors and timers in the VAL of the global variable *Run. If cnt is non-NIL, that amount of milliseconds is waited maximally, and NIL is returned upon timeout. See also raw and wait.


: (key)                    # Wait for a key
-> "a"                     # 'a' pressed

(kill 'pid ['cnt]) -> flg
Sends a signal with the signal number cnt (or SIGTERM if cnt is not given) to the process with the ID pid. Returns T if successful.


: (kill *Pid 20)                                # Stop current process

[2]+  Stopped               bin/picolisp        # Unix shell
$ fg                                            # Job control: Foreground
bin/picolisp
-> T                                            # 'kill' was successful


L

(last 'lst) -> any
Returns the last element of lst. See also fin and tail.


: (last (1 2 3 4))
-> 4
: (last '((a b) c (d e f)))
-> (d e f)

(length 'any) -> cnt | T
Returns the "length" of any. For numbers this is the number of digits in the value (plus 1 for negative values), for symbols it is the number of characters in the name, and for lists it is the number of elements (or T for circular lists). See also size.


: (length "abc")
-> 3
: (length "äbc")
-> 3
: (length 123)
-> 3
: (length (1 (2) 3))
-> 3
: (length (1 2 3 .))
-> T

(let sym 'any . prg) -> any
(let (sym 'any ..) . prg) -> any
Defines local variables. The value of the symbol sym - or the values of the symbols sym in the list of the second form - are saved and the symbols are bound to the evaluated any arguments. prg is executed, then the symbols are restored to their original values. The result of prg is returned. It is an error condition to pass NIL as a sym argument. See also let?, bind, job and use.


: (setq  X 123  Y 456)
-> 456
: (let X "Hello" (println X))
"Hello"
-> "Hello"
: (let (X "Hello" Y "world") (prinl X " " Y))
Hello world
-> "world"
: X
-> 123
: Y
-> 456

(let? sym 'any . prg) -> any
Conditional local variable binding and execution: If any evalutes to NIL, NIL is returned. Otherwise, the value of the symbol sym is saved and sym is bound to the evaluated any argument. prg is executed, then sym is restored to its original value. The result of prg is returned. It is an error condition to pass NIL as the sym argument. (let? sym 'any ..) is equivalent to (when 'any (let sym @ ..)). See also let, bind, job and use.


: (setq Lst (1 NIL 2 NIL 3))
-> (1 NIL 2 NIL 3)
: (let? A (pop 'Lst) (println 'A A))
A 1
-> 1
: (let? A (pop 'Lst) (println 'A A))
-> NIL

(lieu 'any) -> sym | NIL
Returns the argument any when it is an external symbol and currently manifest in heap space, otherwise NIL. See also ext?.


: (lieu *DB)
-> {1}

(line 'flg ['cnt ..]) -> lst|sym
Reads a line of characters from the current input channel. End of line is recognized as linefeed (hex "0A"), carriage return (hex "0D"), or the combination of both. (Note that a single carriage return may not work on network connections, because the character look-ahead to distinguish from return+linefeed can block the connection.) If flg is NIL, a list of single-character transient symbols is returned. When cnt arguments are given, subsequent characters of the input line are grouped into sublists, to allow parsing of fixed field length records. If flg is non-NIL, strings are returned instead of single-character lists. NIL is returned upon end of file. See also char, till and eof.


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

(lines 'any ..) -> cnt
Returns the sum of the number of lines in the files with the names any. See also info.


: (lines "x.l")
-> 11

(link 'any ..) -> any
Links one or several new elements any to the end of the list in the current make environment. This operation is efficient also for long lists, because a pointer to the last element of the list is maintained. link returns the last linked argument. See also chain and made.


: (make
   (println (link 1))
   (println (link 2 3)) )
1
3
-> (1 2 3)

(list 'any ..) -> lst
Returns a list of all any arguments.


: (list 1 2 3 4)
-> (1 2 3 4)
: (list 'a (2 3) "Ok")
-> (a (2 3) "Ok")

(lst? 'any) -> flg
Returns T when the argument any is a (possibly empty) list (NIL or a cons pair cell). See also pair.


: (lst? NIL)
-> T
: (lst? (1 . 2))
-> T
: (lst? (1 2 3))
-> T

(listen 'cnt1 ['cnt2]) -> cnt | NIL
Listens at a socket descriptor cnt1 (as received by port) for an incoming connection, and returns the new socket descriptor cnt. While waiting for a connection, a select system call is executed for all file descriptors and timers in the VAL of the global variable *Run. If cnt2 is non-NIL, that amount of milliseconds is waited maximally, and NIL is returned upon timeout. The global variable *Adr is set to the IP address of the client. See also accept, connect, nagle and *Adr.


: (setq *Socket
   (listen (port 6789) 60000) )  # Listen at port 6789 for max 60 seconds
-> 4
: *Adr
-> "127.0.0.1"

(lit 'any) -> any
Returns the literal (i.e. quoted) value of any, by consing it with the quote function if necessary.


: (lit T)
-> T
: (lit 1)
-> 1
: (lit '(1))
-> (1)
: (lit '(a))
-> '(a)

(load 'any ..) -> any
Loads all any arguments. Normally, the name of each argument is taken as a file to be executed in a read-eval loop. The argument semantics are identical to that of in, with the exception that if an argument is a symbol and its first character is a hyphen '-', then that argument is parsed as a function call (without the surrounding parentheses). When any is T, all remaining command line arguments are loaded recursively. When any is NIL, standard input is read, a prompt is issued before each read operation, the results are printed to standard output (read-eval-print loop), and load terminates when an empty line is entered. In any case, load terminates upon end of file, or when NIL is read. The hash table for transient symbols is cleared before and after the load, so that all transient symbols in the file have a local scope. Returns the value of the last evaluated expression. See also call, in, out and str.


: (load "lib.l" "-* 1 2 3")
-> 6

(lock ['sym]) -> cnt | NIL
Write-locks an external symbol sym (file record locking), or the whole database root file if sym is NIL. Returns NIL if successful, or the ID of the process currently holding the lock. When sym is non-NIL, the lock is released at the next top level call to commit or rollback, otherwise only when another database is opened with pool, or when the process terminates. See also *Solo.


: (lock '{1})        # Lock single object
-> NIL
: (lock)             # Lock whole database
-> NIL

(-> sym [num]) -> any
Searches for the current value of the pattern variable sym at top level (or level num) in the current Pilog environment. See also prove and unify.


: (? (append (1 2 3) (4 5 6) @X) (@ println 'X '= (-> @X)))
X = (1 2 3 4 5 6)
 @X=(1 2 3 4 5 6)
-> NIL

(loop ['any | (NIL 'any . prg) | (T 'any . prg) ..]) -> any
Endless loop with multiple conditional exits: The body is executed an unlimited number of times. If a clause has NIL or T as its CAR, the clause's second element is evaluated as a condition and - if the result is NIL or non-NIL, respectively - the prg is executed and the result returned. See also do and for.


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

(low? 'any) -> sym | NIL
Returns any when the argument is a string (symbol) that starts with a lowercase character. See also lowc.


: (low? "a")
-> "a"
: (low? "A")
-> NIL
: (low? 123)
-> NIL
: (low? ".")
-> NIL

(lowc 'any) -> any
Lower case conversion: If any is not a symbol, it is returned as it is. Otherwise, a new transient symbol with all characters of any, converted to lower case, is returned. See also uppc, fold and low?.


: (lowc 123)
-> 123
: (lowc "ABC")
-> "abc"

(lt0 'any) -> num | NIL
Returns num when the argument is a number and less than zero, otherwise NIL. See also ge0, gt0, =0 and n0.


: (lt0 -2)
-> -2
: (lt0 3)
-> NIL

(lup 'lst 'any) -> lst
(lup 'lst 'any 'any2) -> lst
Looks up any in the CAR-elements of cells stored in the index tree lst, as built up by idx. In the first form, the first found cell is returned, in the second form a list of all cells whose CAR is in the range any .. any2. See also assoc.


: (idx 'A 'a T)
-> NIL
: (idx 'A (1 . b) T)
-> NIL
: (idx 'A 123 T)
-> NIL
: (idx 'A (1 . a) T)
-> NIL
: (idx 'A (1 . c) T)
-> NIL
: (idx 'A (2 . d) T)
-> NIL
: (idx 'A)
-> (123 a (1 . a) (1 . b) (1 . c) (2 . d))
: (lup A 1)
-> (1 . b)
: (lup A 2)
-> (2 . d)
: (lup A 1 1)
-> ((1 . a) (1 . b) (1 . c))
: (lup A 1 2)
-> ((1 . a) (1 . b) (1 . c) (2 . d))


M

(made ['lst1 ['lst2]]) -> lst
Initializes a new list value for the current make environment. All list elements already produced with chain and link are discarded, and lst1 is used instead. Optionally, lst2 can be specified as the new linkage cell, otherwise the last cell of lst1 is used. When called without arguments, made does not modify the environment. In any case, the current list is returned.


: (make
   (link 'a 'b 'c)         # Link three items
   (println (made))        # Print current list (a b c)
   (made (1 2 3))          # Discard it, start new with (1 2 3)
   (link 4) )              # Link 4
(a b c)
-> (1 2 3 4)

(make .. [(made 'lst ..)] .. [(link 'any ..)] ..) -> any
Initializes and executes a list-building process with the made, chain and link functions, and returns the result list. For efficiency, pointers to the head and the tail of the list are maintained internally.


: (make (link 1) (link 2 3) (link 4))
-> (1 2 3 4)
: (make (made (1 2 3)) (link 4))
-> (1 2 3 4)

(map 'fun 'lst ..) -> lst
Applies fun to lst and all successive CDR's. When additional lst arguments are given, they are passed to fun in the same way. Returns the result of the last application.


: (map println (1 2 3 4) '(A B C))
(1 2 3 4) (A B C)
(2 3 4) (B C)
(3 4) (C)
(4) NIL
-> NIL

(mapc 'fun 'lst ..) -> any
Applies fun to each element of lst. When additional lst arguments are given, their elements are also passed to fun. Returns the result of the last application.


: (mapc println (1 2 3 4) '(A B C))
1 A
2 B
3 C
4 NIL
-> NIL

(mapcan 'fun 'lst ..) -> lst
Applies fun to each element of lst. When additional lst arguments are given, their elements are also passed to fun. Returns a (destructively) concatenated list of all results.


: (mapcan reverse '((a b c) (d e f) (g h i)))
-> (c b a f e d i h g)

(mapcar 'fun 'lst ..) -> lst
Applies fun to each element of lst. When additional lst arguments are given, their elements are also passed to fun. Returns a list of all results.


: (mapcar + (1 2 3) (4 5 6))
-> (5 7 9)
: (mapcar '((X Y) (+ X (* Y Y))) (1 2 3 4) (5 6 7 8))
-> (26 38 52 68)

(mapcon 'fun 'lst ..) -> lst
Applies fun to lst and all successive CDR's. When additional lst arguments are given, they are passed to fun in the same way. Returns a (destructively) concatenated list of all results.


: (mapcon copy '(1 2 3 4 5))
-> (1 2 3 4 5 2 3 4 5 3 4 5 4 5 5)

(maplist 'fun 'lst ..) -> lst
Applies fun to lst and all successive CDR's. When additional lst arguments are given, they are passed to fun in the same way. Returns a list of all results.


: (maplist cons (1 2 3) '(A B C))
-> (((1 2 3) A B C) ((2 3) B C) ((3) C))

(maps 'fun 'sym ['lst ..]) -> any
Applies fun to all properties of sym. When additional lst arguments are given, their elements are also passed to fun. Returns the result of the last application. See also putl and getl.


: (put 'X 'a 1)
-> 1
: (put 'X 'b 2)
-> 2
: (put 'X 'flg T)
-> T
: (getl 'X)
-> (flg (2 . b) (1 . a))
: (maps println 'X '(A B))
flg A
(2 . b) B
(1 . a) NIL
-> NIL

(mark 'sym|0 [NIL | T | 0]) -> flg
Tests, sets or resets a mark for sym in the database (for a second argument of NIL, T or 0, respectively), and returns the old value. The marks are local to the current process (not stored in the database), and vanish when the process terminates. If the first argument is zero, all marks are cleared.


: (pool "db")
-> T
: (mark '{1} T)      # Mark
-> NIL
: (mark '{1})        # Test
-> T                 # -> marked
: (mark '{1} 0)      # Unmark
-> T
: (mark '{1})        # Test
-> NIL               # -> unmarked

(match 'lst1 'lst2) -> flg
Takes lst1 as a pattern to be matched against lst2, and returns T when successful. Atoms must be equal, and sublists must match recursively. Symbols in the pattern list with names starting with an at-mark "@" (see pat?) are taken as wildcards. They can match zero, one or more elements, and are bound to the corresponding data. See also chop, split and fill.


: (match '(@A is @B) '(This is a test))
-> T
: @A
-> (This)
: @B
-> (a test)
: (match '(@X (d @Y) @Z) '((a b c) (d (e f) g) h i))
-> T
: @X
-> ((a b c))
: @Y
-> ((e f) g)
: @Z
-> (h i)

(max 'any ..) -> any
Returns the largest of all any arguments. See also Comparing.


: (max 2 'a 'z 9)
-> z
: (max (5) (2 3) 'X)
-> (5)

(maxi 'fun 'lst ..) -> any
Applies fun to each element of lst. When additional lst arguments are given, their elements are also passed to fun. Returns that element from lst for that fun returned a maximal value. See also mini.


: (setq A 1  B 2  C 3)
-> 3
: (maxi val '(A B C))
-> C
: (maxi                          # Symbol with largest list value
   '((X)
      (and (pair (val X)) (size @)) )
   (what) )
-> *History

(member 'any 'lst) -> any
Returns the tail of lst that starts with any when any is a member of lst, otherwise NIL. See also memq, assoc and idx.


: (member 3 (1 2 3 4 5 6))
-> (3 4 5 6)
: (member 9 (1 2 3 4 5 6))
-> NIL
: (member '(d e f) '((a b c) (d e f) (g h i)))
-> ((d e f) (g h i))

(memq 'any 'lst) -> any
Returns the tail of lst that starts with any when any is a member of lst, otherwise NIL. == is used for comparison (pointer equality). See also member, mmeq, asoq and delq.


: (memq 'c '(a b c d e f))
-> (c d e f)
: (memq 3 (1 2 3 4 5 6))
-> NIL

(meta 'obj|typ 'sym ['sym2|cnt ..]) -> any
Fetches a property value any, by searching the property lists of the classes and superclasses of obj, or the classes in typ, for the property key sym, and by applying the get algorithm to the following optional arguments.


: (setq A '(B))            # Be 'A' an object of class 'B'
-> (B)
: (put 'B 'a 123)
-> 123
: (meta 'A 'a)             # Fetch 'a' from 'B'
-> 123

(meth 'obj ..) -> any
This function is usually not called directly, but is used by dm as a template to initialize the VAL of message symbols. It searches for itself in the methods of obj and its classes and superclasses, and executes that method. An error "Bad message" is issued if the search is unsuccessful.


: meth
-> 67283504    # Value of 'meth'
: stop>
-> 67283504    # Value of any message

(method 'msg 'obj) -> fun
Returns the function body of the method that would be executed upon sending the message msg to the object obj. If the message cannot be located in obj, its classes and superclasses, NIL is returned. See also send and try.


: (method 'mis> '+Number)
-> ((Val Obj) (and Val (not (num? Val)) "Numeric input expected"))

(min 'any ..) -> any
Returns the smallest of all any arguments. See also Comparing.


: (min 2 'a 'z 9)
-> 2
: (min (5) (2 3) 'X)
-> X

(mini 'fun 'lst ..) -> any
Applies fun to each element of lst. When additional lst arguments are given, their elements are also passed to fun. Returns that element from lst for that fun returned a minimal value. See also maxi.


: (setq A 1  B 2  C 3)
-> 3
: (mini val '(A B C))
-> A

(mix 'lst cnt|'any ..) -> lst
Builds a list from the elements of the argument lst, as specified by the following cnt|'any arguments. If such an argument is a number, the cnt'th element from lst is taken, otherwise that arguments is evaluated and the result is used.


: (mix '(a b c d) 3 4 1 2)
-> (c d a b)
: (mix '(a b c d) 1 'A 4 'D)
-> (a A d D)

(mmeq 'lst 'lst) -> any
Returns the tail of the second argument lst that starts with a member of the first argument lst, otherwise NIL. == is used for comparison (pointer equality). See also member, memq, asoq and delq.


: (mmeq '(a b c) '(d e f))
-> NIL
: (mmeq '(a b c) '(d b x))
-> (b x)


N

(n== 'any ..) -> flg
Returns T when not all any arguments are the same (pointer equality). (n== 'any ..) is equivalent to (not (== 'any ..)). See also ==.


: (n== 'a 'a)
-> NIL
: (n== 1 1)
-> T

(n0 'any) -> flg
Returns T when any is not a number with value zero. See also =0, lt0, ge0 and gt0.


: (n0 (- 6 3 2 1))
-> NIL
: (n0 'a)
-> T

(nT 'any) -> flg
Returns T when any is not the symbol T. See also =T.


: (nT 0)
-> T
: (nT "T")
-> T
: (nT T)
-> NIL

(nagle 'cnt 'flg) -> cnt
Disables the "nagle" algorithm for the socket descriptor cnt if flg is NIL, or enables it if flg is non-NIL. Returns the socket descriptor. See also listen and connect.


: (nagle (connect "localhost" 8080) NIL)  # Disable the nagle algorithm
-> 3

(name 'sym ['sym2]) -> sym
Returns, if sym2 is not given, a new transient symbol with the name of sym. Otherwise sym must be a transient symbol, and its name is changed to that of sym2. See also str, sym, zap and intern.


: (name 'abc)
-> "abc"
: (name "abc")
-> "abc"
: (name '{abc})
-> "abc"
: (name (new))
-> NIL
: (de foo (Lst) (car Lst))          # 'foo' calls 'car'
-> foo
: (intern (name (zap 'car) "xxx"))  # Globally change the name of 'car'
-> xxx
: (xxx (1 2 3))
-> 1
: (pp 'foo)
(de foo (Lst)
   (xxx Lst) )                      # Name changed
-> foo
: (foo (1 2 3))                     # 'foo' still works
-> 1
: (car (1 2 3))                     # Reader returns a new 'car' symbol
!? (car (1 2 3))
car -- Undefined
?

(nand 'any ..) -> flg
Logical NAND. The expressions any are evaluated from left to right. If NIL is encountered, T is returned immediately. Else NIL is returned. (nand ..) is equivalent to (not (and ..)).


: (nand (lt0 7) (read))
-> T
: (nand (lt0 -7) (read))
abc
-> NIL
: (nand (lt0 -7) (read))
NIL
-> T

(need 'cnt ['lst ['any]]) -> lst
Produces a list of at least cnt elements. When called without optional arguments, a list of cnt NIL's is returned. When lst is given, it is extended to the left (if cnt is positive) or (destructively) to the right (if cnt is negative) with any elements.


: (need 5)
-> (NIL NIL NIL NIL NIL)            # Allocate 5 cells
: (need 5 '(a b c))
-> (NIL NIL a b c)
: (need -5 '(a b c))
-> (a b c NIL NIL)
: (need 5 '(a b c) " ")             # String alignment
-> (" " " " a b c)

(new ['flg|num] ['typ ['any ..]]) -> sym
Creates and returns a new object. If flg is given and non-NIL, the new object will be an external symbol (created in the corresponding database file if num is given). typ (typically a list of classes) is assigned to the VAL, and the initial T message is sent with the arguments any to the new object. See also box.


: (new)
-> $134426427
: (new T '(+Address))
-> {1A;3}

(next) -> any
Can only be used inside functions with a variable number of arguments (with @). Returns the next argument from the internal list. See also args, arg, rest, and pass.


: (de foo @ (println (next)))          # Print next argument
-> foo
: (foo)
NIL
-> NIL
: (foo 123)
123
-> 123

(nil . prg) -> NIL
Executes prg, and returns NIL. See also t, prog, prog1 and prog2.


: (nil (println 'Ok))
Ok
-> NIL

(nond (('any1 . prg1) ('any2 . prg2) ..)) -> any
Negated ("non-cond") multi-way conditional: If any of the anyN conditions evaluates to NIL, prgN is executed and the result returned. Otherwise (all conditions evaluate to non-NIL), NIL is returned. See also cond, ifn and unless.


: (nond
   ((= 3 3) (println 1))
   ((= 3 4) (println 2))
   (NIL (println 3)) )
2
-> 2

(nor 'any ..) -> flg
Logical NOR. The expressions any are evaluated from left to right. If a non-NIL value is encountered, NIL is returned immediately. Else T is returned. (nor ..) is equivalent to (not (or ..)).


: (nor (lt0 7) (= 3 4))
-> T

(not 'any) -> flg
Logical negation. Returns T if any evaluates to NIL.


: (not (== 'a 'a))
-> NIL
: (not (get 'a 'a))
-> T

(nth 'lst 'cnt ..) -> lst
Returns the tail of lst starting from the cnt'th element of lst. Successive cnt arguments operate on the results in the same way. (nth 'lst 2) is equivalent to (cdr 'lst).


: (nth '(a b c d) 2)
-> (b c d)
: (nth '(a (b c) d) 2 2)
-> (c)
: (cdadr '(a (b c) d))
-> (c)

(num? 'any) -> num | NIL
Returns any when the argument any is a number, otherwise NIL.


: (num? 123)
-> 123
: (num? (1 2 3))
-> NIL


O

(off sym ..) -> NIL
Stores NIL in the VAL's of all argument symbols sym. See also on, onOff, zero and one.


: (off A B)
-> NIL
: A
-> NIL
: B
-> NIL

(offset 'lst1 'lst2) -> cnt | NIL
Returns the cnt position of the tail list lst1 in lst2, or NIL if it is not found. See also index.


: (offset '(c d e f) '(a b c d e f))
-> 3
: (offset '(c d e) '(a b c d e f))
-> NIL

(on sym ..) -> T
Stores T in the VAL's of all argument symbols sym. See also off, onOff, zero and one.


: (on A B)
-> T
: A
-> T
: B
-> T

(one sym ..) -> 1
Stores 1 in the VAL's of all argument symbols sym. See also zero, on, off and onOff.


: (one A B)
-> 1
: A
-> 1
: B
-> 1

(onOff sym ..) -> flg
Logical negates the VAL's of all argument symbols sym. Returns the new value of the last symbol. See also on, off, zero and one.


: (onOff A B)
-> T
: A
-> T
: B
-> T
: (onOff A B)
-> NIL
: A
-> NIL
: B
-> NIL

(open 'sym) -> cnt | NIL
Opens the file sym in read/write mode, and returns a file descriptor cnt (or NIL on error). If the file does not exist, it is created. The file descriptor can be used in subsequent calls to in and out. See also close.


: (open "x")
-> 3

(opt) -> sym
Return the next command line argument (option) as a string, and remove it from the remaining command line arguments. See also Invocation and argv.


$ ./p  -"de f () (println 'opt (opt))"  -f abc  -bye
opt "abc"

(or 'any ..) -> any
Logical OR. The expressions any are evaluated from left to right. If a non-NIL value is encountered, it is returned immediately. Else the result of the last expression is returned.


: (or (= 3 3) (read))
-> T
: (or (= 3 4) (read))
abc
-> abc

(out 'any . prg) -> any
Opens any as output channel during the execution of prg. The current output channel will be saved and restored appropriately. If the argument is NIL, standard output is used. If the argument is a symbol, it is used as a file name (opened in "append" mode if the first character is "+"). If it is a number, it is used as the descriptor of an open file. Otherwise (if it is a list), it is taken as a command with arguments, and a pipe is opened for output. See also call, in, pipe, ctl and load.


: (out "a" (println 123 '(a b c) 'def))      # Write one line to file "a"
-> def


P

(pack 'any ..) -> sym
Returns a transient symbol whose name is concatenated from all arguments any. A NIL arguments contributes nothing to the result string, a number is converted to a digit string, a symbol supplies the characters of its name, and for a list its elements are taken. See also text and glue.


: (pack 'car " is " 1 '(" symbol " name))
-> "car is 1 symbol name"

(pair 'any) -> any
Returns any when the argument a cons pair cell. See also atom.


: (pair NIL)
-> NIL
: (pair (1 . 2))
-> (1 . 2)
: (pair (1 2 3))
-> (1 2 3)

(pass 'fun ['any ..]) -> any
Passes to fun all arguments any, and all remaining variable arguments (@) as they would be returned by rest. (pass 'fun 'any) is equivalent to (apply 'fun (cons 'any (rest))). See also apply.


: (de bar (A B . @)
   (println 'bar A B (rest)) )
-> bar
: (de foo (A B . @)
   (println 'foo A B)
   (pass bar 1)
   (pass bar 2) )
-> foo
: (foo 'a 'b 'c 'd 'e 'f)
foo a b
bar 1 c (d e f)
bar 2 c (d e f)
-> (d e f)

(path 'sym) -> sym
Substitutes any leading "@" character in the sym argument with the Pico Lisp Home Directory, as it was remembered during interpreter startup. Optionally, the name may be preceded by a "+" character (as used by out). This mechanism is used internally by all I/O functions. See also Invocation.


$ /usr/bin/picolisp /usr/lib/picolisp/lib.l
: (path "a/b/c")
-> "a/b/c"
: (path "@a/b/c")
-> "/usr/lib/picolisp/a/b/c"
: (path "+@a/b/c")
-> "+/usr/lib/picolisp/a/b/c"

(pat? 'any) -> sym | NIL
Returns any when the argument any is a symbol whose name starts with an at-mark "@", otherwise NIL.


: (pat? '@)
-> @
: (pat? "@Abc")
-> "@Abc"
: (pat? "ABC")
-> NIL
: (pat? 123)
-> NIL

(peek) -> sym
Single character look-ahead: Returns the same character as the next call to char would return. See also skip.


$ cat a
# Comment
abcd
$ ./p dbg.l
: (in "a" (list (peek) (char)))
-> ("#" "#")

(pick 'fun 'lst ..) -> any
Applies fun to successive elements of lst until non-NIL is returned. Returns that value, or NIL if fun did not return non-NIL for any element of lst. When additional lst arguments are given, their elements are also passed to fun. See also seek, find.


: (put 'D 'str "Hello")
-> "Hello"
: (pick '((X) (get X 'str)) '(A B C D E F))
-> "Hello"

(pipe exe) -> cnt
(pipe exe . prg) -> any
Executes exe in a fork'ed child process (which terminates thereafter). In the first form, pipe just returns a file descriptor to read from the standard output of that process. In the second form, it opens the standard output of that process as input channel during the execution of prg. The current input channel will be saved and restored appropriately. See also in and out.


: (pipe                                # equivalent to 'any'
   (prinl "(a b # Comment^Jc d)")         # (child process)
   (read) )                               # (parent process)
-> (a b c d)
: (pipe                                # pipe through an external program
   (out '(tr "[a-z]" "[A-Z]")             # (child process)
      (prinl "abc def ghi") )
   (line T) )                             # (parent process)
-> "ABC DEF GHI"

(poll 'cnt) -> flg
Checks for the availability of data for reading on the file descriptor cnt. See also open, in and close.


: (and (poll *Fd) (in *Fd (read)))  # Prevent blocking

(pool ['sym1 ['lst] ['sym2]]) -> flg
Opens the file sym1 as a database file in read/write mode. If the file does not exist, it is created. A currently open database is closed. lst is a list of block size scale factors (i.e. numbers), defaulting to (2) (for a single file with a 256 byte block size). If lst is given, an individual database file is opened for each item. If sym2 is non-NIL, it is opened in append-mode as a journal file. Returns T when successful. See also journal.


: (pool "/dev/hda2")
-> T

(pop 'var) -> any
Pops the first element (CAR) from the stack in var. See also push, queue, cut, del and fifo.


: (setq S '((a b c) (1 2 3)))
-> ((a b c) (1 2 3))
: (pop S)
-> a
: (pop (cdr S))
-> 1
: (pop 'S)
-> (b c)
: S
-> ((2 3))

(port ['T] 'cnt|(cnt . cnt) ['var]) -> cnt
Opens a TCP-Port cnt (or a UDP-Port if the first argument is T), and returns a socket descriptor suitable as an argument for listen or accept (or udp, respectively). If cnt is zero, some free port number is allocated. If a pair of cnts is given instead, it should be a range of numbers which are tried in turn. When var is given, it is bound to the port number.


: (port 0 'A)                       # Allocate free port
-> 4
: A
-> 1034                             # Got 1034
: (port (4000 . 4008) 'A)           # Try one of these ports
-> 5
: A
-> 4002

(pr 'any ..) -> any
Binary print: Prints all any arguments to the current output channel in encoded binary format. See also rd, wr and rpc.


: (out "x" (pr 7 "abc" (1 2 3) 'a))          # Print to "x"
-> a
: (hd "x")
00000000  04 0E 0E 61 62 63 01 04 02 04 04 04 06 03 05 61  ...abc.........a
-> NIL

(pre? 'sym1 'sym2) -> flg
Returns non-NIL when the name of the first symbol sym1 is a prefix string of the name of the second symbol sym2. See also sub?.


: (pre? "abc" "abcdef")
-> T
: (pre? "def" "abcdef")
-> NIL
: (pre? "" "abcdef")
-> T

(prin 'any ..) -> any
Prints the string representation of all any arguments to the current output channel. No space or newline is printed between individual items, of after the last item. For lists, all elements are prin'ted recursively. See also prinl.


: (prin 'abc 123 '(a 1 b 2))
abc123a1b2-> (a 1 b 2)

(prinl 'any ..) -> any
Prints the string representation of all any arguments to the current output channel, followed by a newline. No space or newline is printed between individual items. For lists, all elements are prin'ted recursively. See also prin.


: (prinl 'abc 123 '(a 1 b 2))
abc123a1b2
-> (a 1 b 2)

(print 'any ..) -> any
Prints all any arguments to the current output channel. If there is more than one argument, a space is printed between successive arguments. No space or newline is printed after the last item. See also println, printsp, sym and str


: (print 123)
123-> 123
: (print 1 2 3)
1 2 3-> 3
: (print '(a b c) 'def)
(a b c) def-> def

(println 'any ..) -> any
Prints all any arguments to the current output channel, followed by a newline. If there is more than one argument, a space is printed between successive arguments. See also print, printsp.


: (println '(a b c) 'def)
(a b c) def
-> def

(printsp 'any ..) -> any
Prints all any arguments to the current output channel, followed by a space. If there is more than one argument, a space is printed between successive arguments. See also print, println.


: (printsp '(a b c) 'def)
(a b c) def -> def

(prog . prg) -> any
Executes prg, and returns the result of the last expression. See also nil, t, prog1 and prog2.


: (prog (print 1) (print 2) (print 3))
123-> 3

(prog1 'any1 . prg) -> any1
Executes all arguments, and returns the result of the first expression any1. See also nil, t, prog and prog2.


: (prog1 (print 1) (print 2) (print 3))
123-> 1

(prog2 'any1 'any2 . prg) -> any2
Executes all arguments, and returns the result of the second expression any2. See also nil, t, prog and prog1.


: (prog2 (print 1) (print 2) (print 3))
123-> 2

(prop 'sym1|lst ['sym2|cnt ..] 'sym) -> lst|sym
Fetches a property for a property key sym from a symbol. That symbol is sym1 (if no other arguments are given), or a symbol found by applying the get algorithm to sym1|lst and the following arguments. The property (the cell, not just its value) is returned, suitable for direct (destructive) manipulations.


: (put 'X 'cnt 0)
-> 0
: (prop 'X 'cnt)
-> (0 . cnt)
: (inc (prop 'X 'cnt))        # Directly manipulate the property value
-> 1
: (get 'X 'cnt)
-> 1

(protect . prg) -> any
Executes prg, and returns the result of the last expression. If a SIGTERM signal is received during that time, termination of the process will be delayed until the execution of prg is completed. See also kill.


: (protect (journal "db1.log" "db2.log"))
-> T

(prove 'lst ['lst]) -> lst
The Pilog interpreter. Tries to prove the query list in the first argument, and returns an association list of symbol-value pairs, or NIL if not successful. The query list is modified as a side effect, allowing subsequent calls to prove for further results. The optional second argument may contain a list of symbols; in that case the successful matches of rules defined for these symbols will be traced. See also goal, -> and unify.


: (prove (goal '((equal 3 3))))
-> T
: (prove (goal '((equal 3 @X))))
-> ((@X . 3))
: (prove (goal '((equal 3 4))))
-> NIL

(push 'var 'any ..) -> any
Implements a stack using a list in var. The any arguments are cons'ed in front of the value list. See also push1, pop, queue and fifo.


: (push 'S 3)              # Use the VAL of 'S' as a stack
-> 3
: S
-> (3)
: (push 'S 2)
-> 2
: (push 'S 1)
-> 1
: S
-> (1 2 3)
: (push S 999)             # Now use the CAR of the list in 'S'
-> 999
: (push S 888 777)
-> 777
: S
-> ((777 888 999 . 1) 2 3)

(push1 'var 'any ..) -> any
Maintains a unique list in var. Each any argument is cons'ed in front of the value list only if it is not already a member of that list. See also push, pop and queue.


: (push1 'S 1 2 3)
-> 3
: S
-> (3 2 1)
: (push1 'S 2 4)
-> 4
: S
-> (4 3 2 1)

(put 'sym1|lst ['sym2|cnt ..] 'sym 'any) -> any
Stores a new value any for a property key sym in a symbol. That symbol is sym1 (if no other arguments are given), or a symbol found by applying the get algorithm to sym1|lst and the following arguments.


: (put 'X 'a 1)
-> 1
: (get 'X 'a)
-> 1
: (prop 'X 'a)
-> (1 . a)

(putl 'sym1|lst1 ['sym2|cnt ..] 'lst) -> lst
Stores a complete new property list lst in a symbol. That symbol is sym1 (if no other arguments are given), or a symbol found by applying the get algorithm to sym1|lst1 and the following arguments. All previously defined properties for that symbol are lost. See also getl and maps.


: (putl 'X '((123 . a) flg ("Hello" . b)))
-> ((123 . a) flg ("Hello" . b))
: (get 'X 'a)
-> 123
: (get 'X 'b)
-> "Hello"
: (get 'X 'flg)
-> T

(pwd) -> sym
Returns the path to the current working directory. See also dir and cd.


: (pwd)
-> "/home/app/"


Q

(quote . any) -> any
Returns any unevaluated. The reader recognizes the single quote char ' as a macro for this function. See also lit.


: 'a
-> a
: '(foo a b c)
-> (foo a b c)
: (quote (quote (quote a)))
-> ('('(a)))

(queue 'var 'any) -> any
Implements a queue using a list in var. The any argument is (destructively) concatenated to the end of the value list. See also push, pop and fifo.


: (queue 'A 1)
-> 1
: (queue 'A 2)
-> 2
: (queue 'A 3)
-> 3
: A
-> (1 2 3)
: (pop 'A)
-> 1
: A
-> (2 3)

(quit ['any ['any]])
Stops current execution. If no arguments are given, all pending finally expressions are executed and control is returned to the top level read-eval-print loop. Otherwise, an error handler is entered. The first argument can be some error message, and the second might be the reason for the error. See also Error Handling.


: (de foo (X) (quit "Sorry, my error" X))
-> foo
: (foo 123)                                  # 'X' is bound to '123'
123 -- Sorry, my error                       # Error entered
? X                                          # Inspect 'X'
-> 123
?                                            # Empty line: Exit
:


R

(rand ['cnt1 'cnt2] | ['T]) -> cnt | flg
Returns a pseudo random number in the range cnt1 .. cnt2 (or -2147483648 .. +2147483647 if no arguments are given). If the argument is T, a boolean value flg is returned. See also seed.


: (rand 3 9)
-> 3
: (rand 3 9)
-> 7

(rank 'any 'lst ['flg]) -> lst
Searches a ranking list. lst should be sorted. Returns the element from lst with a maximal CAR less or equal to any (if flg is NIL), or with a minimal CAR greater or equal to any (if flg is non-NIL), or NIL if no match is found. See also Comparing.


: (rank 0 '((1 . a) (100 . b) (1000 . c)))
-> NIL
: (rank 50 '((1 . a) (100 . b) (1000 . c)))
-> (1 . a)
: (rank 100 '((1 . a) (100 . b) (1000 . c)))
-> (100 . b)
: (rank 300 '((1 . a) (100 . b) (1000 . c)))
-> (100 . b)
: (rank 9999 '((1 . a) (100 . b) (1000 . c)))
-> (1000 . c)
: (rank 50 '((1000 . a) (100 . b) (1 . c)) T)
-> (100 . b)

(raw ['flg]) -> flg
Console mode control function. When called without arguments, it returns the current console mode (NIL for "cooked mode"). Otherwise, the console is set to the new state. See also key.


$ ./p
: (raw)
-> NIL
$ ./p dbg.l
: (raw)
-> T

(rd ['sym]) -> any
(rd 'cnt) -> num | NIL
Binary read: Reads one item from the current input channel in encoded binary format. When called with a cnt argument (second form), that number of raw bytes (in big endian format if cnt is positive) is read as a single number. Upon end of file, if the sym argument is given, it is returned, otherwise NIL. See also pr and wr.


: (out "x" (pr 'abc "EOF" 123 "def"))
-> "def"
: (in "x" (rd))
-> abc
: (in "x"
   (make
      (use X
         (until (== "EOF" (setq X (rd "EOF")))  # '==' detects end of file
            (link X) ) ) ) )
-> (abc "EOF" 123 "def")  # as opposed to reading a symbol "EOF"

: (in "/dev/urandom" (rd 20))
-> 396737673456823753584720194864200246115286686486

(read ['sym1 ['sym2]]) -> any
Reads one item from the current input channel. NIL is returned upon end of file. When called without arguments, an arbitrary Lisp expression is read. Otherwise, a token (a number, or an internal or transient symbol) is read. In that case, sym1 specifies which set of characters to accept for internal symbols (in addition to the standard alphanumerical characters), and sym2 an optional comment character. See also any, str, skip and eof.


: (list (read) (read) (read))    # Read three things from console
123                              # a number
abcd                             # a symbol
(def                             # and a list
ghi
jkl
)
-> (123 abcd (def ghi jkl))
: (make (while (read "_" "#") (link @)))
abc = def_ghi("xyz"+-123) # Comment
""
-> (abc "=" def_ghi "(" "xyz" "+" -123 ")")

(rel sym lst [any ..]) -> any
Defines a relation sym for the current class *Class, using lst as the list of classes for that relation, and possibly additional arguments any for its initialization.


(class +Person +Entity)
(rel nm     (+List +Ref +String))               # Names
(rel tel    (+Ref +String))                     # Telephone
(rel adr    (+Joint) prs (+Address))            # Address

(class +Address +Entity)
(rel Cit    (+Need +Hook +Link) (+City))        # City
(rel str    (+List +Ref +String) Cit)           # Street
(rel prs    (+List +Joint) adr (+Person))       # Inhabitants

(class +City +Entity)
(rel nm     (+List +Ref +String))               # Zip / Names

(replace 'lst 'any1 'any2 ..) -> lst
Replaces in lst all occurrences of any1 with any2. For optional additional argument pairs, this process is repeated.


: (replace '(a b b a) 'a 'A)
-> (A b b A)
: (replace '(a b b a) 'b 'B)
-> (a B B a)
: (replace '(a b b a) 'a 'B 'b 'A)
-> (B A A B)

(rest) -> lst
Can only be used inside functions with a variable number of arguments (with @). Returns the the list of all remaining arguments from the internal list. See also args, next, arg and pass.


: (de foo @ (println (rest)))
-> foo
: (foo 1 2 3)
(1 2 3)
-> (1 2 3)

(reverse 'lst) -> lst
Returns a reversed copy of lst. See also flip.


: (reverse (1 2 3 4))
-> (4 3 2 1)

(rewind) -> flg
Sets the file position indicator for the current output stream to the beginning of the file, and truncates the file length to zero. Returns T when successful. See also flush.


(rollback) -> flg
Cancels a transaction, by discarding all modifications of external symbols. For nested transactions, only the changes since the last call to begin are discarded. Returns T when the topmost transaction is cancelled. See also commit.


: (pool "db")
-> T
: (begin)
-> T
: (rollback)            # Rollback second level
-> NIL
: (rollback)            # Rollback top level
-> T

(rot 'lst ['cnt]) -> lst
Rotate: The contents of the cells of lst are (destructively) shifted right, and the value from the last cell is stored in the first cell. Without the optional cnt argument, the whole list is rotated. Otherwise only the first cnt elements are rotated.


: (rot (1 2 3 4))             # Rotate all four elements
-> (4 1 2 3)
: (rot (1 2 3 4 5 6) 3)       # Rotate only the first three elements
-> (3 1 2 4 5 6)

(rpc 'sym ['any ..]) -> flg
Rapid (or remote) procedure call: Send an executable list (sym any ..) via standard output in encoded binary format. See also pr, pipe, tell and hear.


: (hear (pipe (do 3 (wait 2000) (rpc 'println ''Ok))))
-> 3
: Ok  # every two seconds
Ok
Ok

(run 'any ['cnt]) -> any
If any is an atom, run behaves like eval. Otherwise any is a list, which is evaluated in sequence. The last result is returned. If a binding environment offset cnt is given, that evaluation takes place in the corresponding environment. See also eval and up.


: (run '((println (+ 1 2 3)) (println 'Ok)))
6
Ok
-> Ok


S

(sect 'lst 'lst) -> lst
Returns the intersection of the lst arguments. See also diff.


: (sect (1 2 3 4) (3 4 5 6))
-> (3 4)
: (sect (1 2 3) (4 5 6))
-> NIL

(seed 'any) -> cnt
Initializes the random generator's seed, and returns a pseudo random number in the range -2147483648 .. +2147483647. See also rand.


: (seed "init string")
-> 2015582081
: (rand)
-> -706917003
: (rand)
-> 1224196082
: (seed "init string")
-> 2015582081
: (rand)
-> -706917003
: (rand)
-> 1224196082

(seek 'fun 'lst ..) -> lst
Applies fun to lst and all successive CDR's, until non-NIL is returned. Returns the tail of lst starting with that element, or NIL if fun did not return non-NIL for any element of lst. When additional lst arguments are given, they are passed to fun in the same way. See also find, pick.


: (seek '((X) (> (car X) 9)) (1 5 8 12 19 22))
-> (12 19 22)

(send 'msg 'obj ['any ..]) -> any
Sends the message msg to the object obj, optionally with arguments any. If the message cannot be located in obj, its classes and superclasses, an error "Bad message" is issued. See also try and method.


: (send 'stop> Dlg)  # Equivalent to (stop> Dlg)
-> NIL

(seq 'cnt|sym1 ['sym2 ['num]]) -> sym | num | NIL
Sequential single step: Returns the first external symbol in the cnt'th database file, or the next external symbol following sym1 in the database, or NIL when the end of the database is reached. When sym2 is given, the database is extended up to (including the creation of) sym2. If num is given, it should be the return value of a previous call to seq, and is used as an internal free list link. See also free.


: (pool "db")
-> T
: (seq *DB)
-> {2}
: (seq @)
-> {3}

(set 'var 'any ..) -> any
Stores new values any in the var arguments.


: (set 'L '(a b c)  (cdr L) '999)
-> 999
: L
-> (a 999 c)

(setq var 'any ..) -> any
Stores new values any in the var arguments.


: (setq  A 123  B (list A A))  # Set 'A' to 123, then 'B' to (123 123)
-> (123 123)

(size 'any) -> cnt
Returns the "size" of any. For numbers this is the number of bytes needed for the value, for external symbols it is the number of bytes it would occupy in the database, for other symbols it is the number of bytes occupied in the UTF-8 representation of the name, and for lists it is the total number of cells in this list and all its sublists. See also length.


: (size "abc")
-> 3
: (size "äbc")
-> 4
: (size 123)
-> 1
: (size (1 (2) 3))
-> 4

(skip ['sym]) -> sym
Skips all white space (and comments if sym is given) in the input stream. Returns the next available character, or NIL upon end of file. See also peek and eof.


$ cat a
# Comment
abcd
$ ./p dbg.l
: (in "a" (skip "#"))
-> "a"

(sort 'lst) -> lst
Sorts lst by destructively exchanging its elements. See also Comparing.


: (sort '(a 3 1 (1 2 3) d b 4 T NIL (a b c) (x y z) c 2))
-> (NIL 1 2 3 4 a b c d (1 2 3) (a b c) (x y z) T)

(space ['cnt]) -> cnt
Prints cnt spaces, or a single space when cnt is not given.


: (space)
 -> T
: (space 1)
 -> T
: (space 2)
  -> T

(sp? 'any) -> flg
Returns T when the argument any is NIL, or if it is a string (symbol) that consists only of whitespace characters.


: (sp? "  ")
-> T
: (sp? "ABC")
-> NIL
: (sp? 123)
-> NIL

(split 'lst 'any ..) -> lst
Splits lst at all places containing an element any and returns the resulting list of sublists.


: (split (1 a 2 b 3 c 4 d 5 e 6) 'e 3 'a)
-> ((1) (2 b) (c 4 d 5) (6))
: (mapcar pack (split (chop "The quick brown fox") " "))
-> ("The" "quick" "brown" "fox")

(sqrt 'num) -> num
Returns the square root of the num argument.


: (sqrt 64)
-> 8
: (sqrt 1000)
-> 31
: (sqrt 10000000000000000000000000000000000000000)
-> 100000000000000000000

(state 'var ((sym|lst sym [. prg]) . prg) ..) -> any
Implements a finite state machine. The variable var holds the current state as a symbolic value. When a clause is found that contains the current state in its CAAR sym|lst value, and either has no prg condition in its CDDAR, or that condition returns non-NIL, the current state will be set to the CADAR sym of the clause, the body prg in its CDR will be executed, and the result returned. T is a catch-all for any state. If no state-condition matches, NIL is returned. See also case and job.


: (de tst ()
   (job '((Cnt . 4))
      (state '(start)
         ((start run) (printsp 'start))
         ((run run (gt0 (dec 'Cnt)))
            (printsp 'run) )
         ((run stop) (printsp 'run))
         ((stop start) (setq Cnt 4) (println 'stop)) ) ) )
-> tst
: (do 12 (tst))
start run run run run stop
start run run run run stop
-> stop
: (pp 'tst)
(de tst NIL
   (job '((Cnt . 4))
      (state '(start)
      ...
-> tst
: (do 3 (tst))
start run run -> run
: (pp 'tst)
(de tst NIL
   (job '((Cnt . 2))
      (state '(run)
      ...
-> tst

(stem 'lst 'any ..) -> lst
Returns the tail of lst that does not contain any of the any arguments. (stem 'lst 'any ..) is equivalent to (last (split 'lst 'any ..)). See also tail and split.


: (stem (chop "abc/def\\ghi") "/" "\\")
-> ("g" "h" "i")

(stk any ..) -> T
Displays a dump of the internal runtime stack. All (unevaluated) any arguments are printed as a header, then each stack entry is printed per line, preceded by its (hexadecimal) address. See also env.


: (cons 'A (stk Test))
(Test)
BFFFF69C A
BFFFF70C (cons 'A (stk Test))

-> (A . T)

(stamp ['dat 'tim]) -> sym
Returns a date-time string in the form "YYYY-MM-DD HH:MM:SS". If dat and/or tim is missing, the current date or time is used. See also date and time.


: (stamp)
-> "2000-09-12 07:48:04"
: (stamp (date) 0)
-> "2000-09-12 00:00:00"
: (stamp (date 2000 1 1) (time 12 0 0))
-> "2000-01-01 12:00:00"

(stat) -> num
Prints memory usage statistics. The total size of the heap (in million cells), followed by the percentage of used cells. Returns the number of currently used cells. See also heap.


: (stat)
1 7%
-> 66892

(str 'sym) -> lst
(str 'lst) -> sym
In the first form, the string sym is parsed into a list. This mechanism is also used by load. The second form does the reverse operation by building a string from a list. See also any, name and sym.


: (str "a (1 2) b")
-> (a (1 2) b)
: (str '(a "Hello" DEF))
-> "a \"Hello\" DEF"

(strip 'any) -> any
Strips all leading quote symbols from any.


: (strip 123)
-> 123
: (strip '''(a))
-> (a)
: (strip (quote quote a b c))
-> (a b c)

(str? 'any) -> sym | NIL
Returns the argument any when it is a transient symbol (string), otherwise NIL. See also sym?, box? and ext?.


: (str? 123)
-> NIL
: (str? '{ABC})
-> NIL
: (str? 'abc)
-> NIL
: (str? "abc")
-> "abc"

(sub? 'sym1 'sym2) -> flg
Returns non-NIL when the name of the first symbol sym1 is a substring of the name of the second symbol sym2. See also pre?.


: (sub? "def" "abcdef")
-> T
: (sub? "abb" "abcdef")
-> NIL
: (sub? "" "abcdef")
-> T

(sum 'fun 'lst ..) -> num
Applies fun to each element of lst. When additional lst arguments are given, their elements are also passed to fun. Returns the sum of all numeric values returned from fun.


: (setq A 1  B 2  C 3)
-> 3
: (sum val '(A B C))
-> 6
: (sum                           # Total size of symbol list values
   '((X)
      (and (pair (val X)) (size @)) )
   (what) )
-> 32021

(super ['any ..]) -> any
Can only be used inside methods. Sends the current message to the current object This, this time starting the search for a method at the superclass(es) of the class where the current method was found.


(dm stop> ()         # 'stop>' method of current class
   (super)           # Call the 'stop>' method of the superclass
   ... )             # other things

(sym 'any) -> sym
Generate the printed representation of any into the name of a new symbol sym. See also any, name and str.


: (sym '(abc "Hello" 123))
-> "(abc \"Hello\" 123)"

(sym? 'any) -> flg
Returns T when the argument any is a symbol. See also str?, box? and ext?.


: (sym? 'a)
-> T
: (sym? NIL)
-> T
: (sym? 123)
-> NIL
: (sym? '(a b))
-> NIL

(sync) -> flg
Waits for pending data from all family processes. While other processes are still sending data (via the tell mechanism), a select system call is executed for all file descriptors and timers in the VAL of the global variable *Run. See also key and wait.


: (or (lock) (sync))       # Ensure database consistency
-> T                       # (numeric process-id if lock failed)

(sys 'any ['any]) -> sym
Returns or sets a system environment variable.


: (sys "TERM")                # Get current value
-> "xterm"
: (sys "TERM" "vt100")        # Set new value
-> "vt100"
: (sys "TERM")
-> "vt100"


T

T
A global constant, evaluating to itself. T is commonly returned as the boolean value "true" (though any non-NIL values could be used). As a property key, it is used to store Pilog clauses, and inside Pilog clauses it is the cut operator. See also NIL.


: T
-> T
: (= 123 123)
-> T
: (get 'not T)
-> ((@P (1 -> @P) T (fail)) (@P))

This
Holds the current object during method execution (see OO Concepts), or inside the body of a with statement. As it is a normal symbol, however, it can be used in normal bindings anywhere.


: (with 'X (println 'This 'is This))
This is X
-> X
: (put 'X 'a 1)
-> 1
: (put 'X 'b 2)
-> 2
: (put 'Y 'a 111)
-> 111
: (put 'Y 'b 222)
-> 222
: (mapcar '((This) (cons (: a) (: b))) '(X Y))
-> ((1 . 2) (111 . 222))

(t . prg) -> T
Executes prg, and returns T. See also nil, prog, prog1 and prog2.


: (t (println 'Ok))
Ok
-> T

(tail 'cnt|lst 'lst) -> lst
Returns the last cnt elements of lst. If cnt is negative, it is added to the length of lst. If the first argument is a lst, tail is a predicate function returning that argument list if it is equal to the tail of the second argument, and NIL otherwise. See also head. (tail -2 Lst) is equivalent to (nth Lst 3).


: (tail 3 '(a b c d e f))
-> (d e f)
: (tail -2 '(a b c d e f))
-> (c d e f)
: (tail 0 '(a b c d e f))
-> NIL
: (tail 10 '(a b c d e f))
-> (a b c d e f)
: (tail '(d e f) '(a b c d e f))
-> (d e f)

(tell 'sym ['any ..]) -> any
Family IPC: Send an executable list (sym any ..) to all family members (i.e. all children of the current process, and all other children of the parent process, see fork) for automatic execution. tell can also be used by commit to notify about database changes. See also rpc and hear.


: (call 'ps "x")                            # Show processes
  PID TTY      STAT   TIME COMMAND
  ..
 1321 pts/0    S      0:00 bin/picolisp ..  # Parent process
 1324 pts/0    S      0:01 bin/picolisp ..  # First child
 1325 pts/0    S      0:01 bin/picolisp ..  # Second child
 1326 pts/0    R      0:00 ps x
-> T
: *Pid                                      # We are the second child
-> 1325
: (tell 'println '*Pid)                     # Ask all others to print their Pid's
1324
-> *Pid

(text 'sym 'any ..) -> sym
Builds a new transient symbol (string) from sym, by replacing all occurrences of an at-mark "@", followed by one of the letters "1" through "9", and "A" through "Z", with the corresponding any argument. In this context "@A" refers to the 10th argument. A literal at-mark in the text can be represented by two successive at-marks. See also pack and glue.


:  (text "abc @1 def @2" 'XYZ 123)
-> "abc XYZ def 123"
: (text "a@@bc.@1" "de")
-> "a@bc.de"

(throw 'sym 'any)
Non-local jump into a previous catch environment with the jump label sym (or T as a catch-all). Any pending finally expressions are executed, local symbol bindings are restored, open files are closed and internal data structures are reset appropriately, as the environment was at the time when the corresponding catch was called. Then any is returned from that catch.


: (de foo (N)
   (println N)
   (throw 'Ok) )
-> foo
: (let N 1  (catch 'Ok (foo 7))  (println N))
7
1
-> 1

(tick (cnt1 . cnt2) . prg) -> any
Executes prg, then (destructively) adds the number of elapsed user ticks to the cnt1 parameter, and the number of elapsed system ticks to the cnt2 parameter. Thus, cnt1 and cnt2 will finally contain the total number of user and system time ticks spent in prg and all functions called (this works also for recursive functions). For execution profiling, tick is usually inserted into words with prof, and removed with unprof. See also usec.


: (de foo ()                        # Define function with empty loop
   (tick (0 . 0) (do 100000000)) )
-> foo
: (foo)                             # Execute it
-> NIL
: (pp 'foo)
(de foo NIL
   (tick (97 . 0) (do 100000000)) ) # 'tick' incremented 'cnt1' by 97
-> foo

(till 'any ['flg]) -> lst|sym
Reads from the current input channel till a character contained in any is found. If flg is NIL, a list of single-character transient symbols is returned. Otherwise, a single string is returned. See also from and line.


: (till ":")
abc:def
-> ("a" "b" "c")
: (till ":" T)
abc:def
-> "abc"

(time ['T]) -> tim
(time 'tim) -> (h m s)
(time 'h 'm ['s]) -> tim | NIL
(time '(h m [s])) -> tim | NIL
Calculates the time of day, represented as the number of seconds since midnight. When called without arguments, the current local time is returned. When called with a T argument, the current Coordinated Universal Time (UTC) is returned. When called with a single number tim, it is taken as a time value and a list with the corresponding hour, minute and second is returned. When called with two or three numbers (or a list of two or three numbers) for the hour, minute (and optionally the second), the corresponding time value is returned (or NIL if they do not represent a legal time). See also date and usec.


: (time)                         # Now
-> 32334
: (time 32334)                   # Now
-> (8 58 54)
: (time 25 30)                   # Illegal time
-> NIL

(touch 'sym) -> sym
When sym is an external symbol, it is marked as "modified" so that upon a later commit it will be written to the database file. An explicit call of touch is only necessary when the value or properties of sym are indirectly modified.


: (get '{2} 'lst)
-> (1 2 3 4 5)
: (set (cdr (get (touch '{2}) 'lst)) 999)    # Only read-access, need 'touch'
-> 999
: (get '{2} 'lst)                            # Modified second list element
-> (1 999 3 4 5)

(trace 'sym) -> sym
(trace 'sym 'cls) -> sym
(trace '(sym . cls)) -> sym
Inserts $ trace function call at the beginning of the function or method body of sym, so that trace information will be printed before and after execution. Built-in functions (C-function pointer) are automatically converted to Lisp expressions.


: (trace '+)
-> +
: (+ 3 4)
 + : 3 4
 + = 7
-> 7

(trim 'lst) -> lst
Returns a copy of lst with all trailing white space characters or NIL elements removed. See also clip.


: (trim (1 NIL 2 NIL NIL))
-> (1 NIL 2)
: (trim '(a b " " " "))
-> (a b)

(try 'msg 'any ['any ..]) -> any
Tries to send the message msg to the object obj, optionally with arguments any. If any is not an object, or if the message cannot be located in obj, its classes and superclasses, NIL is returned. See also send and method.


: (try 'msg> 123)
-> NIL
: (try 'html> 'a)
-> NIL

(type 'any) -> lst
Return the type (list of classes) of the object sym. See also isa.


: (type '{1A;3})
(+Address)


U

(udp 'any1 'cnt 'any2) -> any
(udp 'cnt) -> any
Simple unidirectional sending/receiving of UDP packets. In the first form, any2 is sent to a UDP server listening at host any1, port cnt. In the second form, one item is received from a UDP socket cnt, established with port. See also connect.


# First session
: (port T 6666)
-> 3
: (udp 3)  # Receive a datagram

# Second session (on the same machine)
: (udp "localhost" 6666 '(a b c))
-> (a b c)

# First session
-> (a b c)

(unify 'any) -> lst
Unifies any with the current Pilog environment at the current level and with a value of NIL, and returns the new environment or NIL if not successful. See also prove and ->.


: (? (@A unify '(@B @C)))
 @A=(((NIL . @C) 0 . @C) ((NIL . @B) 0 . @B) T)

(unless 'any . prg) -> any
Conditional execution: When the condition any evaluates to non-NIL, NIL is returned. Otherwise prg is executed and the result returned. See also when.


: (unless (= 3 3) (println 'Strange 'result))
-> NIL
: (unless (= 3 4) (println 'Strange 'result))
Strange result
-> result

(until 'any . prg) -> any
Conditional loop: While the condition any evaluates to NIL, prg is repeatedly executed. If prg is never executed, NIL is returned. Otherwise the result of prg is returned. See also while.


: (until (=T (setq N (read)))
   (println 'square (* N N)) )
4
square 16
9
square 81
T
-> 81

(up sym ['val]) -> any
Looks up (or modifies) the previously saved value of sym in the enclosing environment. See also eval, run and env.


: (let N 1 ((quote (N) (println N (up N))) 2))
2 1
-> 1
: (let N 1 ((quote (N) (println N (up N) (up N 7))) 2) N)
2 1 7
-> 7

(upp? 'any) -> sym | NIL
Returns any when the argument is a string (symbol) that starts with an uppercase character. See also uppc.


: (upp? "A")
-> T
: (upp? "a")
-> NIL
: (upp? 123)
-> NIL
: (upp? ".")
-> NIL

(uppc 'any) -> any
Upper case conversion: If any is not a symbol, it is returned as it is. Otherwise, a new transient symbol with all characters of any, converted to upper case, is returned. See also lowc, fold and upp?.


: (uppc 123)
-> 123
: (uppc "abc")
-> "ABC"
: (uppc 'car)
-> "CAR"

(use sym . prg) -> any
(use (sym ..) . prg) -> any
Defines local variables. The value of the symbol sym - or the values of the symbols sym in the list of the second form - are saved, prg is executed, then the symbols are restored to their original values. During execution of prg, the values of the symbols can be temporarily modified. The return value is the result of prg. See also bind, job and let.


: (setq  X 123  Y 456)
-> 456
: (use (X Y) (setq  X 3  Y 4) (* X Y))
-> 12
: X
-> 123
: Y
-> 456

(usec) -> num
Returns the number the microseconds since interpreter startup. See also time and tick.


: (usec)
-> 1154702479219050


V

(val 'var) -> any
Returns the current value of var.


: (setq L '(a b c))
-> (a b c)
: (val 'L)
-> (a b c)
: (val (cdr L))
-> b


W

(wait ['cnt] . prg) -> any
Waits for a condition. While the result of the execution of prg returns non-NIL, a select system call is executed for all file descriptors and timers in the VAL of the global variable *Run. When cnt is non-NIL, the waiting time is limited to cnt milliseconds. See also key and sync.


: (wait 2000)                                # Wait 2 seconds
-> NIL
: (prog
   (zero *Cnt)
   (setq *Run                                # Install background loop
      '((-2000 0 (println (inc '*Cnt)))) )   # Increment '*Cnt' every 2 sec
   (wait NIL (> *Cnt 6))                     # Wait until > 6
   (off *Run) )
1                                            # Waiting ..
2
3
4
5
6
7
-> NIL

(when 'any . prg) -> any
Conditional execution: When the condition any evaluates to non-NIL, prg is executed and the result is returned. Otherwise NIL is returned. See also unless.


: (when (> 4 3) (println 'Ok) (println 'Good))
Ok
Good
-> Good

(while 'any . prg) -> any
Conditional loop: While the condition any evaluates to non-NIL, prg is repeatedly executed. If prg is never executed, NIL is returned. Otherwise the result of prg is returned. See also until.


: (while (read)
   (println 'got: @) )
abc
got: abc
1234
got: 1234
NIL
-> 1234

(wipe 'sym|lst) -> sym|lst
Clears the VAL and the property list of sym, or of all symbols in the list lst. When a symbol is an external symbol, its state is also set to "not loaded". Does nothing when sym is an external symbol that has been modified or deleted ("dirty").


: (setq A (1 2 3 4))
-> (1 2 3 4)
: (put 'A 'a 1)
-> 1
: (put 'A 'b 2)
-> 2
: (show 'A)
A (1 2 3 4)
   b 2
   a 1
-> A
: (wipe 'A)
-> A
: (show 'A)
A NIL
-> A

(with 'sym . prg) -> any
Saves the current object This and sets it to the new value sym. Then prg is executed, and This is restored to its previous value. The return value is the result of prg. Used typically to access the local data of sym in the same manner as inside a method body. prg is not executed (and NIL is returned) when sym is NIL. (with 'X . prg) is equivalent to (let? This 'X . prg).


: (put 'X 'a 1)
-> 1
: (put 'X 'b 2)
-> 2
: (with 'X (list (: a) (: b)))
-> (1 2)

(wr 'num ..) -> num
Writes all num arguments as raw bytes to the current output channel. See also rd and pr.


: (out "x" (wr 1 255 257))                   # Write to "x"
-> 257
: (hd "x")
00000000  01 FF 01                                         ...
-> NIL


X

(xchg 'var 'var ..) -> any
Exchange the values of successive var argument pairs.


: (setq  A 1  B 2  C '(a b c))
-> (a b c)
: (xchg  'A C  'B (cdr C))
-> 2
: A
-> a
: B
-> b
: C
-> (1 2 c)

(xor 'any 'any) -> flg
Returns T if exactly one of the arguments evaluates to non-NIL.


: (xor T NIL)
-> T
: (xor T T)
-> NIL

(x| 'num ..) -> num
Returns the bitwise XOR of all num arguments. See also &, | and bit?.


: (x| 2 7)
-> 5
: (x| 2 7 1)
-> 4


Y


Z

(zap 'sym) -> sym
"Delete" the symbol sym. For internal symbols, that means to remove it from the internal hash table, effectively transforming it to a transient symbol. For external symbols, it means to mark it as "deleted", so that upon a later commit it will be removed from the database file. See also intern.


: (de foo (Lst) (car Lst))          # 'foo' calls 'car'
-> foo
: (zap 'car)                        # Delete the symbol 'car'
-> "car"
: (pp 'foo)
(de foo (Lst)
   ("car" Lst) )                    # 'car' is now a transient symbol
-> foo
: (foo (1 2 3))                     # 'foo' still works
-> 1
: (car (1 2 3))                     # Reader returns a new 'car' symbol
!? (car (1 2 3))
car -- Undefined
?

(zero sym ..) -> 0
Stores 0 in the VAL's of all argument symbols sym. See also one, on, off and onOff.


: (zero A B)
-> 0
: A
-> 0
: B
-> 0


Other

(! . prg) -> any
Low level breakpoint function: The current execution environment is saved and the I/O channels are redirected to the console. Then prg is displayed, and a read-eval-print-loop is entered (with ! as its prompt character), to evaluate expressions and examine the current program environment. An empty input line terminates the read-eval-print-loop, the environment and I/O channels are restored, and the result of prg is returned. ! is normally inserted into existing programs with the debug function. See also e, ^ and *Dbg.


: (de foo (N) (and (println 1) (! println N) (println 2)))
-> foo
: (foo 7)
1                 # Executed '(println 1)'
(println N)       # Entered breakpoint
! N               # Examine the value of 'N'
-> 7
! (e)             # Evaluate '^', i.e. (println N)
7
-> 7
! (e @)           # Evaluate '@' -> the result of '(println 1)'
-> 1
!                 # Empty line: continue
7                 # Executed '(println N)'
2                 # Executed '(println 2)'
-> 2

($ sym|lst lst . prg) -> any
Low level trace function: The first argument sym|lst is printed to the console with a proper indentation, followed by a colon :. If a function is traced, the first argument is the function symbol, else if a method is traced, it is a cons pair of message and class. The second argument lst should be a list of symbols, identical to the function's argument list. The current values of these symbols are printed, followed by a newline. Then prg is executed, and its return value printed in a similar way (this time with an equals sign = instead of a colon) and returned. $ is normally inserted into existing programs with the trace function.


: (de foo (A B) ($ foo (A B) (* A B)))
-> foo
: (foo 3 4)
 foo : 3 4        # Function entry, arguments 3 and 4
 foo = 12         # Function exit, return value 12
-> 12

(% 'num ..) -> num
Returns the remainder from the divisions of successive num arguments. The sign of the result is that of the first argument.


: (% 17 5)
-> 2
: (% -17 5)  # Sign is that of the first argument
-> -2
: (% 5 2)
-> 1
: (% 15 10)
-> 5
: (% 15 10 2)  # (% 15 10) -> 5, then (% 5 2) -> 1
-> 1

(& 'num ..) -> num
Returns the bitwise AND of all num arguments. See also |, x| and bit?.


: (& 6 3)
-> 2
: (& 7 3 1)
-> 1

(* 'num ..) -> num
Returns the product of all num arguments.


: (* 1 2 3)
-> 6
: (* 5 3 2 2)
-> 60

(*/ 'num1 ['num2 ..] 'num3) -> num
Returns the product of num1 and all following num2 arguments, divided by the num3 argument. The result is rounded to the nearest integer value.


: (*/ 3 4 2)
-> 6
: (*/ 1234 2 10)
-> 247
: (*/ 100 6)
-> 17

*Adr
A global variable holding the IP address of last recently accepted client. See also listen and accept.


: *Adr
-> "127.0.0.1"

*Bye
A global variable holding a (possibly empty) prg body, to be executed just before the termination of the Pico Lisp interpreter.


: (push '*Bye '(call 'rm "-r" *Tmp))   # Remove all temporary files
-> (call 'rm "-r" *Tmp)

*Class
A global variable holding the current class.


: (class +Test)
-> +Test
: *Class
-> +Test

*DB
A global constant holding the external symbol {1}, the database root. All transient symbols in a database can be reached from that root. Except during debugging, any explicit literal access to symbols in the database should be avoided, because otherwise a memory leak might occur (The garbage collector temporarily sets *DB to NIL and restores its value after collection, thus disposing of all external symbols not currently used in the program).


: (show *DB)
{1} NIL
   +City {P}
   +Person {3}
-> {1}
: (show '{P})
{P} NIL
   nm (566 . {AhDx})
-> {P}
: (show '{3})
{3} NIL
   tel (681376 . {Agyl})
   nm (1461322 . {2gu7})
-> {3}

*Dbg
A boolean variable controlling the $ (tracing) and ! (breakpoint) functions. They are enabled when *Dbg is non-NIL.


: (de foo (A B) (* A B))
-> foo
: (trace 'foo)
-> foo
: (foo 3 4)
 foo : 3 4
 foo = 12
-> 12
: (let *Dbg NIL (foo 3 4))
-> 12

*Err
A global variable holding a (possibly empty) prg body, which will be executed during error processing. See also Error Handling, *Rst and *Msg.


: (de *Err (prinl "Fatal error!"))
-> ((prinl "Fatal error!"))
: (/ 3 0)
!? (/ 3 0)
Div/0
Fatal error!
$

*Fork
A global variable holding a (possibly empty) prg body, to be executed after a call to fork in the child process.


: (push '*Fork '(off *Tmp))   # Clear '*Tmp' in child process
-> (off *Tmp)

*Led
A global variable holding a (possibly empty) prg body that implements a "Line editor". When non-NIL, it should return a single symbol (string) upon execution.


: (de *Led "(bye)")
# *Led redefined
-> *Led
: $                                    # Exit

*Msg
A global variable holding the last recently issued error message. See also Error Handling, *Err and *Rst.


: (+ 'A 2)
!? (+ 'A 2)
A -- Number expected
?
:
: *Msg
-> "Number expected"

*PPid
A global constant holding the process-id of the parent picolisp process, or NIL if the current process is a top level process.


: (println *PPid *Pid)
NIL 5286

: (unless (fork) (println *PPid *Pid) (bye))
5286 5522

*Pid
A global constant holding the current process-id.


: *Pid
-> 6386
: (call "ps")                          # Show processes
  PID TTY          TIME CMD
 .... ...      ........ .....
 6386 pts/1    00:00:00 bin/picolisp   # <- current process
 6388 pts/1    00:00:00 ps
-> T

*Rst
A global variable holding a (possibly empty) prg body, which will be executed after error processing. This makes it possible to restart an application despite of a failure. See also Error Handling, *Err and *Msg.


: (de loopTest ()
   (let N 4
      (loop
         (println (/ 100 (dec 'N))) ) ) )
-> loopTest
: (de *Rst
   (prinl "Loop Failed!")
   (wait 4000)
   (loopTest) )  # restart
-> *Rst
: (loopTest)
33
50
100
!? (/ 100 (dec 'N))
Div/0
Loop Failed!
33
50
100
!? (/ 100 (dec 'N))
Div/0
Loop Failed!
...

*Run
This global variable can hold a list of prg expressions which are used during key, sync and wait. The first element of each expression must either be a positive number (thus denoting a file descriptor to wait for) or a negative number (denoting a timeout value in milliseconds (in that case another number must follow to hold the remaining time)). A select system call is performed with these values, and the corresponding prg body is executed when input data are available or when a timeout occurred.


: (de *Run (-2000 0 (println '2sec)))     # Install 2-sec-timer
-> *Run
: 2sec                                    # Prints "2sec" every 2 seconds
2sec
2sec
                                          # (Enter) Exit
$

*Scl
A global variable holding the current fixed-point input scale. See also Numbers. The value can be locally overridden with the scl function:


: (pp 'scl)
(de scl (*Scl . "Prg")
   (run "Prg") )
-> scl
: (str "123.45")                 # Default value of '*Scl' is 0
-> (123)
: (scl 0 (str "123.45"))
-> (123)
: (scl 3 (str "123.45"))
-> (123450)

*Solo
A global variable indicating exclusive database access. Its value is 0 initially, set to T (or NIL) during cooperative database locks when lock is successfully called with a NIL (or non-NIL) argument.


: *Solo
-> 0
: (lock *DB)
-> NIL
: *Solo
-> NIL
: (rollback)
-> T
: *Solo
-> 0
: (lock)
-> NIL
: *Solo
-> T
: (rollback)
-> T
: *Solo
-> T

*Uni
A global variable holding all unique data that were collected with the comma (,) read-macro. See also Read-Macros.


: (off *Uni)            # Clear
-> NIL
: ,"abc"                # Collect a transient symbol
-> "abc"
: ,(1 2 3)              # Collect a list
-> (1 2 3)
: *Uni
-> ((1 2 3) "abc")

(+ 'num ..) -> num
Returns the sum of all num arguments.


: (+ 1 2 3)
-> 6

(- 'num ..) -> num
Returns the difference of the first num argument and all following arguments. If only a single argument is given, it is negated.


: (- 7)
-> -7
: (- 7 2 1)
-> 4

(/ 'num ..) -> num
Returns the the first num argument successively divided by all following arguments.


: (/ 12 3)
-> 4
: (/ 60 3 2 2)

(: sym|0 [sym1|cnt ..]) -> any
Fetches a value any from the properties of a symbol, or from a list, by applying the get algorithm to This and the following arguments. Used typically in methods or with bodies. See also get, =: and ::.


: (put 'X 'a 1)
-> 1
: (with 'X (: a))
-> 1

(:: sym [sym1|cnt .. sym2]) -> lst|sym
Fetches a property for a property key sym or sym2 from a symbol. That symbol is This (if no other arguments are given), or a symbol found by applying the get algorithm to This and the following arguments. The property (the cell, not just its value) is returned, suitable for direct (destructive) manipulations. Used typically in methods or with bodies. See also =: and :.


: (with 'X (=: cnt 0) (inc (:: cnt)) (: cnt))
-> 1

(< 'any ..) -> flg
Returns T when all arguments any are in strictly increasing order. See also Comparing.


: (< 3 4)
-> T
: (< 'a 'b 'c)
-> T
: (< 999 'a)
-> T

(<= 'any ..) -> flg
Returns T when all arguments any are in strictly non-decreasing order. See also Comparing.


: (<= 3 3)
-> T
: (<= 1 2 3)
-> T
: (<= "abc" "abc" "def")
-> T

(<> 'any ..) -> flg
Returns T when not all any arguments are equal (structure equality). (<> 'any ..) is equivalent to (not (= 'any ..)). See also Comparing.


: (<> 'a 'b)
-> T
: (<> 'a 'b 'b)
-> T
: (<> 'a 'a 'a)
-> NIL

(= 'any ..) -> flg
Returns T when all any arguments are equal (structure equality). See also Comparing.


: (= 6 (* 1 2 3))
-> T
: (= "a" "a")
-> T
: (== "a" "a")
-> T
: (= (1 (2) 3) (1 (2) 3))
-> T

(=0 'any) -> num | NIL
Returns 0 when any is a number with value zero. See also n0, lt0, ge0 and gt0.


: (=0 (- 6 3 2 1))
-> 0
: (=0 'a)
-> NIL

(=: sym [sym1|cnt .. sym2] 'any)
Stores a new value any for a property key sym or sym2 in a symbol. That symbol is This (if no other arguments are given), or a symbol found by applying the get algorithm to This and the following arguments. Used typically in methods or with bodies. See also put, : and ::.


: (with 'X (=: a 1) (=: b 2))
-> 2
: (get 'X 'a)
-> 1
: (get 'X 'b)
-> 2

(== 'any ..) -> flg
Returns T when all any arguments are the same (pointer equality). See also n==.


: (== 'a 'a)
-> T
: (== 'NIL NIL (val NIL) (car NIL) (cdr NIL))
-> T
: (== 6 (* 1 2 3))
-> NIL

(==== ['sym ..]) -> NIL
Close the current transient scope by clearing the transient hash table. All transient symbols become hidden and inaccessible by the reader. Then any optional sym arguments are inserted into the transient hash table. See also extern and intern.


: (setq S "abc")           # Read "abc"
-> "abc"
: (== S "abc")             # Read again, get the same symbol
-> T
: (====)                   # Close scope
-> NIL
: (== S "abc")             # Read again, get another symbol
-> NIL

(=T 'any) -> flg
Returns T when any is the symbol T. (=T X) is equivalent to (== T X). See also nT.


: (=T 0)
-> NIL
: (=T "T")
-> NIL
: (=T T)
-> T

(> 'any ..) -> flg
Returns T when all arguments any are in strictly decreasing order. See also Comparing.


: (> 4 3)
-> T
: (> 'A 999)
-> T

(>= 'any ..) -> flg
Returns T when all arguments any are in strictly non-increasing order. See also Comparing.


: (>= 'A 999)
-> T
: (>= 3 2 2 1)
-> T

(>> 'cnt 'num) -> num
Shifts right the num argument by cnt bit-positions. If cnt is negative, a corresponding left shift is performed.


: (>> 1 8)
-> 4
: (>> 3 16)
-> 2
: (>> -3 16)
-> 128
: (>> -1 -16)
-> -32

(? [sym 'any ..] . lst) -> flg
Top-level function for interactive Pilog queries. It displays each result, waits for console input, and terminates when a non-empty line is entered.


: (? (append (a b c) (d e f) @X))
 @X=(a b c d e f)
-> NIL

: (? (append @X @Y (a b c)))
 @X=NIL @Y=(a b c)
 @X=(a) @Y=(b c)
 @X=(a b) @Y=(c)
 @X=(a b c) @Y=NIL
-> NIL

: (? (append @X @Y (a b c)))
 @X=NIL @Y=(a b c).                       # Stopped
-> NIL

@
Holds the result of the last top level expression in the current read-eval-print loop, or the result of the conditional expression during the evaluation of flow functions (see @ Result). When @ is used as a formal parameter in lambda expressions, it denotes a variable number of evaluated arguments.
@@
Holds the result of the second last top level expression in the current read-eval-print loop (see @ Result).
@@@
Holds the result of the third last top level expression in the current read-eval-print loop (see @ Result).
^
Holds the currently executed expression during a breakpoint or an error. See also debug, !, e and *Dbg.


: (* (+ 3 4) (/ 7 0))
!? (/ 7 0)
Div/0
? ^
-> (/ 7 0)

(| 'num ..) -> num
Returns the bitwise OR of all num arguments. See also x|, & and bit?.


: (| 1 2)
-> 3
: (| 1 2 4 8)
-> 15


Download

The Pico Lisp system can be downloaded from the Pico Lisp Download page.