*CPU
"aarch64"
, "x86-64"
etc. See also *OS
and version
.
: *CPU -> "x86-64"
*Class
class
, extend
, dm
and var
and rel
.
: (class +Test) -> +Test : *Class -> +Test
(cache 'var 'any [. prg]) -> any
idx
structure
("memoization") in var
. A hash
of the argument any
is used
internally to build the index key. If no prg
is given, the internal
var
holding a previously stored value is returned (note that
var
may have a name which is not human-readable).
: (de fibonacci (N) (cache '(NIL) N (if (>= 2 N) 1 (+ (fibonacci (dec N)) (fibonacci (- N 2))) ) ) ) -> fibonacci : (fibonacci 22) -> 17711 : (fibonacci 10000) -> 3364476487643178326662161200510754331030 ... # (2090 digits)
: (off C) -> NIL : (cache 'C 1234 (* 3 4)) -> 12 : (inc (cache 'C 1234)) -> 13 : (val (cache 'C 1234)) -> 13
(call 'any ..) -> flg
any
arguments specify the
command and its arguments. Returns T
if the command was executed
successfully. The (system dependent) exit status code of the child process is
stored in the global variable @@
. See
also exec
.
: (when (call 'test "-r" "file.l") # Test if file exists and is readable (load "file.l") # Load it (call 'rm "file.l") ) # Remove it : (cons (call "sh" "-c" "kill -SEGV $$") @@ (hex @@)) -> (NIL 11 . "B")
call/1
: (be mapcar (@ NIL NIL)) -> mapcar : (be mapcar (@P (@X . @L) (@Y . @M)) (call @P @X @Y) # Call the given predicate (mapcar @P @L @M) ) -> mapcar : (? (mapcar permute ((a b c) (d e f)) @X)) @X=((a b c) (d e f)) @X=((a b c) (d f e)) @X=((a b c) (e d f)) ... @X=((a c b) (d e f)) @X=((a c b) (d f e)) @X=((a c b) (e d f)) ...
(can 'msg) -> lst
msg
. See also OO Concepts, class
, has
, dep
, what
and who
.
: (can 'zap>) -> ((zap> . +relation) (zap> . +Blob) (zap> . +Entity)) : (more @ pp) (dm (zap> . +relation) (Obj Val)) (dm (zap> . +Blob) (Obj Val) (and Val (call 'rm "-f" (blob Obj (: var))) ) ) (dm (zap> . +Entity) NIL (for X (getl This) (let V (or (atom X) (pop 'X)) (and (meta This X) (zap> @ This V)) ) ) ) -> NIL
(car 'var) -> any
var
if it is a symbol, or the
first element if it is a list. See also cdr
and c..r
.
: (car (1 2 3 4 5 6)) -> 1
(c[ad]*ar 'var) -> any
(c[ad]*dr 'lst) -> any
car
and cdr
functions, with up to four letters 'a' and
'd'.
: (cdar '((1 . 2) . 3)) -> 2
(case 'any (any1 . prg1) (any2 . prg2) ..) -> any
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. See also casq
and state
.
: (case (char 66) ("A" (+ 1 2 3)) (("B" "C") "Bambi") ("D" (* 1 2 3))) -> "Bambi" : (case 'b (a 1) ("b" 2) (b 3) (c 4)) -> 2
(casq 'any (any1 . prg1) (any2 . prg2) ..) -> any
any
is evaluated and compared to the CAR
elements anyN
of each clause. ==
is used for comparison (pointer equality). 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. See also case
and state
.
: (casq 'b (a 1) ("b" 2) (b 3) (c 4)) -> 3 : (casq 'b (a 1) ("b" 2) ((a b c) 3) (c 4)) -> 3
(catch 'any . prg) -> any
throw
or by a runtime error. If
any
is an atom, it is used by throw
as a jump label
(with T
being a catch-all for any label), and a throw
called during the execution of prg
will immediately return the
thrown value. Otherwise, any
should be a list of strings, to catch
any error whose message contains one of these strings, and catch
will immediately return the matching string. If neither throw
nor
an error occurred, the result of prg
is returned. The global
variable @@
is set to T
if
a throw
or error occurred, otherwise NIL
. See also
finally
, quit
and Error
Handling
.
: (catch 'OK (println 1) (throw 'OK 999) (println 2)) 1 -> 999 : (catch '("No such file") (in "doesntExist" (foo))) -> "No such file"
Pattern for catching and logging errors:
(if2 (catch '(NIL) (...) ) @@ (nil (msg *Msg)) # If an error was thrown, log it and return NIL @ ) ) ) # else return the value returned from catch
(cd 'any) -> sym
any
. The old directory is
returned on success, otherwise NIL
. See also chdir
, dir
and pwd
.
: (when (cd "lib") (println (length (dir))) (cd @) ) 99
(cdr 'lst) -> any
lst
. See also
car
and c..r
.
: (cdr (1 2 3 4 5 6)) -> (2 3 4 5 6)
(center 'cnt|lst 'any ..) -> sym
any
arguments pack
ed in a centered format. Trailing blanks
are omitted. See also align
, tab
and wrap
.
: (center 4 12) -> " 12" : (center 4 "a") -> " a" : (center 7 "a") -> " a" : (center (3 3 3) "a" "b" "c") -> " a b c"
(chain 'any ..) -> any
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 result list is
maintained. chain
returns the last linked argument. See also
link
, yoke
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
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 UTF-8
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 "d") # Convert symbol to unicode -> 100 : (char T) # Special case -> # (not printable) : (char 0) -> NIL : (char NIL) -> 0
(chdir 'any . prg) -> any
any
with cd
during the execution of prg
. Then
the previous directory will be restored and the result of prg
returned. See also dir
and pwd
.
: (pwd) -> "/usr/abu/pico" : (chdir "src" (pwd)) -> "/usr/abu/pico/src" : (pwd) -> "/usr/abu/pico"
(chkTree 'sym ['fun]) -> num
fun
is
called with the key and value of each node, and should return NIL
for failure. See also tree
and
root
.
: (show *DB '+Item) {40} 6 nr (6 . {H1}) pr (6 . {H3}) sup (6 . {H2}) nm (67 . {I3}) -> {40} : (chkTree '{H1}) # Check that node -> 6
(chop 'any) -> lst
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
any
arguments by cons
ing them to a list and then connecting the
CDR of the last cell to the first cell. See also circ?
and list
.
: (circ 'a 'b 'c) -> (a b c .)
(circ? 'any) -> any
any
is a circular list, else
NIL
. See also circ
.
: (circ? 'a) -> NIL : (circ? (1 2 3)) -> NIL : (circ? (1 . (2 3 .))) -> (2 3 .)
(class sym . typ) -> obj
sym
as a class with the superclass(es)
typ
. As a side effect, the global variable *Class
is set to obj
. See also
extend
, dm
, var
,
rel
, type
, isa
and object
.
: (class +A +B +C +D) -> +A : +A -> (+B +C +D) : (dm foo> (X) (bar X)) -> foo> : +A -> ((foo> (X) (bar X)) +B +C +D)
(clause '(sym . any)) -> sym
sym
argument, by concatenating the any
argument to the
T
property of sym
. See also *Rule
and be
.
: (clause '(likes (John Mary))) -> likes : (clause '(likes (John @X) (likes @X wine) (likes @X food))) -> likes : (? (likes @X @Y)) @X=John @Y=Mary -> NIL
clause/2
: (? (clause append ((NIL @X @X)))) -> T : (? (clause append @C)) @C=((NIL @X @X)) @C=(((@A . @X) @Y (@A . @Z)) (append @X @Y @Z)) -> NIL
(clip 'lst) -> lst
lst
with all whitespace 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) -> cnt | NIL
cnt
, and returns it when successful.
Should not be called inside an out
body
for that descriptor. See also open
,
poll
,
listen
and connect
.
: (close 2) # Close standard error -> 2
(cmd ['any]) -> sym
any
. Setting the name may not work on some operating systems. Note
that the new name must not be longer than the original one. See also argv
, file
and Invocation.
$ pil + : (cmd) -> "/usr/bin/picolisp" : (cmd "!/bin/picolust") -> "!/bin/picolust" : (cmd) -> "!/bin/picolust"
(cnt 'fun 'lst ..) -> cnt
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
(collect 'sym 'cls ['hook] ['any|beg ['end [sym|cnt ..]]])
cls
, where the
values for the sym
arguments correspond to the any
arguments, or where the values for the sym
arguments are in the
range beg
.. end
. sym
, cls
and hook
should specify a tree
for cls
or one of its
superclasses. If additional sym|cnt
arguments are given, the final
values for the result list are obtained by applying the get
algorithm. See also db
, aux
,
fetch
, init
, step
and and search
.
: (collect 'nr '+Item) -> ({B1} {B2} {B3} {B4} {B5} {B6} {B8}) : (collect 'nr '+Item 3 6 'nr) -> (3 4 5 6) : (collect 'nr '+Item 3 6 'nm) -> ("Auxiliary Construction" "Enhancement Additive" "Metal Fittings" "Gadget Appliance") : (collect 'nm '+Item "Main Part") -> ({B1})
(commit ['any] [exe1] [exe2]) -> T
any
is given, 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 lock
ed and protect
ed. See also rollback
.
: (pool "db") -> T : (put '{1} 'str "Hello") -> "Hello" : (commit) -> T
(complete 'any) -> T | lst
readline(3)
to complete the
text before the current input point. If it is NIL
,
readline's default filename generator function is used. Otherwise, it
should be a function which returns the next match (if any
is NIL
), some default value (if any
is
T
, meaning there is no partial word to be completed), or
initializes the generator with the given text and returns the first
result.
: (pp 'complete) (de complete (S) (when S (setq "*Cmpl" (if (=T S) (list " ") (flip (all* S))) ) ) (pop '"*Cmpl") ) -> complete
(con 'lst 'any) -> any
any
to the first cell of lst
, by
(destructively) storing any
in the CDR of lst
. See
also set
and conc
.
: (setq C (1 . a)) -> (1 . a) : (con C '(b c d)) -> (b c d) : C -> (1 b c d)
(conc 'lst ..) -> lst
append
and con
.
: (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
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
, and
,
if2
and when
.
: (cond ((= 3 4) (println 1)) ((= 3 3) (println 2)) (T (println 3)) ) 2 -> 2
(connect 'any1 'any2) -> cnt | NIL
any1
, port any2
. any1
may be either a
hostname or a standard internet address in numbers-and-dots/colons notation
(IPv4/IPv6). any2
may be either a port number or a service name.
Returns a socket descriptor cnt
, or NIL
if the
connection cannot be established. See also listen
and udp
.
: (connect "localhost" 4444) -> 3 : (connect "some.host.org" "http") -> 4
(cons 'any ['any ..]) -> lst
(cons 'a 'b 'c 'd)
is equivalent to (cons
'a (cons 'b (cons 'c 'd)))
. See also list
.
: (cons 1 2) -> (1 . 2) : (cons 'a '(b c d)) -> (a b c d) : (cons '(a b) '(c d)) -> ((a b) c d) : (cons 'a 'b 'c 'd) -> (a b c . d)
(copy 'any) -> any
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
(co ['any [. prg]]) -> any
any
. If called without arguments, the tag of the
currently running coroutine is returned. If prg
is not given, a
coroutine with that tag will be stopped. Otherwise, if a coroutine running with
that tag is found (pointer equality is used for comparison), its execution is
resumed. Else a new coroutine with that tag is initialized and started.
prg
will be executed until it either terminates normally, or until
yield
is called. In the latter case
co
returns, or transfers control to some other, already running,
coroutine. A coroutine cannot call or stop itself directly or indirectly. See
also stack
, catch
and throw
.
: (de pythag (N) # A generator function (if (=T N) (co 'rt) # Stop (co 'rt (for X N (for Y (range X N) (for Z (range Y N) (when (= (+ (* X X) (* Y Y)) (* Z Z)) (yield (list X Y Z)) ) ) ) ) ) ) ) : (pythag 20) -> (3 4 5) : (pythag 20) -> (5 12 13) : (pythag 20) -> (6 8 10)
(count 'tree) -> num
tree
and root
.
: (count (tree 'nr '+Item)) -> 7
(create 'typ 'sym 'lst . prg)
typ
with the properties in sym
and lst
.
It handles large amounts of data, by sorting and traversing each database index
separately. prg
is executed repeatedly - and should return a list
of values for the properties in sym
and lst
- until it
returns NIL
. If the fin
of
the list is NIL
, a new object of type typ
is created,
otherwise it should be an existing object to be updated. If sym
is
non-NIL
, the first column of the input data is assigned to the
sym
property and should already be sorted. The rest of the input
data is assigned to the properties in lst
. create
allocates heap memory, and builds temporary files which increase disk
requirements while it runs. No explicit lock
should be established on the database, and
no other processes should operate on this database while it runs. When creating
more than a few hundred million index entries per file, it might be necessary to
increase the number of open files with e.g. ulimit -n 10000
. See
also dbs
, new
, commit
and prune
.
# Minimal E/R model (class +Cls +Entity) # Class (rel key (+Key +Number)) # with a unique numeric key, (rel num (+Ref +Number)) # an indexed number, (rel str (+Ref +String)) # and an indexed string (dbs (0 +Cls) (4 (+Cls key)) # Each index in a different file (4 (+Cls num)) (4 (+Cls str)) ) # Generating random data (create '(+Cls) 'key '(num str) (co 'go # Use a coroutine as generator (for Key 100000000 # Key is sorted in input (yield # Return keys, numbers and single-char strings (list Key (rand) (char (rand 97 122))) ) ) ) ) # Reading from a file in PLIO format (create '(+Cls) 'key '(num str) (rd) ) # Reading from a TAB-separated CSV file (create '(+Cls) 'key '(num str) (when (split (line) "\t") (list (format (car @)) (format (cadr @)) (pack (caddr @)) ) ) ) # Direct, naive approach (without using 'create') # Don't try this at home! Takes forever due to disk trashing (prune 0) (gc 400 200) (for Key 100000000 (new `(db: +Cls) '(+Cls) 'key Key 'num (rand) 'str (char (rand 97 122)) ) (at (0 . 10000) (commit) (prune 7)) ) (commit) (prune) (gc 0)
(ctl 'sym . prg) -> any
sym
is "+
") can be set on the file
sym
, then executes prg
and releases the lock. If the
file 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
, out
, err
and pipe
.
$ echo 9 >count # Write '9' to file "count" $ pil + : (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 'pid) -> pid
(ctty 'any) -> any | NIL
ctty
changes the current TTY
device to any
(or just sets standard I/O to a PTY if
any
is NIL
). Otherwise, the local console is prepared
for serving the PicoLisp process with the process ID pid
. See also
raw
.
: (ctty "/dev/tty") -> "/dev/tty"
(curry lst . fun) -> fun
lst
and the functional expression fun
. Each member in
lst
that is a pat?
symbol
is substituted inside fun
by its value. All other symbols in
lst
are collected into a job
environment. curry
is a general
higher-order function, not limited to strict currying (which generates only
single-argument functions).
: (de multiplier (@X) (curry (@X) (N) (* @X N)) ) -> multiplier : (multiplier 7) -> ((N) (* 7 N)) : ((multiplier 7) 3) -> 21 : (def 'fiboCounter (curry ((N1 . 0) (N2 . 1)) (Cnt) (do Cnt (println (prog1 (+ N1 N2) (setq N1 N2 N2 @) ) ) ) ) ) -> fiboCounter : (pp 'fiboCounter) (de fiboCounter (Cnt) (job '((N2 . 1) (N1 . 0)) (do Cnt (println (prog1 (+ N1 N2) (setq N1 N2 N2 @)) ) ) ) ) -> fiboCounter : (fiboCounter 5) 1 2 3 5 8 -> 8 : (fiboCounter 5) 13 21 34 55 89 -> 89
(cut 'cnt 'var) -> lst
cnt
elements (CAR) from the stack in
var
. See also pop
,
rid
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)