# C

`*CPU`
  A global variable holding the target CPU (architecture). Typical values are `"aarch64"`, `"x86-64"` etc. See also `*OS` and `version`.

      : *CPU
      -> "x86-64"

`*Class`
  A global variable holding the current class. See also OO Concepts, `class`, `extend`, `dm` and `var` and `rel`.

      : (class +Test)
      -> +Test
      : *Class
      -> +Test

`(cache 'var 'any [. prg]) -> any`
  Speeds up some calculations by maintaining a tree of previously calculated results in an `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`
  Calls an external system command. The `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`
  Pilog predicate that succeeds if the argument term can be proven.

      : (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`
  (Debug mode only) Returns a list of all classes that accept the message `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`
  List access: Returns the value of `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`
  List access shortcuts. Combinations of the `car` and `cdr` functions, with up to four letters 'a' and 'd'.

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

`(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. 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`
  Multi-way branch: `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`
  Sets up the environment for a non-local jump which may be caused by `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`, if@@ 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:

      (if@@
         (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`
  Changes the current directory to `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`
  List access: Returns all but the first element of `lst`. See also `car` and `c..r`.

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

`(center 'cnt|lst 'any ..) -> sym`
  Returns a transient symbol with all `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`
  Concatenates (destructively) one or several new list 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 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`
  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 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`
  Changes the current directory to `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`
  Checks a database tree node (and recursively all sub-nodes) for consistency. Returns the total number of nodes checked. Optionally, `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`
  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 `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`
  Returns the circular list tail if `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`
  Defines `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`
  Declares a Pilog fact or rule for the `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`
  Pilog predicate that succeeds if the first argument is a predicate which has the second argument defined as a clause.

      : (? (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`
  Returns a copy of `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`
  Closes a file descriptor `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`
  When called without an argument, the name of the command that invoked the picolisp interpreter is returned. Otherwise, the command name is set to `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`
  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

`(collect 'sym 'cls ['hook] ['any|beg ['end [sym|cnt ..]]])`
  Returns a list of all database objects of class `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`
  Closes a transaction, by writing all new or modified external symbols to, and removing all deleted external symbols from the database. When `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`
  Global variable holding a (possibly empty) function, which will be called when TAB is pressed in `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`
  Connects `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`
  Concatenates all argument lists (destructively). See also `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`
  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`, `and`, `if2` and `when`.

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

`(connect 'any1 'any2) -> cnt | NIL`
  Tries to establish a TCP/IP connection to a server listening at host `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`
  Constructs a new list cell with the first argument in the CAR and the second argument in the CDR. If more than two arguments are given, a corresponding chain of cells is built. `(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`
  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

`(co ['any [. prg]]) -> any`
  Starts, resumes or stops a coroutine with the tag given by `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`
  Returns the number of nodes in a database tree. See also `tree` and `root`.

      : (count (tree 'nr '+Item))
      -> 7

`(create 'typ 'sym 'lst . prg)`
  Creates or updates database objects of the type `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`
  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 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`
  Unless called with a short number, `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`
  Builds a new function from the list of symbols or symbol-value pairs `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`
  Pops the first `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)