# R

`*Rule`
  A global variable holding the current Pilog rule symbol. It is cleared at the beginning of a new REPL. See also `be` and `clause`.

      : (be likes (John Mary))
      -> likes
      : *Rule
      -> likes

`*Run`
  This global variable can hold a list of `prg` expressions which are used during `key`, `sync`, `wait` and `listen`. 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 `poll(2)` system call is performed with these values, and the corresponding `prg` body is executed when input data are available or when a timeout occurred (with `@` set to the file descriptor or timeout value). See also `task`.

      : (de *Run (-2000 0 (println '2sec)))     # Install 2-sec-timer
      -> *Run
      : 2sec                                    # Prints "2sec" every 2 seconds
      2sec
      2sec
                                                # (Ctrl-D) Exit
      $

`+Ref`
  Prefix class for maintaining non-unique indexes to `+relation`s, a subclass of `+index`. Accepts an optional argument for a `+Hook` attribute. See also Database.

      (rel tel (+Fold +Ref +String))  # Phone number with folded, non-unique index

`+Ref2`
  Prefix class for maintaining a secondary ("backing") index to `+relation`s. Can only be used as a prefix class to `+Key` or `+Ref`. It maintains an index in the current (sub)class, in addition to that in one of the superclasses (must be a `+Ref`), to allow (sub)class-specific queries. See also Database.

      (class +Ord +Entity)             # Order class
      (rel nr (+Need +Ref +Number))    # Order number
      ...
      (class +EuOrd +Ord)              # EU-specific order subclass
      (rel nr (+Ref2 +Key +Number))    # Order number with backing index

`+relation`
  Abstract base class of all database relations. Relation objects are usually defined with `rel`. The class hierarchy includes the classes `+Any`, `+Bag`, `+Bool`, `+Number`, `+Date`, `+Time`, `+Symbol`, `+String`, `+Link`, `+Joint` and `+Blob`, and the prefix classes `+Hook`, `+Hook2`, `+index`, `+Key`, `+Ref`, `+Ref2`, `+Idx`, `+IdxFold`, `+Sn`, `+Fold`, `+Aux`, `+UB`, `+Dep`, `+List`, `+Need`, `+Mis`, `+Alt` and `+Swap`. See also Database and `+Entity`.

  Messages to relation objects include

      mis> (Val Obj)       # Return error if mismatching type or value
      has> (Val X)         # Check if the value is present
      put> (Obj Old New)   # Put new value
      rel> (Obj Old New)   # Maintain relational structures
      lose> (Obj Val)      # Delete relational structures
      keep> (Obj Val)      # Restore deleted relational structures
      zap> (Obj Val)       # Clean up relational structures

`(rand ['cnt1 'cnt2] | ['T]) -> cnt | flg`
  Returns a pseudo random number in the range of the positive short numbers `cnt1` and `cnt2` (or -2147483648 .. +2147483647 if no arguments are given). If the argument is `T`, a boolean value `flg` is returned. Note that if a range is given, the results are "more random" because the higher bits of the internal generator are used. See also `seed`.

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

`(range 'num1 'num2 ['num3]) -> lst`
  Produces a list of numbers in the range `num1` through `num2`. When `num3` is non-`NIL`, it is used to increment `num1` (if it is smaller than `num2`) or to decrement `num1` (if it is greater than `num2`). See also `need`.

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

`range/3`
  Pilog predicate that succeeds if the first argument is in the range of the result of applying the `get` algorithm to the following arguments. Typically used as filter predicate in `select/3` database queries. See also `Comparing`, `isa/2`, `same/3`, `bool/3`, `head/3`, `fold/3`, `part/3` and `tolr/3`.

      : (?
         @Nr (1 . 5)  # Numbers between 1 and 5
         @Nm "part"
         (select (@Item)
            ((nr +Item @Nr) (nm +Item @Nm))
            (range @Nr @Item nr)
            (part @Nm @Item nm) ) )
       @Nr=(1 . 5) @Nm="part" @Item={B1}
       @Nr=(1 . 5) @Nm="part" @Item={B2}
      -> NIL

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

`(rassoc 'any 'lst) -> lst`
  Reverse `assoc`. Returns the first element from `lst` with its CDR equal to `any`, or `NIL` if no match is found. See also `rasoq` and `asoq`.

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

`(rasoq 'any 'lst) -> lst`
  Reverse `asoq`. Returns the first element from `lst` with `any` as its CDR, or `NIL` if no match is found. `==` is used for comparison (pointer equality). See also `assoc` and `rassoc`.

      : (rasoq 'b '((1 . a) (2 . b) (3 . c))) )
      -> (2 . b)
      : (rasoq "b" '((1 . a) (2 . b) (3 . c))) )
      -> NIL

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

      $ pil +
      : (raw)
      -> NIL
      : (raw T)
      -> T
      ...  # Raw mode, no echo!

`(rc 'sym 'any1 ['any2 ['any3 'any4..]]) -> any`
  Fetches a value from a resource file `sym`, or stores one or more key-value pairs `(any1 . any2)` in that file, using the key `any1` (and optionally `any3` etc. for multiple stores). All values are stored in a list in the file, using `assoc`. During the whole operation, the file is exclusively locked with `ctl`.

      : (info "a.rc")               # File exists?
      -> NIL                        # No
      : (rc "a.rc" 'a 1)            # Store 1 for 'a'
      -> 1
      : (rc "a.rc" 'b (2 3 4))      # Store (2 3 4) for 'b'
      -> (2 3 4)
      : (rc "a.rc" 'c 'b)           # Store 'b' for 'c'
      -> b
      : (info "a.rc")               # Check file
      -> (28 733124 . 61673)
      : (in "a.rc" (echo))          # Display it
      ((c . b) (b 2 3 4) (a . 1))
      -> T
      : (rc "a.rc" 'c)              # Fetch value for 'c'
      -> b
      : (rc "a.rc" @)               # Fetch value for 'b'
      -> (2 3 4)

`(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, otherwise little endian) is read as a single number. Upon end of file, if the `sym` argument is given, it is returned, otherwise `NIL`. See also `pr`, `tell`, `hear` 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, an internal symbol, a transient symbol (for punctuation), or a list of symbols (for a string)) is read. In that case, `sym1` specifies which set of characters to accept for continuous symbol names (in addition to the standard alphanumerical characters), and `sym2` an optional comment character. See also `any`, `str`, `line`, `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
      NIL
      -> (abc "=" def_ghi "(" ("x" "y" "z") "+" "-" 123 ")")

`(recur fun) -> any`
`(recurse ..) -> any`
  Implements anonymous recursion, by defining the function `recurse` on the fly. During the execution of `fun`, the symbol `recurse` is bound to the function definition `fun`. See also `let` and `lambda`.

      : (de fibonacci (N)
         (when (lt0 N)
            (quit "Bad fibonacci" N) )
         (recur (N)
            (if (>= 2 N)
               1
               (+
                  (recurse (dec N))
                  (recurse (- N 2)) ) ) ) )
      -> fibonacci
      : (fibonacci 22)
      -> 17711
      : (fibonacci -7)
      -7 -- Bad fibonacci

`(redef sym . fun) -> sym`
  Redefines `sym` in terms of itself. The current definition is saved in a new symbol, which is substituted for each occurrence of `sym` in `fun`, and which is also returned. See also `de`, `undef`, `daemon` and `patch`.

      : (de hello () (prinl "Hello world!"))
      -> hello
      : (pp 'hello)
      (de hello NIL
         (prinl "Hello world!") )
      -> hello

      : (redef hello (A B)
         (println 'Before A)
         (prog1 (hello) (println 'After B)) )
      -> "hello"
      : (pp 'hello)
      (de hello (A B)
         (println 'Before A)
         (prog1 ("hello") (println 'After B)) )
      -> hello
      : (hello 1 2)
      Before 1
      Hello world!
      After 2
      -> "Hello world!"

      : (redef * @
         (msg (rest))
         (pass *) )
      -> "*"
      : (* 1 2 3)
      (1 2 3)
      -> 6

      : (redef + @
         (pass (ifn (num? (next)) pack +) (arg)) )
      -> "+"
      : (+ 1 2 3)
      -> 6
      : (+ "a" 'b '(c d e))
      -> "abcde"

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

      (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

`(release 'sym) -> NIL`
  Releases the mutex represented by the file 'sym'. This is the reverse operation of `acquire`.

      : (release "sema1")
      -> NIL

`remote/2`
  Pilog predicate for remote database queries. It takes a list and an arbitrary number of clauses. The list should contain a Pilog variable for the result in the CAR, and a list of resources in the CDR. The clauses will be evaluated on remote machines according to these resources. Each resource must be a cons pair of two functions, an "out" function in the CAR, and an "in" function in the CDR. See also `*Ext`, `revolve/2`, `select/3` and `db/3`.

      (setq *Ext           # Set up external offsets
         (mapcar
            '((@Host @Ext)
               (cons @Ext
                  (curry (@Host @Ext (Sock)) (Obj)
                     (when (or Sock (setq Sock (connect @Host 4040)))
                        (ext @Ext
                           (out Sock (pr (cons 'qsym Obj)))
                           (prog1
                              (in Sock (rd))
                              (unless @
                                 (close Sock)
                                 (off Sock) ) ) ) ) ) ) )
            '("localhost")
            '(20) ) )

      (de rsrc ()  # Simple resource handler, ignoring errors or EOFs
         (extract
            '((@Ext Host)
               (let? @Sock (connect Host 4040)
                  (cons
                     (curry (@Ext @Sock) (X)  # out
                        (ext @Ext (out @Sock (pr X))) )
                     (curry (@Ext @Sock) ()  # in
                        (ext @Ext (in @Sock (rd))) ) ) ) )
            '(20)
            '("localhost") ) )

      : (?
         @Nr (1 . 3)
         @Sup 2
         @Rsrc (rsrc)
         (remote (@Item . @Rsrc)
            (db nr +Item @Nr @Item)
            (val @Sup @Item sup nr) )
         (show @Item) )
      {AF2} (+Item)
         pr 1250
         inv 100
         sup {AG2}
         nm "Spare Part"
         nr 2
       @Nr=(1 . 3) @Sup=2 @Rsrc=((((X) (ext 20 (out 3 (pr X)))) NIL (ext 20 (in 3 (rd))))) @Item={AF2}
      -> NIL

`(remove 'cnt 'lst) -> lst`
  Removes the element at position `cnt` from `lst`. This is a non-destructive operation. See also `insert`, `place`, `append`, `delete` and `replace`.

      : (remove 3 '(a b c d e))
      -> (a b d e)
      : (remove 1 '(a b c d e))
      -> (b c d e)
      : (remove 9 '(a b c d e))
      -> (a b c d e)

`(repeat) -> lst`
  Makes the current Pilog definition "tail recursive", by closing the previously defined rules in the definition's T property to a circular list. See also `repeat/0` and `be`.

      (be a (1))     # Define three facts
      (be a (2))
      (be a (3))
      (repeat)       # Unlimited supply

      : (? (a @N))
       @N=1
       @N=2
       @N=3
       @N=1
       @N=2
       @N=3.         # Stop
      -> NIL

`repeat/0`
  Pilog predicate that always succeeds, also on backtracking. See also `repeat` and `true/0`.

      : (be integer (@I)   # Generate unlimited supply of integers
         (^ @C (box 0))    # Init to zero
         (repeat)          # Repeat from here
         (^ @I (inc @C)) )
      -> integer

      : (? (integer @X))
       @X=1
       @X=2
       @X=3
       @X=4.               # Stop
      -> NIL

`(replace 'lst 'any1 'any2 ..) -> lst`
  Replaces in `lst` all occurrences of `any1` with `any2`. For optional additional argument pairs, this process is repeated. This is a non-destructive operation. See also `append`, `delete`, `insert`, `remove` and `place`.

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

`(request 'typ 'sym ['hook] 'val ..) -> obj`
  Returns a database object. If a matching object cannot be found (using `db`), a new object of the given type is created (using `new`). See also `obj`.

      : (request '(+Item) 'nr 2)
      -> {B2}

`(request! 'typ 'sym ['hook] 'val ..) -> obj`
  Transaction wrapper function for `request`. See also `new!`, `set!`, `put!` and `inc!`.

`(rest) -> lst`
  Can only be used inside functions with a variable number of arguments (with `@`). Returns 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)

`(retract) -> lst`
  Removes a Pilog fact or rule. See also `be`, `clause`, `asserta` and `assertz`.

      : (be a (1))
      -> a
      : (be a (2))
      -> a
      : (be a (3))
      -> a

      : (retract '(a (2)))
      -> (((1)) ((3)))

      :  (? (a @N))
       @N=1
       @N=3
      -> NIL

`retract/1`
  Pilog predicate that removes a fact or rule. See also `retract`, `asserta/1` and `assertz/1`.

      : (be a (1))
      -> a
      : (be a (2))
      -> a
      : (be a (3))
      -> a

      : (? (retract (a 2)))
      -> T
      : (rules 'a)
      1 (be a (1))
      2 (be a (3))
      -> a

`(rev 'cnt1 'cnt2) -> cnt`
  Reverses the lowest `cnt1` bits of `cnt2`. See also `>>` and `hash`.

      : (bin (rev 4 (bin "0101")))
      -> "1010"
      : (rev 32 1)
      -> 2147483648
      : (hex @)
      -> "80000000"
      : (rev 32 (hex "E0000000"))
      -> 7

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

      : (out "a" (prinl "Hello world"))
      -> "Hello world"
      : (in "a" (echo))
      Hello world
      -> T
      : (info "a")
      -> (12 733216 . 53888)
      : (out "a" (rewind))
      -> T
      : (info "a")
      -> (0 733216 . 53922)

`revolve/2`
  Pilog predicate for quasi-parallel evaluation of clauses. It takes a list and an arbitrary number of clauses. The list should contain a Pilog variable for the result in the CAR, another Pilog variable for passing the values in the CADR, and a list of values in the CDDR. The clauses will be evaluated in a round-robin fashion. See also `remote/2`.

      : (solve
         (quote
            @Rsrc '((1 2 3 4) (5 6 7 8) (a b c))
            (revolve (@Res @Lst . @Rsrc)
               (lst @Res @Lst) ) )
         @Res )
      -> (1 5 a 2 6 b 3 7 c 4 8)

`(rid 'var 'any) -> any`
  Destructively removes all occurrences of `any` from the (possibly circular) value of `var`, and returns the new value. See also `fifo`, `queue`, `cut` and `del`.

      $: (off E)
      -> NIL
      : (fifo 'E 1 2 3 2 4 2)
      -> 2
      : E
      -> (2 1 2 3 2 4 .)
      $: (rid 'E 2)
      -> (4 1 3 .)
      $: (rid 'E 4)
      -> (3 1 .)

`(rollback) -> flg`
  Cancels a transaction, by discarding all modifications of external symbols. See also `commit`.

      : (pool "db")
      -> T
      # .. Modify external objects ..
      : (rollback)            # Rollback
      -> T

`(root 'tree) -> (num . sym)`
  Returns the root of a database index tree, with the number of entries in `num`, and the base node in `sym`. See also `tree`.

      : (root (tree 'nr '+Item))
      -> (6 . {H1})

`(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. See also `flip` .

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

`(round 'num1 ['num2]) -> sym`
  Formats a number `num1` with `num2` decimal places, according to the current scale `*Scl`. `num2` defaults to 3. See also Numbers and `format`.

      : (scl 4)               # Set scale to 4
      -> 4
      : (round 123456)        # Format with three decimal places
      -> "12.346"
      : (round 123456 2)      # Format with two decimal places
      -> "12.35"
      : (format 123456 *Scl)  # Format with full precision
      -> "12.3456"

`(rules 'sym ..) -> sym`
  Prints all rules defined for the `sym` arguments. See also Pilog and `be`.

      : (rules 'member 'append)
      1 (be member (@X (@X . @)))
      2 (be member (@X (@ . @Y)) (member @X @Y))
      1 (be append (NIL @X @X))
      2 (be append ((@A . @X) @Y (@A . @Z)) (append @X @Y @Z))
      -> append

`(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 an offset `cnt` is given, the value of `@` in the `cnt`'th call environment is used during that evaluation. `cnt` should be greater than zero. See also `up`.

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

      : (de f Prg
         (let A 12
            (println (cons 'Prg Prg) (cons 'A A))
            (run Prg 1) ) )
      -> f
      : (let (Prg 77  A 99)
         (f
            (println (cons 'Prg Prg) (cons 'A A)) ) )
      (Prg (println (cons 'Prg Prg) (cons 'A A))) (A . 12)
      (Prg . 77) (A . 99)
      -> (A . 99)