# C

`*CPU`
  A global variable holding the target CPU (architecture). Possible values include `"arm64"`, `"x86-64"`, `"ppc64"`, `"emu"` or `"JVM"`. 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 this will immediately return the matching string. If neither `throw` nor an error occurs, the result of `prg` is returned. 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"

`(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 '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 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`
  Returs 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 `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` and `step`.

      : (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

`(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 'sym [. prg]) -> any`
  Starts, resumes or stops a coroutine with the tag given by `sym`. 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 resume 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 'sym|NIL|pid) -> flg`
  When called with a symbolic argument, `ctty` changes the current TTY device to `sym` (if called with `NIL`, the TTY is not changed, and only the TTY flag of standard out and standar error is set). Otherwise, the local console is prepared for serving the PicoLisp process with the process ID `pid`. See also `raw`.

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

`(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` 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)