*newlisp-function-reference* *nl-function-reference* FUNCTIONS IN ALPHABETICAL ORDER *newlisp-function-!* *nl-!* FUNCTION: !~ {syntax:} (! {str-shell-command} [{int-flags}]) Executes the command in {str-shell-command} by shelling out to the operating system and executing. This function returns a different value depending on the host operating system. > (! "vi") (! "ls -ltr") < Use the |nl-exec| function to execute a shell command and capture the standard output or to feed standard input. The |nl-process| function may be used to launch a non-blocking child process and redirect std I/O and std error to pipes. On Ms Windows the optional {int-flags} parameter takes process creation flags as defined for the Windows {CreateProcessA} function to control various parameters of process creation. The inclusion of this parameter – which also can be {0} – forces a different creation of the process without a command shell window. This parameter is ignored on Unix. > ; on MS Windows ; close the console of the currently running newLISP process (apply (import "kernel32" "FreeConsole")) ; start another process and wait for it to finish (! "notepad.exe" 0) (exit) < Without the additional parameter, the |nl-!| call would create a new command window replacing the closed one. Note that |nl-!| (exclamation mark) can be also be used as a command-line shell operator by omitting the parenthesis and space after the |nl-!|: > > !ls -ltr ; executed in the newLISP shell window < Used in this way, the |nl-!| operator is not a newLISP function at all, but rather a special feature of the newLISP command shell. The |nl-!| must be entered as the first character on the command-line. *newlisp-function-$* *nl-$* FUNCTION: $~ {syntax:} ($ {int-idx}) The functions that use regular expressions (|nl-directory|, |nl-ends-with|, |nl-find|, |nl-parse|, |nl-regex|, |nl-search|, |nl-starts-with| and |nl-replace|) all bind their results to the predefined system variables {$0}, {$1}, {$2}–{$15} after or during the function's execution. System variables can be treated the same as any other symbol. As an alternative, the contents of these variables may also be accessed by using {($ 0)}, {($ 1)}, {($ 2)}, etc. This method allows indexed access (i.e., {($ i)}, where {i} is an integer). > (set 'str "http://newlisp.org:80") (find "http://(.*):(.*)" str 0) ;→ 0 $0 ;→ "http://newlisp.org:80" $1 ;→ "newlisp.org" $2 ;→ "80" ($ 0) ;→ "http://newlisp.org:80" ($ 1) ;→ "newlisp.org" ($ 2) ;→ "80" < *newlisp-function-+* *nl-+* *newlisp-function--* *nl--* *newlisp-function-star* *nl-star* *newlisp-function-/* *nl-/* *newlisp-function-%* *nl-%* FUNCTION: +, -, *, /, %~ {syntax:} (+ {int-1} [{int-2} ... ]) Returns the sum of all numbers in {int-1} --. {syntax:} (- {int-1} [{int-2} ... ]) Subtracts {int-2} from {int-1}, then the next {int-i} from the previous result. If only one argument is given, its sign is reversed. {syntax:} (* {int-1} [{int-2} ... ]) The product is calculated for {int-1} to {int-i}. {syntax:} (/ {int-1} [{int-2} ... ]) Each result is divided successively until the end of the list is reached. Division by zero causes an error. {syntax:} (% {int-1} [{int-2} ... ]) Each result is divided successively by the next {int}, then the rest (modulo operation) is returned. Division by zero causes an error. For floating point numbers, use the |nl-mod| function. > (+ 1 2 3 4 5) ;→ 15 (+ 1 2 (- 5 2) 8) ;→ 14 (- 10 3 2 1) ;→ 4 (- (* 3 4) 6 1 2) ;→ 3 (- 123) ;→ -123 (map - '(10 20 30)) ;→ (-10 -20 -30) (* 1 2 3) ;→ 6 (* 10 (- 8 2)) ;→ 60 (/ 12 3) ;→ 4 (/ 120 3 20 2) ;→ 1 (% 10 3) ;→ 1 (% -10 3) ;→ -1 (+ 1.2 3.9) ;→ 4 < Floating point values in arguments to |nl-+|, |nl--|, |nl-star|, |nl-/|, and |nl-%| are truncated to the integer value closest to {0} (zero). Floating point values larger or smaller than the maximum ({9,223,372,036,854,775,807}) or minimum ({-9,223,372,036,854,775,808}) integer values are truncated to those values. This includes the values for {+Inf} and {-Inf}. Calculations resulting in values larger than {9,223,372,036,854,775,807} or smaller than {-9,223,372,036,854,775,808} wrap around from positive to negative or negative to positive. Floating point values that evaluate to {NaN} (Not a Number), ar treated as {0} (zero). *newlisp-function-++* *nl-++* FUNCTION: ++~ |nl-destructive| {syntax:} (++ {place} [{num} ... ]) The |nl-++| operator works like |nl-inc|, but performs integer arithmetic. Without the optional argument in {num}, |nl-++| increments the number in {place} by {1}. If floating point numbers are passed as arguments, their fractional part gets truncated first. Calculations resulting in numbers greater than 9,223,372,036,854,775,807 wrap around to negative numbers. Results smaller than -9,223,372,036,854,775,808 wrap around to positive numbers. {place} is either a symbol or a place in a list structure holding a number, or a number returned by an expression. > (set 'x 1) (++ x) ;→ 2 (set 'x 3.8) (++ x) ;→ 4 (++ x 1.3) ;→ 5 (set 'lst '(1 2 3)) (++ (lst 1) 2)) ;→ 4 lst ;→ (1 4 3) < If the symbol for {place} contains {nil}, it is treated as if containing {0}. See |nl---| for decrementing numbers in integer mode. See |nl-inc| for incrementing numbers in floating point mode. *newlisp-function---* *nl---* FUNCTION: --~ |nl-destructive| {syntax:} (-- {place} [{num} ... ]) The |nl---| operator works like |nl-dec|, but performs integer arithmetic. Without the optional argument in {num-2}, |nl---| decrements the number in {place} by {1}. If floating point numbers are passed as arguments, their fractional part gets truncated first. Calculations resulting in numbers greater than 9,223,372,036,854,775,807 wrap around to negative numbers. Results smaller than -9,223,372,036,854,775,808 wrap around to positive numbers. {place} is either a symbol or a place in a list structure holding a number, or a number returned by an expression. > (set 'x 1) (-- x) ;→ 0 (set 'x 3.8) (-- x) ;→ 2 (-- x 1.3) ;→ 1 (set 'lst '(1 2 3)) (-- (lst 1) 2)) ;→ 0 lst ;→ (1 0 3) < If the symbol for {place} contains {nil}, it is treated as if containing {0}. See |nl-++| for incrementing numbers in integer mode. See |nl-dec| for decrementing numbers in floating point mode. *newlisp-function-<* *nl-<* *newlisp-function->* *nl->* *newlisp-function-=* *nl-=* *newlisp-function-<=* *nl-<=* *newlisp-function->=* *nl->=* *newlisp-function-!=* *nl-!=* FUNCTION: <, >, =, <=, >=, !=~ {syntax:} (< {exp-1} [{exp-2} ... ]) + {syntax:} (> {exp-1} [{exp-2} ... ]) + {syntax:} (= {exp-1} [{exp-2} ... ]) + {syntax:} (<= {exp-1} [{exp-2} ... ]) + {syntax:} (>= {exp-1} [{exp-2} ... ]) + {syntax:} (!= {exp-1} [{exp-2} ... ]) Expressions are evaluated and the results are compared successively. As long as the comparisons conform to the comparison operators, evaluation and comparison will continue until all arguments are tested and the result is {true}. As soon as one comparison fails, {nil} is returned. If only one argument is supplied, all comparison operators assume {0} (zero) as a second argument. This can be used to check if a numer is negative, positive, zero or not zero. All types of expressions can be compared: atoms, numbers, symbols, and strings. List expressions can also be compared (list elements are compared recursively). When comparing lists, elements at the beginning of the list are considered more significant than the elements following (similar to characters in a string). When comparing lists of different lengths but equal elements, the longer list is considered greater (see examples). In mixed-type expressions, the types are compared from lowest to highest. Floats and integers are compared by first converting them to the needed type, then comparing them as numbers. *********************************************************************** *Atoms:* nil, true, integer or float, string, symbol, primitive + *Lists:* quoted list/expression, list/expression, lambda, lambda-macro *********************************************************************** > (< 3 5 8 9) ;→ true (> 4 2 3 6) ;→ nil (< "a" "c" "d") ;→ true (>= duba aba) ;→ true (< '(3 4) '(1 5)) ;→ nil (> '(1 2 3) '(1 2)) ;→ true (= '(5 7 8) '(5 7 8)) ;→ true (!= 1 4 3 7 3) ;→ true (< 1.2 6 "Hello" 'any '(1 2 3)) ;→ true (< nil true) ;→ true (< '(((a b))) '(((b c)))) ;→ true (< '((a (b c)) '(a (b d)) '(a (b (d))))) ;→ true ; with single argument compares against 0 (> 1) ;→ true ; checks for positive (> -1) ;→ nil ; checks for negative (= 123) ;→ nil ; checks for zero (map > '(1 3 -4 -3 1 2)) ;→ (true true nil nil true true) < *newlisp-function-<<* *nl-<<* *newlisp-function->>* *nl->>* FUNCTION: <<, >>~ {syntax:} (<< {int-1} {int-2} [{int-3} ... ]) + {syntax:} (>> {int-1} {int-2} [{int-3} ... ]) + {syntax:} (<< {int-1}) + {syntax:} (>> {int-1}) The number {int-1} is arithmetically shifted to the left or right by the number of bits given as {int-2}, then shifted by {int-3} and so on. For example, 64-bit integers may be shifted up to 63 positions. When shifting right, the most significant bit is duplicated (_arithmetic shift_): > (>> 0x8000000000000000 1) ;→ 0xC000000000000000 ; not 0x0400000000000000! < > (<< 1 3) ;→ 8 (<< 1 2 1) ;→ 8 (>> 1024 10) ;→ 1 (>> 160 2 2) ;→ 10 (<< 3) ;→ 6 (>> 8) ;→ 4 < When {int-1} is the only argument |nl-<<| and |nl->>| shift by one bit. *newlisp-function-&* *nl-&* FUNCTION: &~ {syntax:} (& {int-1} {int-2} [{int-3} ... ]) A bitwise |nl-and| operation is performed on the number in {int-1} with the number in {int-2}, then successively with {int-3}, etc. > (& 0xAABB 0x000F) ;→ 11 ; which is 0xB < *newlisp-function-|* *nl-|* FUNCTION: |~ {syntax:} (| {int-1} {int-2} [{int-3} ... ]) A bitwise |nl-or| operation is performed on the number in {int-1} with the number in {int-2}, then successively with {int-3}, etc. > (| 0x10 0x80 2 1) ;→ 147 < *newlisp-function-^* *nl-^* FUNCTION: ^~ {syntax:} (^ {int-1} {int-2} [{int-3} ... ]) A bitwise {xor} operation is performed on the number in {int-1} with the number in {int-2}, then successively with {int-3}, etc. > (^ 0xAA 0x55) ;→ 255 < *newlisp-function-~* *nl-~* FUNCTION: ~~ {syntax:} (~ {int}) A bitwise |nl-not| operation is performed on the number in {int}, reversing all of the bits. > (format "%X" (~ 0xFFFFFFAA)) ;→ "55" (~ 0xFFFFFFFF) ;→ 0 < *newlisp-function-:* *nl-:* FUNCTION: :~ {syntax:} (: {sym-function} {list-object} [ ... ]) The colon is used not only as a syntactic separator between between namespace prefix and the term inside but also as an operator. When used as an operator, the colon |nl-:| constructs a context symbol from the context name in the object list and the symbol following the colon. The object list in {list-object} can be followed by other parameters. The |nl-:| operator implements {polymorphism} of object methods, which are part of different object classes represented by contexts (namespaces). In newLISP, an object is represented by a list, the first element of which is the symbol (name) of its class context. The class context implements the functions applicable to the object. No space is required between the colon and the symbol following it. > (define (Rectangle:area) (mul (self 3) (self 4))) (define (Circle:area) (mul (pow (self 3) 2) (acos 0) 2)) (define (Rectangle:move dx dy) (inc (self 1) dx) (inc (self 2) dy)) (define (Circle:move p dx dy) (inc (self 1) dx) (inc (self 2) dy)) (set 'myrect '(Rectangle 5 5 10 20)) ; x y width height (set 'mycircle '(Circle 1 2 10)) ; x y radius ;; using the : (colon) operator to resolve to a specific context (:area myrect) ;→ 200 (:area mycircle) ;→ 314.1592654 ;; map class methods uses curry to enclose the colon operator and class function (map (curry :area) (list myrect mycircle)) ;→ (200 314.1592654) (map (curry :area) '((Rectangle 5 5 10 20) (Circle 1 2 10))) ;→ (200 314.1592654) ;; change object attributes using a function and re-assigning ;; to the objects name (:move myrect 2 3) myrect ;→ (Rectangle 7 8 10 20) (:move mycircle 4 5) mycircle ;→ (Circle 5 7 10) < Inside the FOOP methods the |nl-self| function is used to access the target object of the method. *newlisp-function-abort* *nl-abort* FUNCTION: abort~ {syntax:} (abort {int-pid}) + {syntax:} (abort) In the first form, |nl-abort| aborts a specific child process of the current parent process giving the process id in {int-pid}. The process must have been started using |nl-spawn|. For processes started using |nl-fork|, use |nl-destroy| instead. The function |nl-abort| is not available on Win32. > (abort 2245) ;→ true < To abort all child processes spawned from the current process use |nl-abort| without any parameters: > (abort) ;→ true ; abort all < The function |nl-abort| is part of the Cilk API for synchronizing child processes and process parallelization. See the reference for the function |nl-spawn| for a full discussion of the Cilk API. *newlisp-function-abs* *nl-abs* FUNCTION: abs~ {syntax:} (abs {num}) Returns the absolute value of the number in {num}. > (abs -3.5) ;→ 3.5 < *newlisp-function-acos* *nl-acos* FUNCTION: acos~ {syntax:} (acos {num-radians}) The arc-cosine function is calculated from the number in {num-radians}. > (acos 1) ;→ 0 (cos (acos 1)) ;→ 1 < *newlisp-function-acosh* *nl-acosh* FUNCTION: acosh~ {syntax:} (acosh {num-radians}) Calculates the inverse hyperbolic cosine of {num-radians}, the value whose hyperbolic cosine is {num-radians}. If {num-radians} is less than 1, |nl-acosh| returns {NaN}. > (acosh 2) ;→ 1.316957897 (cosh (acosh 2)) ;→ 2 (acosh 0.5) ;→ NaN < *newlisp-function-add* *nl-add* FUNCTION: add~ {syntax:} (add {num-1} [{num-2} ... ]) All of the numbers in {num-1}, {num-2}, and on are summed. |nl-add| accepts float or integer operands, but it always returns a floating point number. Any floating point calculation with {NaN} also returns {NaN}. > (add 2 3.25 9) ;→ 14.25 (add 1 2 3 4 5) ;→ 15 < *newlisp-function-address* *nl-address* FUNCTION: address~ {syntax:} (address {int}) + {syntax:} (address {float}) + {syntax:} (address {str}) Returns the memory address of the integer in {int}, the double floating point number in {float}, or the string in {str}. This function is used for passing parameters to library functions that have been imported using the |nl-import| function. > (set 's "\001\002\003\004") (get-char (+ (address s) 3)) ;→ 4 (set 'x 12345) ; x is a 64-bit long int ; on a big-endian CPU, i.e. PPC or SPARC (get-long (address x)) ;→ 12345 ; the 32-bit int is in high 32-bit part of the long int (get-int (+ (address x) 4)) ;→ 12345 ; on a little-endian CPU, i.e. Intel i386 ; the 32-bit int is in the low 32-bit part of the long int (get-int (address x)) ;→ 12345 ; on both architectures (integers are 64 bit in newLISP) (set 'x 1234567890) (get-long (address x)) ;→ 1234567890 < When a string is passed to C library function the address of the string is used automatically, and it is not necessary to use the |nl-address| function in that case. As the example shows, |nl-address| can be used to do pointer arithmetic on the string's address. |nl-address| should only be used on persistent addresses from data objects referred to by a variable symbol, not from volatile intermediate expression objects. See also the |nl-get-char|, |nl-get-int|, |nl-get-long| and |nl-get-float| functions. *newlisp-function-amb* *nl-amb* FUNCTION: amb~ {syntax:} (amb {exp-1} [{exp-2} ... ]) One of the expressions {exp-1} ... {n} is selected at random, and the evaluation result is returned. > (amb 'a 'b 'c 'd 'e) ;→ one of: a, b, c, d, or e at random (dotimes (x 10) (print (amb 3 5 7))) ;→ 35777535755 < Internally, newLISP uses the same function as |nl-rand| to pick a random number. To generate random floating point numbers, use |nl-random|, |nl-randomize|, or |nl-normal|. To initialize the pseudo random number generating process at a specific starting point, use the |nl-seed| function. *newlisp-function-and* *nl-and* FUNCTION: and~ {syntax:} (and {exp-1} [{exp-2} ... ]) The expressions {exp-1}, {exp-2}, {etc.} are evaluated in order, returning the result of the last expression. If any of the expressions yield {nil} or the empty list {()}, evaluation is terminated and {nil} or the empty list {()} is returned. > (set 'x 10) ;→ 10 (and (< x 100) (> x 2)) ;→ true (and (< x 100) (> x 2) "passed") ;→ "passed" (and '()) ;→ () (and true) ;→ true (and) ;→ true < *newlisp-function-append* *nl-append* FUNCTION: append~ {syntax:} (append {list-1} [{list-2} ... ]) + {syntax:} (append {array-1} [{array-2} ... ]) + {syntax:} (append {str-1} [{str-2} ... ]) In the first form, |nl-append| works with lists, appending {list-1} through {list-n} to form a new list. The original lists are left unchanged. > (append '(1 2 3) '(4 5 6) '(a b)) ;→ (1 2 3 4 5 6 a b) (set 'aList '("hello" "world")) ;→ ("hello" "world") (append aList '("here" "I am")) ;→ ("hello" "world" "here" "I am") < In the second form |nl-append| works on arrays: > (set 'A (array 3 2 (sequence 1 6))) ;→ ((1 2) (3 4) (5 6)) (set 'B (array 2 2 (sequence 7 10))) ;→ ((7 8) (9 10)) (append A B) ;→ ((1 2) (3 4) (5 6) (7 8) (9 10)) (append B B B) ;→ ((7 8) (9 10) (7 8) (9 10) (7 8) (9 10)) < In the third form, |nl-append| works on strings. The strings in {str-n} are concatenated into a new string and returned. > (set 'more " how are you") ;→ " how are you" (append "Hello " "world," more) ;→ "Hello world, how are you" < |nl-append| is also suitable for processing binary strings containing zeroes. The |nl-string| function would cut of strings at zero bytes. Linkage characters or strings can be specified using the |nl-join| function. Use the |nl-string| function to convert arguments to strings and append in one step. Use the functions |nl-extend| and |nl-push| to append to an existing list or string modifying the target. *newlisp-function-append-file* *nl-append-file* FUNCTION: append-file~ {syntax:} (append-file {str-filename} {str-buffer}) Works similarly to |nl-write-file|, but the content in {str-buffer} is appended if the file in {str-filename} exists. If the file does not exist, it is created (in this case, |nl-append-file| works identically to |nl-write-file|). This function returns the number of bytes written. On failure the function returns {nil}. For error information, use |nl-sys-error| when used on files. When used on URLs |nl-net-error| gives more error information. > (write-file "myfile.txt" "ABC") (append-file "myfile.txt" "DEF") (read-file "myfile.txt") ;→ "ABCDEF" < |nl-append-file| can take a {http://} or {file://} URL in {str-file-name}. In case of the {http://} prefix , |nl-append-file| works exactly like |nl-put-url| with {"Pragma: append\r\n"} in the header option and can take the same additional parameters. The {"Pragma: append\r\n"} option is supplied automatically. > (append-file "http://asite.com/message.txt" "More message text.") < The file {message.txt} is appended at a remote location {http://asite.com} with the contents of {str-buffer}. If the file does not yet exist, it will be created. In this mode, |nl-append-file| can also be used to transfer files to remote newLISP server nodes. See also |nl-read-file| and |nl-write-file|. *newlisp-function-apply* *nl-apply* FUNCTION: apply~ {syntax:} (apply {func list} [{int-reduce}]) Applies the contents of {func} (primitive, user-defined function, or lambda expression) to the arguments in {list}. > (apply + '(1 2 3 4)) ;→ 10 (set 'aList '(3 4 5)) ;→ (3 4 5) (apply * aList) ;→ 60 (apply sqrt '(25)) ;→ 5 (apply (lambda (x y) (* x y)) '(3 4)) ;→ 12 < The {int-reduce} parameter can optionally contain the number of arguments taken by the function in {func}. In this case, {func} will be repeatedly applied using the previous result as the first argument and taking the other arguments required successively from {list} (in left-associative order). For example, if {op} takes two arguments, then: > (apply op '(1 2 3 4 5) 2) ;; is equivalent to (op (op (op (op 1 2) 3) 4) 5) ;; find the greatest common divisor ;; of two or more integers ;; note that newLISP already has a gcd function (define (gcd_ a b) (let (r (% b a)) (if (= r 0) a (gcd_ r a)))) (define-macro (my-gcd) (apply gcd_ (args) 2)) (my-gcd 12 18 6) ;→ 6 (my-gcd 12 18 6 4) ;→ 2 < The last example shows how |nl-apply|'s {reduce} functionality can be used to convert a two-argument function into one that takes multiple arguments. Note, that a built-in |nl-gcd| is available. |nl-apply| should only be used on functions and operators that evaluate all of their arguments, not on {special forms} like |nl-dotimes| or |nl-case|, which evaluate only some of their arguments. Doing so will cause the function to fail. *newlisp-function-args* *nl-args* FUNCTION: args~ {syntax:} (args) + {syntax:} (args {int-idx-1} [{int-idx-2} ... ]) Accesses a list of all unbound arguments passed to the currently evaluating |nl-define|, |nl-define-macro| lambda, or lambda-macro expression. Only the arguments of the current function or macro that remain after local variable binding has occurred are available. The |nl-args| function is useful for defining functions or macros with a variable number of parameters. |nl-args| can be used to define hygienic macros that avoid the danger of variable capture. See |nl-define-macro|. > (define-macro (print-line) (dolist (x (args)) (print x "\n"))) (print-line "hello" "World") < This example prints a line-feed after each argument. The macro mimics the effect of the built-in function |nl-println|. In the second syntax, |nl-args| can take one or more indices ({int-idx-n}). > (define-macro (foo) (print (args 2) (args 1) (args 0))) (foo x y z) zyx (define (bar) (args 0 2 -1)) (bar '(1 2 (3 4))) ;→ 4 < The function {foo} prints out the arguments in reverse order. The {bar} function shows |nl-args| being used with multiple indices to access nested lists. Remember that {(args)} only contains the arguments not already bound to local variables of the current function or macro: > (define (foo a b) (args)) (foo 1 2) ;→ () (foo 1 2 3 4 5) ;→ (3 4 5) < In the first example, an empty list is returned because the arguments are bound to the two local symbols, {a} and {b}. The second example demonstrates that, after the first two arguments are bound (as in the first example), three arguments remain and are then returned by |nl-args|. {(args)} can be used as an argument to a built-in or user-defined function call, but it should not be used as an argument to another macro, in which case {(args)} would not be evaluated and would therefore have the wrong contents in the new macro environment. *newlisp-function-array* *nl-array* FUNCTION: array~ {syntax:} (array {int-n1} [{int-n2} ... ] [{list-init}]) Creates an array with {int-n1} elements, optionally initializing it with the contents of {list-init}. Up to sixteen dimensions may be specified for multidimensional arrays. Internally, newLISP builds multidimensional arrays by using arrays as the elements of an array. newLISP arrays should be used whenever random indexing into a large list becomes too slow. Not all list functions may be used on arrays. For a more detailed discussion, see the chapter on |nl-arrays|. > (array 5) ;→ (nil nil nil nil nil) (array 5 (sequence 1 5)) ;→ (1 2 3 4 5) (array 10 '(1 2)) ;→ (1 2 1 2 1 2 1 2 1 2) < Arrays can be initialized with objects of any type. If fewer initializers than elements are provided, the list is repeated until all elements of the array are initialized. > (set 'myarray (array 3 4 (sequence 1 12))) ;→ ((1 2 3 4) (5 6 7 8) (9 10 11 12)) < Arrays are modified and accessed using most of the same functions used for modifying lists: ----------------------------------------------------- (setf (myarray 2 3) 99) → 99) myarray → ((1 2 3 4) (5 6 7 8) (9 10 11 99)) (setf (myarray 1 1) "hello") → "hello" myarray → ((1 2 3 4) (5 "hello" 7 8) (9 10 11 99)) (setf (myarray 1) '(a b c d)) → (a b c d) myarray → ((1 2 3 4) (a b c d) (9 10 11 99)) (nth 1 myarray) → (a b c d) ; access a whole row (myarray 0 -1) → 4 ;; use implicit indexing and slicing on arrays (myarray 1) → (a b c d) (myarray 0 -1) → 4 (2 myarray) → (c d) (-3 2 myarray) → (b c) ----------------------------------------------------- Care must be taken to use an array when replacing a whole row. |nl-array-list| can be used to convert arrays back into lists: > (array-list myarray) ;→ ((1 2 3 4) (a b c d) (1 2 3 99)) < To convert a list back into an array, apply |nl-flat| to the list: > (set 'aList '((1 2) (3 4))) ;→ ((1 2) (3 4)) (set 'aArray (array 2 2 (flat aList))) ;→ ((1 2) (3 4)) < The |nl-array?| function can be used to check if an expression is an array: > (array? myarray) ;→ true (array? (array-list myarray)) ;→ nil < When serializing arrays using the function |nl-source| or |nl-save|, the generated code includes the |nl-array| statement necessary to create them. This way, variables containing arrays are correctly serialized when saving with |nl-save| or creating source strings using |nl-source|. > (set 'myarray (array 3 4 (sequence 1 12))) (save "array.lsp" 'myarray) ;; contents of file arraylsp ;; (set 'myarray (array 3 4 (flat '( (1 2 3 4) (5 6 7 8) (9 10 11 12))))) < *newlisp-function-array-list* *nl-array-list* FUNCTION: array-list~ {syntax:} (array-list {array}) Returns a list conversion from {array}, leaving the original array unchanged: > (set 'myarray (array 3 4 (sequence 1 12))) ;→ ((1 2 3 4) (5 6 7 8) (9 10 11 12)) (set 'mylist (array-list myarray)) ;→ ((1 2 3 4) (5 6 7 8) (9 10 11 12)) (list (array? myarray) (list? mylist)) ;→ (true true) < *newlisp-function-array?* *nl-array?* FUNCTION: array?~ {syntax:} (array? {exp}) Checks if {exp} is an array: > (set 'M (array 3 4 (sequence 1 4))) ;→ ((1 2 3 4) (1 2 3 4) (1 2 3 4))) (array? M) ;→ true (array? (array-list M)) ;→ nil < *newlisp-function-asin* *nl-asin* FUNCTION: asin~ {syntax:} (asin {num-radians}) Calculates the arcsine function from the number in {num-radians} and returns the result. > (asin 1) ;→ 1.570796327 (sin (asin 1)) ;→ 1 < *newlisp-function-asinh* *nl-asinh* FUNCTION: asinh~ {syntax:} (asinh {num-radians}) Calculates the inverse hyperbolic sine of {num-radians}, the value whose hyperbolic sine is {num-radians}. > (asinh 2) ;→ 1.443635475 (sinh (asinh 2)) ;→ 2 < *newlisp-function-assoc* *nl-assoc* FUNCTION: assoc~ {syntax:} (assoc {exp-key} {list-alist}) + {syntax:} (assoc {list-exp-key} {list-alist}) In the first syntax the value of {exp-key} is used to search {list-alist} for a {member-list} whose first element matches the key value. If found, the {member-list} is returned; otherwise, the result will be {nil}. > (assoc 1 '((3 4) (1 2))) ;→ (1 2) (set 'data '((apples 123) (bananas 123 45) (pears 7))) (assoc 'bananas data) ;→ (bananas 123 45) (assoc 'oranges data) ;→ nil < Together with |nl-setf| |nl-assoc| can be used to change an association. > (setf (assoc 'pears data) '(pears 8)) data ;→ ((apples 123) (bananas 123 45) (pears 8)) < In the second syntax more then one key expressions can be specified to search in nested, multilevel association lists: > (set 'persons '( (id001 (name "Anne") (address (country "USA") (city "New York"))) (id002 (name "Jean") (address (country "France") (city "Paris"))) )) (assoc '(id001 address) persons) ;→ (address (country "USA") (city "New York")) (assoc '(id001 address city) persons) ;→ (city "New York") < The list in {list-aList} can be a context which will be interpreted as its {default functor}. This way very big lists can be passed by reference for speedier access and less memory usage: > (set 'persons:persons '( (id001 (name "Anne") (address (country "USA") (city "New York"))) (id002 (name "Jean") (address (country "France") (city "Paris"))) )) (define (get-city db id) (last (assoc (list id 'address 'city) db )) ) (get-city persons 'id001) ;→ "New York" < For making replacements in association lists, use the |nl-setf| together with the |nl-assoc| function. The |nl-lookup| function is used to perform association lookup and element extraction in one step. *newlisp-function-atan* *nl-atan* FUNCTION: atan~ {syntax:} (atan {num-radians}) The arctangent of {num-radians} is calculated and returned. > (atan 1) ;→ 0.7853981634 (tan (atan 1)) ;→ 1 < *newlisp-function-atan2* *nl-atan2* FUNCTION: atan2~ {syntax:} (atan2 {num-Y-radians} {num-X-radians}) The |nl-atan2| function computes the principal value of the arctangent of Y / X in radians. It uses the signs of both arguments to determine the quadrant of the return value. |nl-atan2| is useful for converting Cartesian coordinates into polar coordinates. > (atan2 1 1) ;→ 0.7853981634 (div (acos 0) (atan2 1 1)) ;→ 2 (atan2 0 -1) ;→ 3.141592654 (= (atan2 1 2) (atan (div 1 2))) ;→ true < *newlisp-function-atanh* *nl-atanh* FUNCTION: atanh~ {syntax:} (atanh {num-radians}) Calculates the inverse hyperbolic tangent of {num-radians}, the value whose hyperbolic tangent is {num-radians}. If the absolute value of {num-radians} is greater than 1, |nl-atanh| returns {NaN}; if it is equal to 1, |nl-atanh| returns infinity. > (atanh 0.5) ;→ 0.5493061443 (tanh (atanh 0.5)) ;→ 0.5 (atanh 1.1) ;→ NaN (atanh 1) ;→ inf < *newlisp-function-atom?* *nl-atom?* FUNCTION: atom?~ {syntax:} (atom? {exp}) Returns {true} if the value of {exp} is an atom, otherwise {nil}. An expression is an atom if it evaluates to nil, true, an integer, a float, a string, a symbol or a primitive. Lists, lambda or lambda-macro expressions, and quoted expressions are not atoms. > (atom? '(1 2 3)) ;→ nil (and (atom? 123) (atom? "hello") (atom? 'foo)) ;→ true (atom? ''foo) ;→ nil < *newlisp-function-base64-dec* *nl-base64-dec* FUNCTION: base64-dec~ {syntax:} (base64-dec {str}) The BASE64 string in {str} is decoded. Note that {str} is not verified to be a valid BASE64 string. The decoded string is returned. > (base64-dec "SGVsbG8gV29ybGQ=") ;→ "Hello World" < For encoding, use the |nl-base64-enc| function. newLISP's BASE64 handling is derived from routines found in the Unix http://curl.haxx.se/[curl] utility and conforms to the RFC 4648 standard. *newlisp-function-base64-enc* *nl-base64-enc* FUNCTION: base64-enc~ {syntax:} (base64-enc {str} [{bool-flag}]) The string in {str} is encoded into BASE64 format. This format encodes groups of 3 * 8 = 24 input bits into 4 * 8 = 32 output bits, where each 8-bit output group represents 6 bits from the input string. The 6 bits are encoded into 64 possibilities from the letters A–Z and a–z; the numbers 0–9; and the characters + (plus sign) and / (slash). The = (equals sign) is used as a filler in unused 3- to 4-byte translations. This function is helpful for converting binary content into printable characters. Without the optional {bool-flag} parameter the empty string {""} is encoded into {"===="}. If {bool-flag} evaluates to {true}, the the empty string {""} is translated into {""}. Both translations result in {""} when using link:base64-dec[base64-dec]. The encoded string is returned. BASE64 encoding is used with many Internet protocols to encode binary data for inclusion in text-based messages (e.g., XML-RPC). > (base64-enc "Hello World") ;→ "SGVsbG8gV29ybGQ=" (base64-enc "") ;→ "====" (base64-enc "" true) ;→ "" < Note that |nl-base64-enc| does not insert carriage-return/line-feed pairs in longer BASE64 sequences but instead returns a pure BASE64-encoded string. For decoding, use the |nl-base64-dec| function. newLISP's BASE64 handling is derived from routines found in the Unix http://curl.haxx.se/[curl] utility and conforms to the RFC 4648 standard. *newlisp-function-bayes-query* *nl-bayes-query* FUNCTION: bayes-query~ {syntax:} (bayes-query {list-L} {context-D} [{bool-chain} [{bool-probs}]]) Takes a list of tokens ({list-L}) and a trained dictionary ({context-D}) and returns a list of the combined probabilities of the tokens in one category ({A} or {Mc}) versus a category ({B}) against all other categories ({Mi}). All tokens in {list-L} should occur in {context-D}. When using the default {R.A. Fisher Chi²} mode, nonexistent tokens will skew results toward equal probability in all categories. Non-existing tokens will not have any influence on the result when using the true {Chain Bayesian} mode with {bool-chain} set to {true}. The optional last flag, {bool-probs}, indicates whether frequencies or probability values are used in the data set. The |nl-bayes-train| function is typically used to generate a data set's frequencies. Tokens can be strings or symbols. If strings are used, they are prepended with an underscore before being looked up in {context-D}. If |nl-bayes-train| was used to generate {context-D}'s frequencies, the underscore was automatically prepended during the learning process. Depending on the flag specified in {bool-probs}, |nl-bayes-query| employs either the R. A. Fisher Chi² method of compounding probabilities or the Chain Bayesian method. By default, when no flag or {nil} is specified in {bool-probs}, the {Chi²} method of compounding probabilities is used. When specifying {true} in {bool-probs}, the Chain Bayesian method is used. If the R.A. Fisher Chi² method is used, the total number of tokens in the different training set's categories should be equal or similar. Uneven frequencies in categories will skew the results. For two categories {A} and {B}, |nl-bayes-query| uses the following formula: *{p(A|tkn) = p(tkn|A) * p(A) / p(tkn|A) * p(A) + p(tkn|B) * p(B)}* For {N} categories, this formula is used: *{p(Mc|tkn) = p(tkn|Mc) * p(Mc) / sum-i-N( p(tkn|Mi) * p(Mi) )}* The probabilities ({p(Mi)} or {p(A)}, along with {p(B)}) represent the {Bayesian prior probabilities}. {p(Mc|tkn)} and {p(A|tkn)} are the {posterior Bayesian} probabilities of a category or model. Priors are handled differently, depending on whether the R.A. Fisher Chi² or the Chain Bayesian method is used. In Chain Bayesian mode, posteriors from one token calculation get the priors in the next calculation. In the default R.A. Fisher method, priors are not passed on via chaining, but probabilities are compounded using the Chi² method. In Chain Bayes mode, tokens with zero frequency in one category will effectively put the probability of that category to 0 (zero). This also causes all posterior priors to be set to 0 and the category to be completely suppressed in the result. Queries resulting in zero probabilities for all categories yield {NaN} values. The default R.A. Fisher Chi² method is less sensitive about zero frequencies and still maintains a low probability for that token. This may be an important feature in natural language processing when using {Bayesian statistics}. Imagine that five different language {corpus} categories have been trained, but some words occurring in one category are not present in another. When the pure Chain Bayesian method is used, a sentence could never be classified into its correct category because the zero-count of just one word token could effectively exclude it from the category to which it belongs. On the other hand, the Chain Bayesian method offers exact results for specific proportions in the data. When using Chain Bayesian mode for natural language data, all zero frequencies should be removed from the trained dictionary first. The return value of |nl-bayes-query| is a list of probability values, one for each category. Following are two examples: the first for the default R.A. Fisher mode, the second for a data set processed with the Chain Bayesian method. Previous to version 10.3.0 the list of probability values returned in Fisher Chi² mode was normalized by dividing each value by the sum of the whole list. This normalization has been dropped in version 10.3.0. R.A. Fisher Chi² method ^^^^^^^^^^^^^^^^^^^^^^^ In the following example, the two data sets are books from Project Gutenberg. We assume that different authors use certain words with different frequencies and want to determine if a sentence is more likely to occur in one or the other author's writing. A similar method is frequently used to differentiate between spam and legitimate email. > ;; from Project Gutenberg: http://www.gutenberg.org/catalog/ ;; The Adventures of Sherlock Holmes - Sir Arthur Conan Doyle (bayes-train (parse (lower-case (read-file "Doyle.txt")) "[^a-z]+" 0) '() 'DoyleDowson) ;; A Comedy of Masks - Ernest Dowson and Arthur Moore (bayes-train '() (parse (lower-case (read-file "Dowson.txt")) "[^a-z]+" 0) 'DoyleDowson) (save "DoyleDowson.lsp" 'DoyleDowson) < The two training sets are loaded, split into tokens, and processed by the |nl-bayes-train| function. In the end, the {DoyleDowson} dictionary is saved to a file, which will be used later with the |nl-bayes-query| function. The following code illustrates how |nl-bayes-query| is used to classify a sentence as {Doyle} or {Dowson}: > (load "DoyleDowson.lsp") (bayes-query (parse "he was putting the last touches to a picture") 'DoyleDowson) ;→ (0.03802079132 0.9619792087) (bayes-query (parse "immense faculties and extraordinary powers of observation") 'DoyleDowson) ;→ (0.985108793 0.01489120699) < The queries correctly identify the first sentence as a {Dowson} sentence, and the second one as a {Doyle} sentence. Chain Bayesian method ^^^^^^^^^^^^^^^^^^^^^ The second example is frequently found in introductory literature on Bayesian statistics. It shows the Chain Bayesian method of using |nl-bayes-query| on the data of a previously processed data set: > (set 'Data:test-positive '(8 18)) (set 'Data:test-negative '(2 72)) (set 'Data:total '(10 90)) < A disease occurs in 10 percent of the population. A blood test developed to detect this disease produces a false positive rate of 20 percent in the healthy population and a false negative rate of 20 percent in the sick. What is the probability of a person carrying the disease after testing positive? > (bayes-query '(test-positive) Data true) ;→ (0.3076923077 0.6923076923) (bayes-query '(test-positive test-positive) Data true) ;→ (0.64 0.36) (bayes-query '(test-positive test-positive test-positive) Data true) ;→ (0.8767123288 0.1232876712) < Note that the Bayesian formulas used assume statistical independence of events for the |nl-bayes-query| to work correctly. The example shows that a person must test positive several times before they can be confidently classified as sick. Calculating the same example using the R.A. Fisher Chi² method will give less-distinguished results. Specifying probabilities instead of counts ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Often, data is already available as probability values and would require additional work to reverse them into frequencies. In the last example, the data were originally defined as percentages. The additional optional {bool-probs} flag allows probabilities to be entered directly and should be used together with the Chain Bayesian mode for maximum performance: > (set 'Data:test-positive '(0.8 0.2)) (set 'Data:test-negative '(0.2 0.8)) (set 'Data:total '(0.1 0.9)) (bayes-query '(test-positive) Data true true) ;→ (0.3076923077 0.6923076923) (bayes-query '(test-positive test-positive) Data true true) ;→ (0.64 0.36) (bayes-query '(test-positive test-positive test-positive) Data true true) ;→ (0.8767123288 0.1232876712) < As expected, the results are the same for probabilities as they are for frequencies. *newlisp-function-bayes-train* *nl-bayes-train* FUNCTION: bayes-train~ {syntax:} (bayes-train {list-M1} [{list-M2} ... ] {sym-context-D}) Takes one or more lists of tokens ({M1}, {M2—}) from a joint set of tokens. In newLISP, tokens can be symbols or strings (other data types are ignored). Tokens are placed in a common dictionary in {sym-context-D}, and the frequency is counted for each token in each category {Mi}. If the context does not yet exist, it must be quoted. The {M} categories represent data models for which sequences of tokens can be classified (see |nl-bayes-query|). Each token in {D} is a content-addressable symbol containing a list of the frequencies for this token within each category. String tokens are prepended with an {_} (underscore) before being converted into symbols. A symbol named {total} is created containing the total of each category. The {total} symbol cannot be part of the symbols passed as an {Mi} category. The function returns a list of token frequencies found in the different categories or models. > (bayes-train '(A A B C C) '(A B B C C C) 'L) ;→ (5 6) L:A ;→ (2 1) L:B ;→ (1 2) L:C ;→ (2 3) L:total ;→ (5 6) (bayes-train '("one" "two" "two" "three") '("three" "one" "three") '("one" "two" "three") 'S) ;→ (4 3 3) S:_one ;→ (1 1 1) S:_two ;→ (2 0 1) S:_three ;→ (1 2 1) S:total ;→ (4 3 3) < The first example shows training with two lists of symbols. The second example illustrates how an {_} is prepended when training with strings. |nl-bayes-train| creates symbols from strings prepending an underscore character. This is the same way hashes are created and contexts populates with symbols by |nl-bayes-train| can be used like hashes: > ; use a bayes-trained context namespace like a hash dictionary (S "two") ;→ (2 0 1) (S "three") ;→ (1 2 1) (S) ;→ (("one" (1 1 1)) ("three" (1 2 1)) ("two" (2 0 1))) < Note that these examples are just for demonstration purposes. In reality, training sets may contain thousands or millions of words, especially when training natural language models. But small data sets may be used when the frequency of symbols just describe already-known proportions. In this case, it may be better to describe the model data set explicitly, without the |nl-bayes-train| function: > (set 'Data:tested-positive '(8 18)) (set 'Data:tested-negative '(2 72)) (set 'Data:total '(10 90)) < The last data are from a popular example used to describe the |nl-bayes-query| function in introductory papers and books about {bayesian networks}. Training can be done in different stages by using |nl-bayes-train| on an existing trained context with the same number of categories. The new symbols will be added, then counts and totals will be correctly updated. Training in multiple batches may be necessary on big text corpora or documents that must be tokenized first. These corpora can be tokenized in small portions, then fed into |nl-bayes-train| in multiple stages. Categories can also be singularly trained by specifying an empty list for the absent corpus: > (bayes-train shakespeare1 '() 'data) (bayes-train shakespeare2 '() 'data) (bayes-train '() hemingway1 'data) (bayes-train '() hemingway2 'data) (bayes-train shakepeare-rest hemingway-rest 'data) < |nl-bayes-train| will correctly update word counts and totals. Using |nl-bayes-train| inside a context other than {MAIN} requires the training contexts to have been created previously within the {MAIN} context via the |nl-context| function. |nl-bayes-train| is not only useful with the |nl-bayes-query| function, but also as a function for counting in general. For instance, the resulting frequencies could be analyzed using |nl-prob-chi2| against a {null hypothesis} of proportional distribution of items across categories. *newlisp-function-begin* *nl-begin* FUNCTION: begin~ {syntax:} (begin {body}) The |nl-begin| function is used to group a block of expressions. The expressions in {body} are evaluated in sequence, and the value of the last expression in {body} is returned. > (begin (print "This is a block of 2 expressions\n") (print "================================")) < Some built-in functions like |nl-cond|, |nl-define|, |nl-doargs|, |nl-dolist|, |nl-dostring|, |nl-dotimes|, |nl-when| and |nl-while| already allow multiple expressions in their bodies, but |nl-begin| is often used in an |nl-if| expression. The |nl-silent| function works like |nl-begin|, but suppresses console output on return. *newlisp-function-beta* *nl-beta* FUNCTION: beta~ {syntax:} (beta {cum-a} {num-b}) The {Beta} function, |nl-beta|, is derived from the {log Gamma} |nl-gammaln| function as follows: {*beta = exp(gammaln(a) + gammaln(b) - gammaln(a + b))*} > (beta 1 2) ;→ 0.5 < *newlisp-function-betai* *nl-betai* FUNCTION: betai~ {syntax:} (betai {num-x} {num-a} {num-b}) The {Incomplete Beta} function, |nl-betai|, equals the cumulative probability of the {Beta} distribution, |nl-betai|, at {x} in {num-x}. The cumulative binomial distribution is defined as the probability of an event, {pev}, with probability {p} to occur {k} or more times in {N} trials: {*pev = Betai(p, k, N - k + 1)*} > (betai 0.5 3 8) ;→ 0.9453125 < The example calculates the probability for an event with a probability of 0.5 to occur 3 or more times in 10 trials (8 = 10 - 3 + 1). The incomplete Beta distribution can be used to derive a variety of other functions in mathematics and statistics. See also the |nl-binomial| function. *newlisp-function-bind* *nl-bind* FUNCTION: bind~ |nl-destructive| {syntax:} (bind {list-variable-associations} [{bool-eval}]) {list-variable-associations} contains an association list of symbols and their values. |nl-bind| sets all symbols to their associated values. The associated values are evaluated if the {bool-eval} flag is {true}: > (set 'lst '((a (+ 3 4)) (b "hello"))) (bind lst) ;→ "hello" a ;→ (+ 3 4) b ;→ "hello" (bind lst true) ;→ "hello" a ;→ 7 < The return value of bind is the value of the last association. |nl-bind| is often used to bind association lists returned by |nl-unify|. > (bind (unify '(p X Y a) '(p Y X X))) ;→ a X ;→ a Y ;→ a < This can be used for de-structuring: > (set 'structure '((one "two") 3 (four (x y z)))) (set 'pattern '((A B) C (D E))) (bind (unify pattern structure)) A ;→ one B ;→ "two" C ;→ 3 D ;→ four E ;→ (x y z) < |nl-unify| returns an association list and |nl-bind| binds the associations. *newlisp-function-binomial* *nl-binomial* FUNCTION: binomial~ {syntax:} (binomial {int-n} {int-k} {float-p}) The binomial distribution function is defined as the probability for an event to occur {int-k} times in {int-n} trials if that event has a probability of {float-p} and all trials are independent of one another: {*binomial = pow(p, k) * pow(1.0 - p, n - k) * n! / (k! * (n - k)!)*} where {x!} is the factorial of {x} and {pow(x, y)} is {x} raised to the power of {y}. > (binomial 10 3 0.5) ;→ 0.1171875 < The example calculates the probability for an event with a probability of 0.5 to occur 3 times in 10 trials. For a cumulated distribution, see the |nl-betai| function. *newlisp-function-bits* *nl-bits* FUNCTION: bits~ {syntax:} (bits {int} [{bool}]) Transforms a number in {int} to a string of 1's and 0's or a list, if {bool} evaluates to anything not {nil}. In string representation bits are in high to low order. In list presentation 1's and 0's are represented as {true} and {nil} and in order from the lowest to the highest bit. This allows direct indexing and program control switching on the result. > (bits 1234) ;→ "10011010010" (int (bits 1234) 0 2) ;→ 1234 (bits 1234 true) ;→ (nil true nil nil true nil true true nil nil true) ((bits 1234 true) 0) ;→ nil ; indexing of the result < |nl-int| with a base of 2 is the inverse function to |nl-bits|. *newlisp-function-callback* *nl-callback* FUNCTION: callback~ {syntax:} (callback {int-index} {sym-function}) + {syntax:} (callback {sym-function} {str-return-type} [{str}param{type} ...]) + *stntax:* (callback {sym-function}) In the first *simple |nl-callback| syntax* up to sixteen (0 to 15) {callback} functions for up to eight parameters can be registered with imported libraries. The |nl-callback| function returns a procedure address that invokes a user-defined function in {sym-function}. The following example shows the usage of callback functions when importing the http://www.opengl.org[OpenGL] graphics library: If more than sixteen callback functions are required, slots must be reassigned to a different callback function. > ... (define (draw) (glClear GL_COLOR_BUFFER_BIT ) (glRotated rotx 0.0 1.0 0.0) (glRotated roty 1.0 0.0 0.0) (glutWireTeapot 0.5) (glutSwapBuffers)) (define (keyboard key x y) (if (= (& key 0xFF) 27) (exit)) ; exit program with ESC (println "key:" (& key 0xFF) " x:" x " y:" y)) (define (mouse button state x y) (if (= state 0) (glutIdleFunc 0) ; stop rotation on button press (glutIdleFunc (callback 4 'rotation))) (println "button: " button " state:" state " x:" x " y:" y)) (glutDisplayFunc (callback 0 'draw)) (glutKeyboardFunc (callback 1 'keyboard)) (glutMouseFunc (callback 2 'mouse)) ... < The address returned by |nl-callback| is registered with the http://www.opengl.org/documentation/specs/glut/spec3/spec3.html[Glut] library. The above code is a snippet from the file {opengl-demo.lsp}, in the {examples/} directory of the source distribution of newLISP. In the second *extended |nl-callback| syntax* type specifiers are used to describe the functions return and parameter value types when the function is called. An unlimited number of callback functions can be registered with the second syntax, and return values are passed back to the calling function. The symbol in {sym-function} contains a newLISP defined function used as a callback function callable from a C program. In the third syntax |nl-callback| returns a previously returned C-callable address for that symbol. While the first simple |nl-callback| syntax only handles integers and pointer values, |nl-callback| in the expanded syntax can also handle simple and double precision floationg point numbers passed in an out of the |nl-callback| function. Both the simple and extended syntax can be mixed inside the same program. The following example shows the |nl-import| of the {qsort} C library function, which takes as one of it's arguments the address of a comparison function. The comparison function in this case is written in newLISP and called into by the imported {qsort} function: > ; C void qsort(...) takes an integer array with number and width ; of array elements and a pointer to the comparison function (import "libc.dylib" "qsort" "void" "void*" "int" "int" "void*") (set 'rlist '(2 3 1 2 4 4 3 3 0 3)) ; pack the list into an C readable 32-bit integer array (set 'carray (pack (dup "ld " 10) rlist)) ; the comparison callback function receives pointers to integers (define (cmp a b) (- (get-int a) (get-int b))) ; generate a C callable address for cmp (set 'func (callback 'cmp "int" "void*" "void*")) ; sort the carray (qsort carray 10 4 func) ; unpack the sorted array into a LISP list (unpack (dup "ld" 10) carray) ;→ (0 1 2 2 3 3 3 3 4 4) < As type specifiers the same string tags can be used as in the |nl-import| function. All pointer types are passed as numbers in and out of the |nl-callback| function. The functions |nl-get-char|, |nl-get-int|, |nl-get-long| and |nl-get-string| can be used to extract numbers of different precision from parameters. Use |nl-pack| and |nl-unpack| to extract data from binary buffers and structures. Note that newLISP as already a fast built-in |nl-sort| function. *newlisp-function-case* *nl-case* FUNCTION: case~ {syntax:} (case {exp-switch} ({exp-1} {body-1}) [({exp-2} {body-2}) ... ]) The result of evaluating {exp-switch} is compared to each of the {unevaluated} expressions {exp-1, exp-2,} —. If a match is found, the corresponding expressions in {body} are evaluated. The result of the last body expression is returned as the result for the entire |nl-case| expression. > (define (translate n) (case n (1 "one") (2 "two") (3 "three") (4 "four") (true "Can't translate this"))) (translate 3) ;→ "three" (translate 10) ;→ "Can't translate this" < The example shows how, if no match is found, the last expression in the body of a |nl-case| function can be evaluated. *newlisp-function-catch* *nl-catch* FUNCTION: catch~ {syntax:} (catch {exp}) + {syntax:} (catch {exp} {symbol}) In the first syntax, |nl-catch| will return the result of the evaluation of {exp} or the evaluated argument of a |nl-throw| executed during the evaluation of {exp}: > (catch (dotimes (x 1000) (if (= x 500) (throw x)))) ;→ 500 < This form is useful for breaking out of iteration loops and for forcing an early return from a function or expression block: > (define (foo x) … (if condition (throw 123)) … 456) ;; if condition is true (catch (foo p)) ;→ 123 ;; if condition is not true (catch (foo p)) ;→ 456 < In the second syntax, |nl-catch| evaluates the expression {exp}, stores the result in {symbol}, and returns {true}. If an error occurs during evaluation, |nl-catch| returns {nil} and stores the error message in {symbol}. This form can be useful when errors are expected as a normal potential outcome of a function and are dealt with during program execution. > (catch (func 3 4) 'result) ;→ nil result ;→ "ERR: invalid function in function catch : (func 3 4)" (constant 'func +) ;→ + <4068A6> (catch (func 3 4) 'result) ;→ true result ;→ 7 < When a |nl-throw| is executed during the evaluation of {exp}, |nl-catch| will return {true}, and the |nl-throw| argument will be stored in {symbol}: > (catch (dotimes (x 100) (if (= x 50) (throw "fin")) 'result) ;→ true result ;→ "fin" < As well as being used for early returns from functions and for breaking out of iteration loops (as in the first syntax), the second syntax of |nl-catch| can also be used to catch errors. The |nl-throw-error| function may be used to throw user-defined errors. *newlisp-function-ceil* *nl-ceil* FUNCTION: ceil~ {syntax:} (ceil {number}) Returns the next highest integer above {number} as a floating point. > (ceil -1.5) ;→ -1 (ceil 3.4) ;→ 4 < See also the |nl-floor| function. *newlisp-function-change-dir* *nl-change-dir* FUNCTION: change-dir~ {syntax:} (change-dir {str-path}) Changes the current directory to be the one given in {str-path}. If successful, {true} is returned; otherwise {nil} is returned. > (change-dir "/etc") < Makes {/etc} the current directory. *newlisp-function-char* *nl-char* FUNCTION: char~ |nl-utf8_capable| {syntax:} (char {str} [{int-index} [true]]) + {syntax:} (char {int}) Given a string argument, extracts the character at {int-index} from {str}, returning either the ASCII value of that character or the Unicode value on UTF-8 enabled versions of newLISP. If {int-index} is omitted, 0 (zero) is assumed. If {int-idx} is followed by a boolean {true} value, than the index treats {str} as an 8-bit byte array instead of an array of multi-byte UTF-8 characters. The empty string returns {nil}. Both {(char 0)} and {(char nil)} will return {"\000"}. See |nl-Indexing elements of strings and lists|. Given an integer argument, |nl-char| returns a string containing the ASCII character with value {int}. On UTF-8–enabled versions of newLISP, the value in {int} is taken as Unicode and a UTF-8 character is returned. > (char "ABC") ;→ 65 ; ASCII code for "A" (char "ABC" 1) ;→ 66 ; ASCII code for "B" (char "ABC" -1) ;→ 67 ; ASCII code for "C" (char "B") ;→ 66 ; ASCII code for "B" (char "Ω") ;→ 937 ; UTF-8 code for "Ω" (char "Ω" 1 true) ;→ 169 ; byte value at offset 1 (char 65) ;→ "A" (char 66) ;→ "B" (char (char 65)) ;→ 65 ; two inverse applications (map char (sequence 1 255)) ; returns current character set ; The Zen of UTF-8 (char (& (char "生") (char "死"))) ;→ 愛 ; by @kosh_bot < *newlisp-function-chop* *nl-chop* FUNCTION: chop~ |nl-utf8_capable| {syntax:} (chop {str} [{int-chars}]) + {syntax:} (chop {list} [{int-elements}]) If the first argument evaluates to a string, |nl-chop| returns a copy of {str} with the last {int-char} characters omitted. If the {int-char} argument is absent, one character is omitted. |nl-chop| does not alter {str}. If the first argument evaluates to a list, a copy of {list} is returned with {int-elements} omitted (same as for strings). > (set 'str "newLISP") ;→ "newLISP" (chop str) ;→ "newLIS" (chop str 2) ;→ "newLI" str ;→ "newLISP" (set 'lst '(a b (c d) e)) (chop lst) ;→ (a b (c d)) (chop lst 2) ;→ (a b) lst ;→ (a b (c d) e) < *newlisp-function-clean* *nl-clean* FUNCTION: clean~ {syntax:} (clean {exp-predicate} {list}) The predicate {exp-predicate} is applied to each element of {list}. In the returned list, all elements for which {exp-predicate} is {true} are eliminated. |nl-clean| works like |nl-filter| with a negated predicate. > (clean symbol? '(1 2 d 4 f g 5 h)) ;→ (1 2 4 5) (filter symbol? '(1 2 d 4 f g 5 h)) ;→ (d f g h) (define (big? x) (> x 5)) ;→ (lambda (x) (> x 5)) (clean big? '(1 10 3 6 4 5 11)) ;→ (1 3 4 5) (clean <= '(3 4 -6 0 2 -3 0)) ;→ (3 4 2) (clean (curry match '(a *)) '((a 10) (b 5) (a 3) (c 8) (a 9))) ;→ ((b 5) (c 8)) < The predicate may be a built-in predicate or a user-defined function or lambda expression. For cleaning numbers from one list using numbers from another, use |nl-difference| or |nl-intersect| (with the list mode option). See also the related function |nl-index|, which returns the indices of the remaining elements, and |nl-filter|, which returns all elements for which a predicate returns true. *newlisp-function-close* *nl-close* FUNCTION: close~ {syntax:} (close {int-file}) Closes the file specified by the file handle in {int-file}. The handle would have been obtained from a previous |nl-open| operation. If successful, |nl-close| returns {true}; otherwise {nil} is returned. > (close (device)) ;→ true (close 7) ;→ true (close aHandle) ;→ true < Note that using |nl-close| on |nl-device| automatically resets it to 0 (zero, the screen device). *newlisp-function-command-event* *nl-command-event* FUNCTION: command-event~ {syntax:} (command-event {sym-event-handler} | {func-event-handler}) Specifies a user defined function for pre-processing the newLISP command-line before it gets evaluated. This can be used to write customized interactive newLISP shells and to transform HTTP requests when running in server mode. |nl-command-event| takes either a symbol of a user-defined function or a lambda function. The event-handler function must return a string or the command-line will be passed untranslated to newLISP. To only force a prompt, the function should return the empty string {""}. The following example makes the newLISP shell work like a normal Unix shell when the command starts with a letter. But starting the line with an open parenthesis or a space initiates a newLISP evaluation. > (command-event (fn (s) (if (starts-with s "[a-zA-Z]" 0) (append "!" s) s))) < See also the related |nl-prompt-event| which can be used for further customizing interactive mode by modifying the newLISP prompt. The following program can be used either stand-alone or included in newLISP's {init.lsp} startup file: > #!/usr/bin/newlisp ; set the prompt to the current directory name (prompt-event (fn (ctx) (append (real-path) "> "))) ; pre-process the command-line (command-event (fn (s) (if (starts-with s "cd") (string " " (true? (change-dir (last (parse s " "))))) (starts-with s "[a-zA-Z]" 0) (append "!" s) true s))) < In the definition of the command-line translation function the Unix command {cd} gets a special treatment, to make sure that the directory is changed for newLISP process too. This way when shelling out with |nl-!| and coming back, newLISP will maintain the changed directory. Command lines for newLISP must start either with a space or an opening parenthesis. Unix commands must start at the beginning of the line. When newLISP is running in server mode either using the {-c} or {-http} option, it receives HTTP requests similar to the following: --------------- GET /index.html --------------- Or if a query is involved: ----------------------------------------- GET /index.cgi?userid=joe&password=secret ----------------------------------------- A function specified by |nl-command-event| could filter and transform these request lines, e.g.: discovering all queries trying to perform CGI using a file ending in {.exe}. Such a request would be translated into a request for an error page: > ;; httpd-conf.lsp ;; ;; filter and translate HTTP requests for newLISP ;; -c or -http server modes ;; reject query commands using CGI with .exe files (command-event (fn (s) (local (request) (if (find "?" s) ; is this a query (begin (set 'request (first (parse s "?"))) ; discover illegal extension in queries (if (ends-with request ".exe") (set 'request "GET /errorpage.html") (set 'request s))) (set 'request s)) request) )) < When starting the server mode with {newlisp httpd-conf.lsp -c -d80 -w ./httpdoc} newLISP will load the definition for |nl-command-event| for filtering incoming requests, and the query: ---------------- GET /cmd.exe?dir ---------------- Would be translated into: ------------------- GET /errorpage.html ------------------- The example shows a technique frequently used in the past by spammers on Win32 based, bad configured web servers to gain control over servers. {httpd-conf.lsp} files can easily be debugged loading the file into an interactive newLISP session and entering the HTTP requests manually. newLISP will translate the command line and dispatch it to the built-in web server. The server output will appear in the shell window. Note, that the command line length as well as the line length in HTTP headers is limited to 512 characters for newLISP. *newlisp-function-cond* *nl-cond* FUNCTION: cond~ {syntax:} (cond ({exp-condition-1} {body-1}) [({exp-condition-2} {body-2}) ... ]) Like |nl-if|, |nl-cond| conditionally evaluates the expressions within its body. The {exp-condition}s are evaluated in turn, until some {exp-condition-i} is found that evaluates to anything other than {nil} or an empty list {()}. The result of evaluating {body-i} is then returned as the result of the entire {cond-expression}. If all conditions evaluate to {nil} or an empty list, {cond} returns the value of the last {cond-expression}. > (define (classify x) (cond ((< x 0) "negative") ((< x 10) "small") ((< x 20) "medium") ((>= x 30) "big"))) (classify 15) ;→ "medium" (classify 22) ;→ "nil" (classify 100) ;→ "big" (classify -10) ;→ "negative" < When a {body-n} is missing, the value of the last {cond-expression} evaluated is returned. If no condition evaluates to {true}, the value of the last conditional expression is returned (i.e., {nil} or an empty list). > (cond ((+ 3 4))) ;→ 7 < When used with multiple arguments, the function |nl-if| behaves like |nl-cond|, except it does not need extra parentheses to enclose the condition-body pair of expressions. *newlisp-function-cons* *nl-cons* FUNCTION: cons~ {syntax:} (cons {exp-1} {exp-2}) If {exp-2} evaluates to a list, then a list is returned with the result of evaluating {exp-1} inserted as the first element. If {exp-2}evaluates to anything other than a list, the results of evaluating {exp-1} and {exp-2} are returned in a list. Note that there is no {dotted pair} in newLISP: {cons}ing two atoms constructs a list, not a dotted pair. > (cons 'a 'b) ;→ (a b) (cons 'a '(b c)) ;→ (a b c) (cons (+ 3 4) (* 5 5)) ;→ (7 25) (cons '(1 2) '(3 4)) ;→ ((1 2) 3 4) (cons nil 1) ;→ (nil 1) (cons 1 nil) ;→ (1 nil) (cons 1) ;→ (1) (cons) ;→ () < Unlike other Lisps that return {(s)} as the result of the expression {(cons 's nil)}, newLISP's |nl-cons| returns {(s nil)}. In newLISP, {nil} is a Boolean value and is not equivalent to an empty list, and a newLISP cell holds only one value. |nl-cons| behaves like the inverse operation of |nl-first| and |nl-rest| (or |nl-first| and |nl-last| if the list is a pair): > (cons (first '(a b c)) (rest '(a b c))) ;→ (a b c) (cons (first '(x y)) (last '(x y))) ;→ (x y) < *newlisp-function-constant* *nl-constant* FUNCTION: constant~ |nl-destructive| {syntax:} (constant {sym-1} {exp-1} [{sym-2} {exp-2}] ...) Identical to |nl-set| in functionality, |nl-constant| further protects the symbols from subsequent modification. A symbol set with |nl-constant| can only be modified using the |nl-constant| function again. When an attempt is made to modify the contents of a symbol protected with |nl-constant|, newLISP generates an error message. Only symbols from the current context can be used with |nl-constant|. This prevents the overwriting of symbols that have been protected in their home context. The last {exp-n} initializer is always optional. Symbols initialized with |nl-set|, |nl-define|, or |nl-define-macro| can still be protected by using the |nl-constant| function: > (constant 'aVar 123) ;→ 123 (set 'aVar 999) ERR: symbol is protected in function set: aVar (define (double x) (+ x x)) (constant 'double) ;; equivalent to (constant 'double (fn (x) (+ x x))) < The first example defines a constant, {aVar}, which can only be changed by using another |nl-constant| statement. The second example protects {double} from being changed (except by |nl-constant|). Because a function definition in newLISP is equivalent to an assignment of a lambda function, both steps can be collapsed into one, as shown in the last statement line. This could be an important technique for avoiding protection errors when a file is loaded multiple times. The last value to be assigned can be omitted. |nl-constant| returns the contents of the last symbol set and protected. Built-in functions can be assigned to symbols or to the names of other built-in functions, effectively redefining them as different functions. There is no performance loss when renaming functions. > (constant 'squareroot sqrt) ;→ sqrt <406C2E> (constant '+ add) ;→ add <4068A6> < {squareroot} will behave like |nl-sqrt|. The |nl-+| (plus sign) is redefined to use the mixed type floating point mode of |nl-add|. The hexadecimal number displayed in the result is the binary address of the built-in function and varies on different platforms and OSes. *newlisp-function-context* *nl-context* FUNCTION: context~ {syntax:} (context [{sym-context}]) + {syntax:} (context {sym-context} {str | sym} [{exp-value}]) In the first syntax, |nl-context| is used to switch to a different context namespace. Subsequent |nl-load|s of newLISP source or functions like |nl-eval-string| and |nl-sym| will put newly created symbols and function definitions in the new context. If the context still needs to be created, the symbol for the new context should be specified. When no argument is passed to |nl-context|, then the symbol for the current context is returned. Because contexts evaluate to themselves, a quote is not necessary to switch to a different context if that context already exists. > (context 'GRAPH) ; create / switch context GRAPH (define (foo-draw x y z) ; function resides in GRAPH (…)) (set 'var 12345) (symbols) ;→ (foo-draw var) ; GRAPH has now two symbols (context MAIN) ; switch back to MAIN (quote not required) (print GRAPH:var) ;→ 12345 ; contents of symbol in GRAPH (GRAPH:foo-draw 10 20 30) ; execute function in GRAPH (set 'GRAPH:var 6789) ; assign to a symbol in GRAPH < If a context symbol is referred to before the context exists, the context will be created implicitly. > (set 'person:age 0) ; no need to create context first (set 'person:address "") ; useful for quickly defining data structures < Contexts can be copied: > (new person 'JohnDoe) ;→ JohnDoe (set 'JohnDoe:age 99) < Contexts can be referred to by a variable: > (set 'human JohnDoe) human:age ;→ 99 (set 'human:address "1 Main Street") JohnDoe:address ;→ "1 Main Street" < An evaluated context (no quote) can be given as an argument: > > (context 'FOO) FOO FOO> (context MAIN) MAIN > (set 'old FOO) FOO > (context 'BAR) BAR BAR> (context MAIN:old) FOO FOO> < If an identifier with the same symbol already exists, it is redefined to be a context. Symbols within the current context are referred to simply by their names, as are built-in functions and special symbols like {nil} and {true}. Symbols outside the current context are referenced by prefixing the symbol name with the context name and a |nl-:| (colon). To quote a symbol in a different context, prefix the context name with a {'} (single quote). Within a given context, symbols may be created with the same name as built-in functions or context symbols in MAIN. This overwrites the symbols in MAIN when they are prefixed with a context: > (context 'CTX) (define (CTX:new var) (…)) (context 'MAIN) < {CTX:new} will overwrite new in MAIN. In the second syntax, |nl-context| can be used to create symbols in a namespace. Note that this should not be used for creating hashes or dictionaries. For a shorter, more convenient method to use namespaces as hash-like dictionaries, see the chapter link:#hash[Hash functions and dictionaries]. > ;; create a symbol and store data in it (context 'Ctx "abc" 123) ;→ 123 (context 'Ctx 'xyz 999) ;→ 999 ;; retrieve contents from symbol (context 'Ctx "abc") ;→ 123 (context 'Ctx 'xyz) ;→ 999 Ctx:abc ;→ 123 Ctx:xyz ;→ 999 < The first three statements create a symbol and store a value of any data type inside. The first statement also creates the context named {Ctx}. When a symbol is specified for the name, the name is taken from the symbol and creates a symbol with the same name in the context {Ctx}. Symbols can contain spaces or any other special characters not typically allowed in newLISP symbols being used as variable names. This second syntax of |nl-context| only creates the new symbol and returns the value contained in it. It does not switch to the new namespace. *newlisp-function-context?* *nl-context?* FUNCTION: context?~ {syntax:} (context? {exp}) + {syntax:} (context? {exp} {str-sym}) In the first syntax, {context?} is a predicate that returns {true} only if {exp} evaluates to a context; otherwise, it returns {nil}. > (context? MAIN) ;→ true (set 'x 123) (context? x) ;→ nil (set 'FOO:q "hola") ;→ "hola" (set 'ctx FOO) (context? ctx) ;→ true ; ctx contains context foo < The second syntax checks for the existence of a symbol in a context. The symbol is specified by its name string in {str-sym}. > (context? FOO "q") ;→ true (context? FOO "p") ;→ nil < Use |nl-context| to change and create namespaces and to create hash symbols in contexts. *newlisp-function-copy* *nl-copy* FUNCTION: copy~ {syntax:} (copy {exp}) Make a copy from evaluating expression in {exp}. Some built-in functions are |nl-destructive|, changing the original contents of a list, array or string they are working on. With |nl-copy| their behavior can be made non-destructive. > (set 'aList '(a b c d e f)) (replace 'c (copy aList)) ;→ (a b d e f) aList ;→ (a b c d e f) (set 'str "newLISP") ;→ "newLISP" (rotate (copy str)) ;→ "PnewLIS" str ;→ "newLISP" < Using |nl-copy| the functions |nl-replace| and |nl-rotate| are prevented from changing the data. A modified version of the data is returned. *newlisp-function-copy-file* *nl-copy-file* FUNCTION: copy-file~ {syntax:} (copy-file {str-from-name} {str-to-name}) Copies a file from a path-filename given in {str-from-name} to a path-filename given in {str-to-name}. Returns {true} if the copy was successful or {nil}, if the copy was unsuccessful. > (copy-file "/home/me/newlisp/data.lsp" "/tmp/data.lsp") < *newlisp-function-corr* *nl-corr* FUNCTION: corr~ {syntax:} (corr {list-vector-X} {list-vector-Y}) Calculates the {Pearson} product-moment correlation coefficient as a measure of the linear relationship between the two variables in {list-vector-X} and {list-vector-Y}. Both lists must be of same length. |nl-corr| returns a list containing the following values: [cols="1<,10<",width="30%",options="header",] |======================================================= |name |description |r |Correlation coefficient |b0 |Regression coefficient offset |b1 |Regression coefficient slope |t |t - statistic for significance testing |df |Degrees of freedom for t |p |Two tailed probability of t under the null hyothesis |======================================================= > (set 'study-time '(90 100 130 150 180 200 220 300 350 400)) (set 'test-errors '(25 28 20 20 15 12 13 10 8 6)) (corr study-time test-errors) ;→ (-0.926 29.241 -0.064 -6.944 8 0.0001190) < The negative correlation of {-0.926} between study time and test errors is highly signficant with a two-tailed {p} of about {0.0001} under the null hypothesis. The regression coefficients {b0 = 29.241} and {b1 = -0.064} can be used to estimate values of the Y variable (test errors) from values in X (study time) using the equation {Y = b0 + b1 * X}. *newlisp-function-cos* *nl-cos* FUNCTION: cos~ {syntax:} (cos {num-radians}) Calculates the cosine of {num-radians} and returns the result. > (cos 1) ;→ 0.5403023059 (set 'pi (mul 2 (acos 0))) ;→ 3.141592654 (cos pi) ;→ -1 < *newlisp-function-cosh* *nl-cosh* FUNCTION: cosh~ {syntax:} (cosh {num-radians}) Calculates the hyperbolic cosine of {num-radians}. The hyperbolic cosine is defined mathematically as: {(exp (x) + exp (-x)) / 2}. An overflow to {inf} may occur if {num-radians} is too large. > (cosh 1) ;→ 1.543080635 (cosh 10) ;→ 11013.23292 (cosh 1000) ;→ inf (= (cosh 1) (div (add (exp 1) (exp -1)) 2)) ;→ true < *newlisp-function-count* *nl-count* FUNCTION: count~ {syntax:} (count {list-1} {list-2}) Counts elements of {list-1} in {list-2} and returns a list of those counts. > (count '(1 2 3) '(3 2 1 4 2 3 1 1 2 2)) ;→ (3 4 2) (count '(z a) '(z d z b a z y a)) ;→ (3 2) (set 'lst (explode (read-file "myFile.txt"))) (set 'letter-counts (count (unique lst) lst)) < The second example counts all occurrences of different letters in {myFile.txt}. The first list in |nl-count|, which specifies the items to be counted in the second list, should be unique. For items that are not unique, only the first instance will carry a count; all other instances will display {0} (zero). *newlisp-function-cpymem* *nl-cpymem* FUNCTION: cpymem~ {syntax:} (cpymem {int-from-address} {int-to-address} {int-bytes}) Copies {int-bytes} of memory from {int-from-address} to {int-to-address}. This function can be used for direct memory writing/reading or for hacking newLISP internals (e.g., type bits in newLISP cells, or building functions with binary executable code on the fly). Note that this function should only be used when familiar with newLISP internals. |nl-cpymem| can crash the system or make it unstable if used incorrectly. > (cpymem (pack "c c" 0 32) (last (dump 'sym)) 2) (set 's "0123456789") (cpymem "xxx" (+ (address s) 5) 3) s ;→ "01234xxx89") < The first example would remove the protection bit in symbol |nl-sym|. The second example copies a string directly into a string variable. The following example creates a new function from scratch, runs a piece of binary code, and adds up two numbers. This assembly language snippet shows the x86 (Intel CPU) code to add up two numbers and return the result: > 55 push ebp 8B EC mov ebp, esp 8B 45 08 mov eax, [ebp+08] 03 45 0C add eax, [ebp+0c] 5D pop ebp C3 ret ; for Win32/stdcall change last line C2 08 00 ret < The binary representation is attached to a new function created in newLISP: > (set 'foo-code (append (pack "bbbbbbbbbb" 0x55 0x8B 0xEC 0x8B 0x45 0x08 0x03 0x45 0x0C 0x5D) (if (= ostype "Win32") (pack "bbb" 0xC2 0x08 0x00) (pack "b" 0xC3)))) (set 'foo print) (cpymem (pack "ld" (if (= ostype "Win32") 2312 1288)) (first (dump foo)) 4) (cpymem (pack "ld" (address foo-code)) (+ (first (dump foo)) 12) 4) (set 'foo-name "foo") (cpymem (pack "ld" foo-name) (+ (first (dump foo)) 8) 4) (foo 3 4) ;→ 7 < The last example will not work on all hardware platforms and OSs. Use the |nl-dump| function to retrieve binary addresses and the contents from newLISP cells. *newlisp-function-crc32* *nl-crc32* FUNCTION: crc32~ {syntax:} (crc32 {str-data}) Calculates a running 32-bit CRC (Circular Redundancy Check) sum from the buffer in {str-data}, starting with a CRC of {0xffffffff} for the first byte. |nl-crc32| uses an algorithm published by http://www.w3.org[www.w3.org]. > (crc32 "abcdefghijklmnopqrstuvwxyz") ;→ 1277644989 < |nl-crc32| is often used to verify data integrity in unsafe data transmissions. *newlisp-function-crit-chi2* *nl-crit-chi2* FUNCTION: crit-chi2~ {syntax:} (crit-chi2 {num-probability} {int-df}) Calculates the critical minimum {Chi²} for a given confidence probability {num-probability} under the null hypothesis and the degrees of freedom in {int-df} for testing the significance of a statistical null hypothesis. Note that versions prior to 10.2.0 took {(1.0 - p)} for the probability instead of {p}. > (crit-chi2 0.01 4) ;→ 13.27670443 < See also the inverse function |nl-prob-chi2|. *newlisp-function-crit-f* *nl-crit-f* FUNCTION: crit-f~ {syntax:} (crit-f {num-probability} {int-df1} {int-df2}) Calculates the critical minimum {F} for a given confidence probability {num-probability} under the null hypothesis and the degrees of freedmom given in {int-df1} and {int-df2} for testing the significance of a statistical null hypothesis using the {F-test}. > (crit-f 0.05 10 12) ;→ 2.753386727 < See also the inverse function |nl-prob-f|. *newlisp-function-crit-t* *nl-crit-t* FUNCTION: crit-t~ {syntax:} (crit-t {num-probability} {int-df}) Calculates the critical minimum {Student's t} for a given confidence probability {num-probability} under the null hypothesis and the degrees of freedom in {int-df} for testing the significance of a statistical null hypothesis. > (crit-t 0.05 14) ;→ 1.761310142 < See also the inverse function |nl-prob-t|. *newlisp-function-crit-z* *nl-crit-z* FUNCTION: crit-z~ {syntax:} (crit-z {num-probability}) Calculates the critical normal distributed Z value of a given cumulated probability {num-probability} for testing of statistical significance and confidence intervals. > (crit-z 0.999) ;→ 3.090232372 < See also the inverse function |nl-prob-z|. *newlisp-function-current-line* *nl-current-line* FUNCTION: current-line~ {syntax:} (current-line) Retrieves the contents of the last |nl-read-line| operation. |nl-current-line|'s contents are also implicitly used when |nl-write-line| is called without a string parameter. The following source shows the typical code pattern for creating a Unix command-line filter: > #!/usr/bin/newlisp (set 'inFile (open (main-args 2) "read")) (while (read-line inFile) (if (starts-with (current-line) ";;") (write-line))) (exit) < The program is invoked: > ./filter myfile.lsp < This displays all comment lines starting with {;;} from a file given as a command-line argument when invoking the script |nl-filter|. *newlisp-function-curry* *nl-curry* FUNCTION: curry~ {syntax:} (curry {func} {exp}) Transforms {func} from a function {f(x, y)} that takes two arguments into a function {fx(y)} that takes a single argument. |nl-curry| works like a macro in that it does not evaluate its arguments. Instead, they are evaluated during the application of {func}. > (set 'f (curry + 10)) ;→ (lambda ($x) (+ 10 $x)) (f 7) ;→ 17 (filter (curry match '(a *)) '((a 10) (b 5) (a 3) (c 8) (a 9))) ;→ ((a 10) (a 3) (a 9)) (clean (curry match '(a *)) '((a 10) (b 5) (a 3) (c 8) (a 9))) ;→ ((b 5) (c 8)) (map (curry list 'x) (sequence 1 5)) ;→ ((x 1) (x 2) (x 3) (x 4) (x 5)) < |nl-curry| can be used on all functions taking two arguments. *newlisp-function-date* *nl-date* FUNCTION: date~ |nl-utf8_capable| {syntax:} (date) + {syntax:} (date {int-secs} [{int-offset}]) + {syntax:} (date {int-secs} {int-offset} {str-format}) The first syntax returns the local time zone's current date and time as a string representation. If {int-secs} is out of range, {nil} is returned. In the second syntax, |nl-date| translates the number of seconds in {int-secs} into its date/time string representation for the local time zone. The number in {int-secs} is usually retrieved from the system using |nl-date-value|. Optionally, a time-zone offset (in minutes) can be specified in {int-offset}, which is added or subtracted before conversion of {int-sec} to a string. If {int-secs} is out of range or an invalid {str-format} is specified, an empty string {""} is returned. > (date) ;→ "Fri Oct 29 09:56:58 2004" (date (date-value)) ;→ "Sat May 20 11:37:15 2006" (date (date-value) 300) ;→ "Sat May 20 16:37:19 2006" ; 5 hours offset (date 0) ;→ "Wed Dec 31 16:00:00 1969" (date 0 (now 0 -2)) ;→ "Thu Jan 1 00:00:00 1970" ; Unix epoch < The way the date and time are presented in a string depends on the underlying operating system. The second example would show 1-1-1970 0:0 when in the Greenwich time zone, but it displays a time lag of 8 hours when in Pacific Standard Time (PST). |nl-date| assumes the {int-secs} given are in Coordinated Universal Time (UTC; formerly Greenwich Mean Time (GMT)) and converts it according to the local time-zone. The third syntax makes the date string fully customizable by using a format specified in {str-format}. This allows the day and month names to be translated into results appropriate for the current locale: > (set-locale "german") ;→ "de_DE" ; on Linux - no leading 0 on day with %-d (date (date-value) 0 "%A %-d. %B %Y") ;→ "Montag 7. März 2005" (set-locale "C") ; default POSIX (date (date-value) 0 "%A %B %d %Y") ;→ "Monday March 07 2005" ; suppressing leading 0 on Win32 using # (date (date-value) 0 "%a %#d %b %Y") ;→ "Mon 7 Mar 2005" (set-locale "german") (date (date-value) 0 "%x") ;→ "07.03.2005" ; day month year (set-locale "C") (date (date-value) 0 "%x") ;→ "03/07/05" ; month day year < The following table summarizes all format specifiers available on both Win32 and Linux/Unix platforms. More format options are available on Linux/Unix. For details, consult the manual page for the C function {strftime()} of the individual platform's C library. [cols="1<,10<",width="75%",options="header",] |======================================================================= |format |description |%a |abbreviated weekday name according to the current locale |%A |full weekday name according to the current locale |%b |abbreviated month name according to the current locale |%B |full month name according to the current locale |%c |preferred date and time representation for the current locale |%d |day of the month as a decimal number (range 01–31) |%H |hour as a decimal number using a 24-hour clock (range 00–23) |%I |hour as a decimal number using a 12-hour clock (range 01–12) |%j |day of the year as a decimal number (range 001–366) |%m |month as a decimal number (range 01–12) |%M |minute as a decimal number |%p |either 'am' or 'pm' according to the given time value or the corresponding strings for the current locale |%S |second as a decimal number 0–61 (60 and 61 to account for occasional leap seconds) |%U |week number of the current year as a decimal number, starting with the first Sunday as the first day of the first week |%w |day of the week as a decimal, Sunday being 0 |%W |week number of the current year as a decimal number, starting with the first Monday as the first day of the first week |%x |preferred date representation for the current locale without the time |%X |preferred time representation for the current locale without the date |%y |year as a decimal number without a century (range 00–99) |%Y |year as a decimal number including the century |%z |time zone or name or abbreviation (same as %Z on Win32, different on Unix) |%Z |time zone or name or abbreviation (same as %z on Win32, different on Unix) |%% |a literal '%' character |======================================================================= Leading zeroes in the display of decimal day numbers can be suppressed using {"%-d"} on Linux and FreeBSD and using {"%e"} on OpenBSD, SunOS/Solaris and Mac OS X. On Win32 use {"%#d"}. See also |nl-date-value|, |nl-date-list|, |nl-date-parse|, |nl-time-of-day|, |nl-time|, and |nl-now|. *newlisp-function-date-list* *nl-date-list* FUNCTION: date-list~ {syntax:} (date-list {int-seconds} [{int-index}]) Returns a list of year, month, date, hours, minutes, seconds, day of year and day of week from a time value given in seconds after January 1st, 1970 00:00:00. The date and time values aren given as UTC, which may differ from the local timezone. The week-day value ranges from 1 to 7 for Monday thru Sunday. > (date-list 1282479244) ;→ (2010 8 22 12 14 4 234 1) (date-list 1282479244 0) ;→ 2010 ; year (date-list 1282479244 -2) ;→ 234 ; day of year (apply date-value (date-list 1282479244)) ;→ 1282479244 (date-list 0) ;→ (1970 1 1 0 0 0 1 4) ; Thursday 1st, Jan 1900 < A second optional {int-index} parameter can be used to return a specific member of the list. |nl-date-list| is the inverse operation of |nl-date-value|. *newlisp-function-date-parse* *nl-date-parse* FUNCTION: date-parse~ {syntax:} (date-parse {str-date} {str-format}) Parses a date from a text string in {str-date} using a format as defined in {str-format}, which uses the same formatting rules found in |nl-date|. The function |nl-date-parse| returns the number of UTC seconds passed since January 1st, 1970 UTC starting with 0 and up to 2147472000 for a date of January 19th, 2038. For dates before January 1st 1970, negative values are returned down to a value of -2147472000 for December 14th, 1901. This function is not available on Win32 platforms. The function was named {parse-date} in previous versions. The old form is deprecated. > (date-parse "2007.1.3" "%Y.%m.%d") ;→ 1167782400 (date-parse "January 10, 07" "%B %d, %y") ;→ 1168387200 ; output of date-parse as input value to date-list produces the same date (date-list (date-parse "2010.10.18 7:00" "%Y.%m.%d %H:%M")) ;→ (2010 10 18 7 0 0 290 1) < See the |nl-date| function for all possible format descriptors. *newlisp-function-date-value* *nl-date-value* FUNCTION: date-value~ {syntax:} (date-value {int-year} {int-month} {int-day} [{int-hour} {int-min} {int-sec}]) + {syntax:} (date-value) In the first syntax, |nl-date-value| returns the time in seconds since 1970-1-1 00:00:00 for a given date and time. The parameters for the hour, minutes, and seconds are optional. The time is assumed to be Coordinated Universal Time (UTC), not adjusted for the current time zone. In the second syntax, |nl-date-value| returns the time value in seconds for the current time. > (date-value 2002 2 28) ;→ 1014854400 (date-value 1970 1 1 0 0 0) ;→ 0 (date (apply date-value (now))) ;→ "Wed May 24 10:02:47 2006" (date (date-value)) ;→ "Wed May 24 10:02:47 2006" (date) ;→ "Wed May 24 10:02:47 2006" < The function |nl-date-list| can be used to transform a |nl-date-value| back into a list: > (date-list 1014854400) ;→ (2002 2 28 0 0 0) (apply date-value (date-list 1014854400)) ;→ 1014854400 < See also |nl-date|, |nl-date-list|, |nl-date-parse|, |nl-time-of-day|, |nl-time|, and |nl-now|. *newlisp-function-debug* *nl-debug* FUNCTION: debug~ {syntax:} (debug {func}) Calls |nl-trace| and begins evaluating the user-defined function in {func}. |nl-debug| is a shortcut for executing {(trace true)}, then entering the function to be debugged. > ;; instead of doing (trace true) (my-func a b c) (trace nil) ;; use debug as a shortcut (debug (my-func a b c)) < When in |nl-debug| or |nl-trace| mode, error messages will be printed. The function causing the exception will return either {0} or {nil} and processing will continue. This way, variables and the current state of the program can still be inspected while debugging. See also the |nl-trace| function. *newlisp-function-dec* *nl-dec* FUNCTION: dec~ |nl-destructive| {syntax:} (dec {place} [{num}]) The number in {place} is decremented by {1.0} or the optional number {num} and returned. |nl-dec| performs float arithmetic and converts integer numbers passed into floating point type. {place} is either a symbol or a place in a list structure holding a number, or a number returned by an expression. > (set x 10) ;→ 10 (dec x) ;→ 9 x ;→ 9 (dec x 0.25) ;→ 8.75 x ;→ 8.75 < If the symbol for {place} contains {nil}, it is treated as if containing {0.0}: > z ;→ nil (dec z) ;→ -1 (set z nil) (dec z 0.01) ;→ -0.01 < Places in a list structure or a number returned by another expression can be updated too: > (set 'l '(1 2 3 4)) (dec (l 3) 0.1) ;→ 3.9 (dec (first l)) ;→ 0 l ;→ (0 2 3 3.9) (dec (+ 3 4)) ;→ 6 < Use the |nl---| function to decrement in integer mode. Use the |nl-inc| function to increment numbers floating point mode. *newlisp-function-def-new* *nl-def-new* FUNCTION: def-new~ {syntax:} (def-new {sym-source} [{sym-target}]) This function works similarly to |nl-new|, but it only creates a copy of one symbol and its contents from the symbol in {sym-source}. When {sym-target} is not given, a symbol with the same name is created in the current context. All symbols referenced inside {sym-source} will be translated into symbol references into the current context, which must not be MAIN. If an argument is present in {sym-target}, the copy will be made into a symbol and context as referenced by the symbol in {sym-target}. In addition to allowing renaming of the function while copying, this also enables the copy to be placed in a different context. All symbol references in {sym-source} with the same context as {sym-source} will be translated into symbol references of the target context. |nl-def-new| returns the symbol created: > > (set 'foo:var '(foo:x foo:y)) (foo:x foo:y) > (def-new 'foo:var 'ct:myvar) ct:myvar > ct:myvar (ct:x ct:y) > (context 'K) K> (def-new 'foo:var) var K> var (x y) < The following example shows how a statically scoped function can be created by moving it its own namespace: > > (set 'temp (lambda (x) (+ x x))) (lambda (x) (+ x x)) > (def-new 'temp 'double:double) double:double > (double 10) 20 > double:double (lambda (double:x) (+ double:x double:x)) < The following definition of {def-static} can be used to create functions living in their own lexically protected name-space: > (define (def-static s body) (def-new 'body (sym s s))) (def-static 'acc (lambda (x) (inc sum x))) > (acc 1) 1 > (acc 1) 2 > (acc 8) 10 > < The function |nl-def-new| can also be used to configure contexts or context objects in a more granular fashion than is possible with |nl-new|, which copies a whole context. *newlisp-function-default* *nl-default* FUNCTION: default~ {syntax:} (default {context}) Return the contents of the default functor in {context}. > (define Foo:Foo 123) (default Foo) ;→ 123 (setf (default Foo) 456) (set 'ctx Foo) (default ctx) ;→ 456 Foo:Foo ;→ 456 < In many situations newLISP defaults automatically to the default functor when seeing a context name. In circumstances where this is not the case, the |nl-default| function can be used. *newlisp-function-define* *nl-define* FUNCTION: define~ |nl-destructive| {syntax:} (define ({sym-name} [{sym-param-1} ... ]) [{body-1} ... ]) + {syntax:} (define ({sym-name} [({sym-param-1} {exp-default}) ... ]) [{body-1} ... ]) + {syntax:} (define {sym-name} {exp}) Defines the new function {sym-name}, with optional parameters {sym-param-1}—. |nl-define| is equivalent to assigning a lambda expression to {sym-name}. When calling a defined function, all arguments are evaluated and assigned to the variables in {sym-param-1}—, then the {body-1—} expressions are evaluated. When a function is defined, the lambda expression bound to {sym-name} is returned. All parameters defined are optional. When a user-defined function is called without arguments, those parameters assume the value {nil}. If those parameters have a default value specified in {exp-default}, they assume that value. The return value of |nl-define| is the assigned {lambda} expression. When calling a user-defined function, the return value is the last expression evaluated in the function body. > (define (area x y) (* x y)) ;→ (lambda (x y) (* x y)) (area 2 3) ;→ 6 < As an alternative, {area} could be defined as a function without using |nl-define|. > (set 'area (lambda (x y) (* x y)) < {lambda} or {fn} expressions may be used by themselves as {anonymous} functions without being defined as a symbol: > ((lambda ( x y) (* x y)) 2 3) ;→ 6 ((fn ( x y) (* x y)) 2 3) ;→ 6 < |nl-fn| is just a shorter form of writing {lambda}. Parameters can have default values specified: > (define (foo (a 1) (b 2)) (list a b)) (foo) ;→ (1 2) (foo 3) ;→ (3 2) (foo 3 4) ;→ (3 4) < Expressions in {exp-default} are evaluated in the function's current environment. > (define (foo (a 10) (b (div a 2))) (list a b)) (foo) ;→ (10 5) (foo 30) ;→ (30 15) (foo 3 4) ;→ (3 4) < The second version of |nl-define| works like the |nl-set| function. > (define x 123) ;→ 123 ;; is equivalent to (set 'x 123) ;→ 123 (define area (lambda ( x y) (* x y))) ;; is equivalent to (set 'area (lambda ( x y) (* x y))) ;; is equivalent to (define (area x y) (* x y)) < Trying to redefine a protected symbol will cause an error message. *newlisp-function-define-macro* *nl-define-macro* FUNCTION: define-macro~ {syntax:} (define-macro ({sym-name} [{sym-param-1} ... ]) {body}) + {syntax:} (define-macro ({sym-name} [({sym-param-1} {exp-default}) ... ]) {body}) Functions defined using |nl-define-macro| are called {fexpr}s in other LISPs as they don't do variable expansion. In newLISP they are still called macros, because they are written with the same purpose of creating special syntax forms with non-standard evaluation patterns of arguments. Functions created using |nl-define-macro| can be combined with template expansion using |nl-expand| or |nl-letex|. Defines the new fexpr {sym-name}, with optional arguments {sym-param-1}. |nl-define-macro| is equivalent to assigning a lambda-macro expression to a symbol. When a |nl-define-macro| function is called, unevaluated arguments are assigned to the variables in {sym-param-1 ...}. Then the {body} expressions are evaluated. When evaluating the |nl-define-macro| function, the lambda-macro expression is returned. > (define-macro (my-setq p1 p2) (set p1 (eval p2))) ;→ (lambda-macro (p1 p2) (set p1 (eval p2))) (my-setq x 123) ;→ 123 x ;→ 123 < New functions can be created to behave like built-in functions that delay the evaluation of certain arguments. Because fexprs can access the arguments inside a parameter list, they can be used to create flow-control functions like those already built-in to newLISP. All parameters defined are optional. When a macro is called without arguments, those parameters assume the value {nil}. If those parameters have a default value specified in {exp-default}, they assume that default value. > (define-macro (foo (a 1) (b 2)) (list a b)) (foo) ;→ (1 2) (foo 3) ;→ (3 2) (foo 3 4) ;→ (3 4) < Expressions in {exp-default} are evaluated in the function's current environment. > (define-macro (foo (a 10) (b (div a 2))) (list a b)) (foo) ;→ (10 5) (foo 30) ;→ (30 15) (foo 3 4) ;→ (3 4) < Note that in {fexprs}, the danger exists of passing a parameter with the same variable name as used in the |nl-define-macro| definition. In this case, the {fexpr's} internal variable would end up receiving {nil} instead of the intended value: > ;; not a good definition! (define-macro (my-setq x y) (set x (eval y))) ;; symbol name clash for x (my-setq x 123) ;→ 123 x ;→ nil < There are several methods that can be used to avoid this problem, known as {variable capture}, by writing {hygienic} |nl-define-macro|s: * Put the definition into its own lexically closed namespace context. If the function has the same name as the context, it can be called by using the context name alone. A function with this characteristic is called a |nl-{default function}|. This is the preferred method in newLISP to write |nl-define-macro|s. * Use |nl-args| to access arguments passed by the function. > ;; a define-macro as a lexically isolated function ;; avoiding variable capture in passed parameters (context 'my-setq) (define-macro (my-setq:my-setq x y) (set x (eval y))) (context MAIN) (my-setq x 123) ;→ 123 ; no symbol clash < The definition in the example is lexically isolated, and no variable capture can occur. Instead of the function being called using {(my-setq:my-setq …)}, it can be called with just {(my-setq …)} because it is a |nl-{default function}|. The second possibility is to refer to passed parameters using |nl-args|: > ;; avoid variable capture in macros using the args function (define-macro (my-setq) (set (args 0) (eval (args 1)))) < *newlisp-function-delete* *nl-delete* FUNCTION: delete~ {syntax:} (delete {symbol} [{bool}]) + {syntax:} (delete {sym-context} [{bool}]) Deletes a symbol {symbol}, or a context in {sym-context} with all contained symbols from newLISP's symbol table. References to the symbol will be changed to {nil}. When the expression in {bool} evaluates to {true}, symbols are only deleted when they are not referenced. When the expression in {bool} evaluates to {nil}, symbols will be deleted without any reference checking. Note that this mode should only be used, if no references to the symbol exist outside it's namespace. If external references exist, this mode can lead to system crashes, as the external reference is not set to {nil} when using this mode. This mode can be used to delete namespace hashes and to delete namespaces in object systems, where variables are strictly treated as private. Protected symbols of built-in functions and special symbols like {nil} and {true} cannot be deleted. |nl-delete| returns {true} if the symbol was deleted successfully or {nil} if the symbol was not deleted. > (set 'lst '(a b aVar c d)) (delete 'aVar) ; aVar deleted, references marked nil lst ;→ (a b nil c d) (set 'lst '(a b aVar c d)) (delete 'aVar true) ;→ nil ; protect aVar if referenced lst ;→ (a b aVar c d) ;; delete all symbols in a context (set 'foo:x 123) (set 'foo:y "hello") (delete 'foo) ;→ foo:x, foo:y deleted < In the last example only the symbols inside context {foo} will be deleted but not the context symbol {foo} itself. It will be converted to a normal unprotected symbol and contain {nil}. Note that deleting a symbol that is part of an expression which is currently executing can crash the system or have other unforeseen effects. *newlisp-function-delete-file* *nl-delete-file* FUNCTION: delete-file~ {syntax:} (delete-file {str-file-name}) Deletes a file given in {str-file-name}. Returns {true} if the file was deleted successfully. On failure the function returns {nil}. For error information, use |nl-sys-error| when used on files. When used on URLs |nl-net-error| gives more error information. The file name can be given as a URL. > (delete-file "junk") (delete-file "http://asite.com/example.html") (delete-file "file://aFile.txt") < The first example deletes the file {junk} in the current directory. The second example shows how to use a URL to specify the file. In this form, additional parameters can be given. See |nl-delete-url| for details. *newlisp-function-delete-url* *nl-delete-url* FUNCTION: delete-url~ {syntax:} (delete-file {str-url}) This function deletes the file on a remote HTTP server specified in {str-url}. The HTTP {DELETE} protocol must be enabled on the target web server, or an error message string may be returned. The target file must also have access permissions set accordingly. Additional parameters such as timeout and custom headers are available exactly as in the |nl-get-url| function. If {str-url} starts with {file://} a file on the local file system is deleted. This feature is also available when the |nl-delete-file| function is used and a URL is specified for the filename. > (delete-url "http://www.aserver.com/somefile.txt") (delete-url "http://site.org:8080/page.html" 5000) ; delete on the local file system (delete-url "file:///home/joe/somefile.txt") < The second example configures a timeout option of five seconds. Other options such as special HTTP protocol headers can be specified, as well. See the |nl-get-url| function for details. *newlisp-function-destroy* *nl-destroy* FUNCTION: destroy~ {syntax:} (destroy {int-pid}) + {syntax:} (destroy {int-pid} {int-signal}) Destroys a process with process id in {int-pid} and returns {true} on success or {nil} on failure. The process id is normally obtained from a previous call to |nl-fork| on Mac OS X and other Unix or |nl-process| on all platforms. On Unix, |nl-destroy| works like the system utility {kill} using the SIGKILL signal. CAUTION! If {int-pid} is {0} the signal is sent to all processes whose group ID is equal to the process group ID of the sender. If {int-pid} is {-1} all processes with the current user id will be killed, if newLISP is started with super user privileges, all processes except system processes are destroyed. When specifying {int-signal}, |nl-destroy| works like a Unix {kill} command sending the specified Unix signal to the process in {int-pid}. This second syntax is not available on Win32. > (set 'pid (process "/usr/bin/bc" bcin bcout)) (destroy pid) (set 'pid (fork (dotimes (i 1000) (println i) (sleep 10)))) (sleep 100) (destroy pid) < *newlisp-function-det* *nl-det* FUNCTION: det~ {syntax:} (det {matrix} [{float-pivot}]) Returns the determinant of a square matrix. A matrix can either be a nested list or an |nl-array|. Optionally {0.0} or a very small value can be specified in {float-pivot}. This value substitutes pivot elements in the LU-decomposition algorithm, which result in zero when the algorithm deals with a singular matrix. > (set 'A '((-1 1 1) (1 4 -5) (1 -2 0))) (det A) ;→ -1 ; treatment of singular matrices (det '((2 -1) (4 -2))) ;→ nil (det '((2 -1) (4 -2)) 0) ;→ -0 (det '((2 -1) (4 -2)) 1e-20) ;→ -4e-20 < If the matrix is singular and {float-pivot} is not specified, {nil} is returned. See also the other matrix operations |nl-invert|, |nl-mat|, |nl-multiply| and |nl-transpose|. *newlisp-function-device* *nl-device* FUNCTION: device~ {syntax:} (device [{int-handle}]) {int-handle} is an I/O device number, which is set to 0 (zero) for the default STD I/O pair of handles, 0 for {stdin} and 1 for {stdout}. {int-handle} may also be a file handle previously obtained using |nl-open|. In this case both, input and output are channeled through this handle. When no argument is supplied, the current I/O device number is returned. The I/O channel specified by |nl-device| is used internally by the functions |nl-print| and |nl-read-line|. When the current I/O device is 0 or 1, |nl-print| sends output to the console window and |nl-read-line| accepts input from the keyboard. If the current I/O device has been set by opening a file, then |nl-print| and |nl-read-line| work on that file. > (device (open "myfile" "write")) ;→ 5 (print "This goes in myfile") ;→ "This goes in myfile" (close (device)) ;→ true < Note that using |nl-close| on |nl-device| automatically resets |nl-device| to 0 (zero). *newlisp-function-difference* *nl-difference* FUNCTION: difference~ {syntax:} (difference {list-A} {list-B}) + {syntax:} (difference {list-A} {list-B} {bool}) In the first syntax, |nl-difference| returns the {set} difference between {list-A} and {list-B}. The resulting list only has elements occurring in {list-A}, but not in {list-B}. All elements in the resulting list are unique, but {list-A} and {list-B} need not be unique. Elements in the lists can be any type of Lisp expression. > (difference '(2 5 6 0 3 5 0 2) '(1 2 3 3 2 1)) ;→ (5 6 0) < In the second syntax, |nl-difference| works in {list} mode. {bool} specifies {true} or an expression not evaluating to {nil}. In the resulting list, all elements of {list-B} are eliminated in {list-A}, but duplicates of other elements in {list-A} are left. > (difference '(2 5 6 0 3 5 0 2) '(1 2 3 3 2 1) true) ;→ (5 6 0 5 0) < See also the set functions |nl-intersect|, |nl-unique| and |nl-union|. *newlisp-function-directory* *nl-directory* FUNCTION: directory~ {syntax:} (directory [{str-path}]) + {syntax:} (directory {str-path} {str-pattern} [{int-regex-option}]) A list of directory entry names is returned for the directory path given in {str-path}. On failure, {nil} is returned. When {str-path} is omitted, the list of entries in the current directory is returned. > (directory "/bin") (directory "c:/") < The first example returns the directory of {/bin}, the second line returns a list of directory entries in the root directory of drive C:. Note that on Win32 systems, a forward slash (|nl-/|) can be included in path names. When used, a backslash ({\}) must be preceded by a second backslash. In the second syntax, |nl-directory| can take a regular expression pattern in {str-pattern}. Only filenames matching the pattern will be returned in the list of directory entries. In {int-regex-options}, special regular expression options can be specified; see |nl-regex| for details. > (directory "." "\\.c") ;→ ("foo.c" "bar.c") ;; or using braces as string pattern delimiters (directory "." {\.c}) ;→ ("foo.c" "bar.c") ; show only hidden files (starting with dot) (directory "." "^[.]") ;→ ("." ".." ".profile" ".rnd" ".ssh") < The regular expression forces |nl-directory| to return only file names containing the string {".c"}. Other functions that use regular expressions are |nl-find|, |nl-find-all|, |nl-parse|, |nl-regex|, |nl-replace|, and |nl-search|. *newlisp-function-directory?* *nl-directory?* FUNCTION: directory?~ {syntax:} (directory? {str-path}) Checks if {str-path} is a directory. Returns {true} or {nil} depending on the outcome. > (directory? "/etc") ;→ true (directory? "/usr/bin/emacs/") ;→ nil < *newlisp-function-div* *nl-div* FUNCTION: div~ {syntax:} (div {num-1} {num-2} [{num-3} ... ]) + {syntax:} (div {num-1}) Successively divides {num-1} by the number in {num-2—}. |nl-div| can perform mixed-type arithmetic, but it always returns floating point numbers. Any floating point calculation with {NaN} also returns {NaN}. > (div 10 3) ;→ 3.333333333 (div 120 (sub 9.0 6) 100) ;→ 0.4 (div 10) ;→ 0.1 < When {num-1} is the only argument, |nl-div| calculates the inverse of {num-1}. *newlisp-function-do-until* *nl-do-until* FUNCTION: do-until~ {syntax:} (do-until {exp-condition} [{body}]) The expressions in {body} are evaluated before {exp-condition} is evaluated. If the evaluation of {exp-condition} is not {nil}, then the |nl-do-until| expression is finished; otherwise, the expressions in {body} get evaluated again. Note that |nl-do-until| evaluates the conditional expression {after} evaluating the body expressions, whereas |nl-until| checks the condition {before} evaluating the body. The return value of the |nl-do-until| expression is the last evaluation of the {body} expression. If {body} is empty, the last result of {exp-condition} is returned. |nl-do-until| also updates the system iterator symbol {$idx}. > (set 'x 1) (do-until (> x 0) (inc x)) x ;→ 2 (set 'x 1) (until (> x 0) (inc x)) x ;→ 1 < While |nl-do-until| goes through the loop at least once, |nl-until| never enters the loop. See also the functions |nl-while| and |nl-do-while|. *newlisp-function-do-while* *nl-do-while* FUNCTION: do-while~ {syntax:} (do-while {exp-condition body}) The expressions in {body} are evaluated before {exp-condition} is evaluated. If the evaluation of {exp-condition} is {nil}, then the |nl-do-while| expression is finished; otherwise the expressions in {body} get evaluated again. Note that |nl-do-while| evaluates the conditional expression {after} evaluating the body expressions, whereas |nl-while| checks the condition {before} evaluating the body. The return value of the |nl-do-while| expression is the last evaluation of the {body} expression. |nl-do-while| also updates the system iterator symbol {$idx}. > (set 'x 10) (do-while (< x 10) (inc x)) x ;→ 11 (set 'x 10) (while (< x 10) (inc x)) x ;→ 10 < While |nl-do-while| goes through the loop at least once, |nl-while| never enters the loop. See also the functions |nl-until| and |nl-do-until|. *newlisp-function-doargs* *nl-doargs* FUNCTION: doargs~ {syntax:} (doargs ({sym} [{exp-break}]){body}) Iterates through all members of the argument list inside a user-defined function or macro. This function or macro can be defined using |nl-define|, |nl-define-macro|, |nl-lambda|, or |nl-lambda-macro|. The variable in {sym} is set sequentially to all members in the argument list until the list is exhausted or an optional break expression (defined in {exp-break}) evaluates to {true} or a logical true value. The |nl-doargs| expression always returns the result of the last evaluation. |nl-doargs| also updates the system iterator symbol {$idx}. > (define (foo) (doargs (i) (println i))) > (foo 1 2 3 4) 1 2 3 4 < The optional break expression causes |nl-doargs| to interrupt processing of the arguments: > (define-macro (foo) (doargs (i (= i 'x)) (println i))) > (foo a b x c d e) a b true < Use the |nl-args| function to access the entire argument list at once. *newlisp-function-dolist* *nl-dolist* FUNCTION: dolist~ {syntax:} (dolist ({sym} {list} [{exp-break}]){body}) The expressions in {body} are evaluated for each element in {list}. The variable in {sym} is set to each of the elements before evaluation of the body expressions. The variable used as loop index is local and behaves according to the rules of dynamic scoping. Optionally, a condition for early loop exit may be defined in {exp-break}. If the break expression evaluates to any non-{nil} value, the |nl-dolist| loop returns with the value of {exp-break}. The break condition is tested before evaluating {body.} > (set 'x 123) (dolist (x '(a b c d e f g)) ; prints: abcdefg (print x)) ;→ g ; return value (dolist (x '(a b c d e f g) (= x 'e)) ; prints: abcd (print x)) ;; x is local in dolist ;; x has still its old value outside the loop x ;→ 123 ; x has still its old value < This example prints {abcdefg} in the console window. After the execution of |nl-dolist|, the value for {x} remains unchanged because the {x} in |nl-dolist| has local scope. The return value of |nl-dolist| is the result of the last evaluated expression. The internal system variable {$idx} keeps track of the current offset into the list passed to |nl-dolist|, and it can be accessed during its execution: > (dolist (x '(a b d e f g)) (println $idx ":" x)) ;→ g 0:a 1:b 2:d 3:e 4:f 5:g < The console output is shown in boldface. {$idx} is protected and cannot be changed by the user. *newlisp-function-dostring* *nl-dostring* FUNCTION: dostring~ |nl-utf8_capable| {syntax:} (dostring ({sym} {string} [{exp-break}]) {body}) The expressions in {body} are evaluated for each character in {string}. The variable in {sym} is set to each ASCII or UTF-8 integer value of the characters before evaluation of the body expressions. The variable used as loop index is local and behaves according to the rules of dynamic scoping. Optionally, a condition for early loop exit may be defined in {exp-break}. If the break expression evaluates to any non-{nil} value, the |nl-dolist| loop returns with the value of {exp-break}. The break condition is tested before evaluating {body.} > ; ASCII example (set 'str "abcdefg") (dostring (c str) (println c " - " (char c))) 97 - a 98 - b 99 - c 100 - d 101 - e 102 - f 103 - g ; UTF8 example (set 'utf8str "我能吞下玻璃而不伤身体。") (dostring (c utf8str) (println c " - " (char c))) 25105 - 我 33021 - 能 21534 - 吞 ... 20307 - 体 12290 - 。 < This example prints the value of each character in the console window. In UTF-8 enabled versions of newLISP, individual characters may be longer than one byte and the number in the loop variable may exceed 255. The return value of |nl-dostring| is the result of the last evaluated expression. The internal system variable {$idx} keeps track of the current offset into the string passed to |nl-dostring|, and it can be accessed during its execution. *newlisp-function-dotimes* *nl-dotimes* FUNCTION: dotimes~ {syntax:} (dotimes ({sym-var} {int-count} [{exp-break}]) {body}) The expressions in {body} are evaluated {int} times. The variable in {sym} is set from 0 (zero) to ({int} - 1) each time before evaluating the body expression(s). The variable used as the loop index is local to the |nl-dotimes| expression and behaves according the rules of dynamic scoping. The loop index is of integer type. |nl-dotimes| returns the result of the last expression evaluated in {body}. After evaluation of the |nl-dotimes| statement {sym} assumes its previous value. Optionally, a condition for early loop exit may be defined in {exp-break}. If the break expression evaluates to any non-{nil} value, the |nl-dotimes| loop returns with the value of {exp-break}. The break condition is tested before evaluating {body}. > (dotimes (x 10) (print x)) ;→ 9 ; return value < This prints {0123456789} to the console window. *newlisp-function-dotree* *nl-dotree* FUNCTION: dotree~ {syntax:} (dotree ({sym} {sym-context} [{bool}]) {body}) The expressions in {body} are evaluated for all symbols in {sym-context}. The symbols are accessed in a sorted order. Before each evaluation of the body expression(s), the variable in {sym} is set to the next symbol from {sym-context}. The variable used as the loop index is local to the |nl-dotree| expression and behaves according the rules of dynamic scoping. When the optional {bool} expression evaluates to not {nil}, only symbols starting with an underscore character {_} are accessed. Symbol names starting with an {_} underscore are used for |nl-hash keys| and symbols created by |nl-bayes-train|. |nl-dotree| also updates the system iterator symbol {$idx}. > ;; faster and less memory overhead (dotree (s SomeCTX) (print s " ")) ;; slower and higher memory usage (dolist (s (symbols SomeCTX)) (print s " ")) < This example prints the names of all symbols inside SomeCTX to the console window. *newlisp-function-dump* *nl-dump* FUNCTION: dump~ {syntax:} (dump [{exp}]) Shows the binary contents of a newLISP cell. Without an argument, this function outputs a listing of all Lisp cells to the console. When {exp} is given, it is evaluated and the contents of a Lisp cell are returned in a list. > (dump 'a) ;→ (9586996 5 9578692 9578692 9759280) (dump 999) ;→ (9586996 130 9578692 9578692 999) < The list contains the following memory addresses and information: [cols="1<,10<",width="40%",options="header",] |==================================================================== |offset |description |0 |memory address of the newLISP cell |1 |cell->type: major/minor type, see newlisp.h for details |2 |cell->next: linked list ptr |3 |cell->aux: + string length+1 or + low (little endian) or high (big endian) word of 64-bit integer or + low word of IEEE 754 double float |4 |cell->contents: + string/symbol address or + high (little endian) or low (big endian) word of 64-bit integer or + high word of IEEE 754 double float |==================================================================== This function is valuable for changing type bits in cells or hacking other parts of newLISP internals. See the function |nl-cpymem| for a comprehensive example. *newlisp-function-dup* *nl-dup* FUNCTION: dup~ {syntax:} (dup {exp} {int-n} [{bool}]) + {syntax:} (dup {exp}) If the expression in {exp} evaluates to a string, it will be replicated {int-n} times within a string and returned. When specifying an expression evaluating to anything other than {nil} in {bool}, the string will not be concatenated but replicated in a list like any other data type. If {exp} contains any data type other than string, the returned list will contain {int-n} evaluations of {exp}. Without the repetition parameter, |nl-dup| assumes 2. > (dup "A" 6) ;→ "AAAAAA" (dup "A" 6 true) ;→ ("A" "A" "A" "A" "A" "A") (dup "A" 0) ;→ "" (dup "AB" 5) ;→ "ABABABABAB" (dup 9 7) ;→ (9 9 9 9 9 9 9) (dup 9 0) ;→ () (dup 'x 8) ;→ (x x x x x x x x) (dup '(1 2) 3) ;→ ((1 2) (1 2) (1 2)) (dup "\000" 4) ;→ "\000\000\000\000" (dup "*") ;→ "**" < The last example shows handling of binary information, creating a string filled with four binary zeroes. See also the functions |nl-sequence| and |nl-series|. *newlisp-function-empty?* *nl-empty?* FUNCTION: empty?~ {syntax:} (empty? {exp}) + {syntax:} (empty? {str}) {exp} is tested for an empty list (or {str} for an empty string). Depending on whether the argument contains elements, {true} or {nil} is returned. > (set 'var '()) (empty? var) ;→ true (empty? '(1 2 3 4)) ;→ nil (empty? "hello") ;→ nil (empty? "") ;→ true < The first example checks a list, while the second two examples check a string. *newlisp-function-encrypt* *nl-encrypt* FUNCTION: encrypt~ {syntax:} (encrypt {str-source} {str-pad}) Performs a one-time–pad encryption of {str-source} using the encryption pad in {str-pad}. The longer {str-pad} is and the more random the bytes are, the safer the encryption. If the pad is as long as the source text, is fully random, and is used only once, then one-time–pad encryption is virtually impossible to break, since the encryption seems to contain only random data. To retrieve the original, the same function and pad are applied again to the encrypted text: > (set 'secret (encrypt "A secret message" "my secret key")) ;→ ",YS\022\006\017\023\017TM\014\022\n\012\030E" (encrypt secret "my secret key") ;→ "A secret message" < The second example encrypts a whole file: > (write-file "myfile.enc" (encrypt (read-file "myfile") "29kH67*")) < *newlisp-function-ends-with* *nl-ends-with* FUNCTION: ends-with~ {syntax:} (ends-with {str-data} {str-key} [{num-option}]) + {syntax:} (ends-with {list} {exp}) In the first syntax, |nl-ends-with| tests the string in {str-data} to see if it ends with the string specified in {str-key}. It returns {true} or {nil} depending on the outcome. If a regular expression {option} number is specified, {str-key} contains a regular expression pattern. See |nl-regex| for valid numbers for {option}. > (ends-with "newLISP" "LISP") ;→ true (ends-with "newLISP" "lisp") ;→ nil ;; use regular expressions (ends-with "newLISP" "lisp|york" 1) ;→ true < In the second syntax, |nl-ends-with| checks if a list ends with the list element in {exp}. {true} or {nil} is returned depending on outcome. > (ends-with '(1 2 3 4 5) 5) ;→ true (ends-with '(a b c d e) 'b) ;→ nil (ends-with '(a b c (+ 3 4)) '(+ 3 4)) ;→ true < The last example shows that {exp} could be a list by itself. See also the |nl-starts-with| function. *newlisp-function-env* *nl-env* FUNCTION: env~ {syntax:} (env) + {syntax:} (env {var-str}) + {syntax:} (env {var-str} {value-str}) In the first syntax (without arguments), the operating system's environment is retrieved as an association list in which each entry is a key-value pair of environment variable and value. > (env) ;→ (("PATH" "/bin:/usr/bin:/sbin") ("TERM" "xterm-color") ... )) < In the second syntax, the name of an environment variable is given in {var-str}. |nl-env| returns the value of the variable or {nil} if the variable does not exist in the environment. > (env "PATH") ;→ "/bin:/usr/bin:/usr/local/bin" < The third syntax (variable name in {var-str} and value pair in {value-str}) sets or creates an environment variable. If {value-str} is the empty string {""}, then the variable is completely removed from the environment except when running on Solaris, where the variable stays with an empty string. > (env "NEWLISPBIN" "/usr/bin/") ;→ true (env "NEWLISPBIN") ;→ "/usr/bin/" (env "NEWLISPBIN" "") ;→ true (env "NEWLISPBIN") ;→ nil < *newlisp-function-erf* *nl-erf* FUNCTION: erf~ {syntax:} (erf {num}) |nl-erf| calculates the error function of a number in {num}. The error function is defined as: *{erf (x) = 2/sqrt(pi) * integral from 0 to x of exp(-t^2) dt}* > (map erf (sequence 0.0 6.0 0.5)) ;→ (0 0.5204998778 0.8427007929 0.9661051465 0.995322265 0.999593048 0.9999779095 0.9999992569 0.9999999846 0.9999999998 1 1 1) < *newlisp-function-error-event* *nl-error-event* FUNCTION: error-event~ {syntax:} (error-event {sym-event-handler | func-event-handler}) {sym-event-handler} contains a user-defined function for handling errors. Whenever an error occurs, the system performs a |nl-reset| and executes the user-defined error handler. The error handler can use the built-in function |nl-last-error| to retrieve the number and text of the error. The event handler is specified as either a quoted symbol or a lambda function. > (define (my-handler) (print "error # " (first (last-error)) " has occurred\n") ) (error-event 'my-handler) ;→ my-handler ;; specify a function directly (error-event my-handler) ;→ $error-event (error-event (fn () (print "error # " (first (last-error)) " has occurred\n"))) (error-event exit) ;→ $error-event < For a different way of handling errors, see the |nl-catch| function. Use |nl-throw-error| to throw user-defined errors. *newlisp-function-eval* *nl-eval* FUNCTION: eval~ {syntax:} (eval {exp}) {eval} evaluates the result of evaluating {exp} in the current variable environment. > (set 'expr '(+ 3 4)) ;→ (+ 3 4) (eval expr) ;→ 7 (eval (list + 3 4)) ;→ 7 (eval ''x) ;→ x (set 'y 123) (set 'x 'y) x ;→ y (eval x) ;→ 123 < As usual, evaluation of variables happens in the current variable environment: > ; eval in global (top level) environment (set 'x 3 'y 4) (eval '(+ x y)) ;→ 7 ; eval in local environment (let ( (x 33) (y 44) ) (eval '(+ x y))) ;→ 77 ; old environment after leaving local let environment (eval '(+ x y)) ;→ 7 < newLISP passes all arguments by value. Using a quoted symbol, expressions can be passed by reference through the symbol. |nl-eval| can be used to access the original contents of the symbol: > (define (change-list aList) (push 999 (eval aList))) (set 'data '(1 2 3 4 5)) (change-list 'data) ;→ (999 1 2 3 4 5) < In the example, the parameter {'data } is quoted, so |nl-push| can work on the original list. There is a safer method to pass arguments by reference in newLISP by enclosing the data inside context objects. See the chapter |nl-Passing data by reference|. Passing references into user defined function using namespace ids avoids {variable capture} of the passed symbol, in case the symbol passed is the same used as a parameter in the function. *newlisp-function-eval-string* *nl-eval-string* FUNCTION: eval-string~ {syntax:} (eval-string {str-source} [{sym-context} [{exp-error} [{int-offset}]]]) The string in {str-source} is compiled into newLISP's internal format and then evaluated. The evaluation result is returned. If the string contains more than one expression, the result of the last evaluation is returned. An optional second argument can be used to specify the context to which the string should be parsed and translated. If an error occurs while parsing and evaluating {str-source} then {exp-error} will be evaluated and the result returned. {int-offset} specifies an optional offset into {str-source}, where to start evaluation. > (eval-string "(+ 3 4)") ;→ 7 (set 'X 123) ;→ 123 (eval-string "X") ;→ 123 (define (repl) ; read print eval loop (while true (println "=> " (eval-string (read-line) MAIN (last-error))) ) ) (set 'a 10) (set 'b 20) (set 'foo:a 11) (set 'foo:b 22) (eval-string "(+ a b)") ;→ 30 (eval-string "(+ a b)" 'foo) ;→ 33 < The second example shows a simple newLISP interpreter eval loop. The last example shows how to specify a target context for translation. The symbols {a} and {b} now refer to symbols and their values in context {foo} instead of {MAIN}. See also the function |nl-read-expr| which translates a string without evaluating it. *newlisp-function-even?* *nl-even?* FUNCTION: even?~ {syntax:} (even? {int-number}) Checks if an integer number is {even divisable} by {2}, without remainder. When a floating point number is passed for {int-number}, it will be converted to an integer by cutting off its fractional part. > (even? 123) ;→ nil (even? 8) ;→ true (even? 8.7) ;→ true < Use |nl-odd?| to check if an integer is not divisable by {2}. *newlisp-function-exec* *nl-exec* FUNCTION: exec~ {syntax:} (exec {str-process}) + {syntax:} (exec {str-process} [{str-stdin}]) In the first form, |nl-exec| launches a process described in {str-process} and returns all standard output as a list of strings (one for each line in standard out (STDOUT)). |nl-exec| returns {nil} if the process could not be launched. If the process could be launched but only returns and error and no valid output, the empty list will be returned. > (exec "ls *.c") ;→ ("newlisp.c" "nl-math.c" "nl-string.c") < The example starts a process and performs the shell command {ls}, capturing the output in an array of strings. In the second form, |nl-exec| creates a process pipe, starts the process in {str-process}, and receives from {str-stdin} standard input for this process. The return value is {true} if the process was successfully launched; otherwise it is {nil}. > (exec "cgiProc" query) < In this example, cgiProc could be a cgi processor (e.g., Perl or newLISP) that receives and processes standard input supplied by a string contained in the variable query. *newlisp-function-exists* *nl-exists* FUNCTION: exists~ {syntax:} (exists {func-condition} {list}) Successively applies {func-condition} to the elements of {list} and returns the first element that meets the condition in {func-condition}. If no element meets the condition, {nil} is returned. > (exists string? '(2 3 4 6 "hello" 7)) ;→ "hello" (exists string? '(3 4 2 -7 3 0)) ;→ nil (exists zero? '(3 4 2 -7 3 0)) ;→ 0 ; check for 0 or 0.0 (exists < '(3 4 2 -7 3 0)) ;→ -7 ; check for negative (exists (fn (x) (> x 3)) '(3 4 2 -7 3 0)) ;→ 4 (exists (fn (x) (= x 10)) '(3 4 2 -7 3 0)) ;→ nil < If {func-condition} is |nl-nil?|, the result {nil} is ambiguous. In this case |nl-index| or |nl-find| are the better method when looking for {nil}. Use the |nl-for-all| function to check if a condition is met for all elements in a list. *newlisp-function-exit* *nl-exit* FUNCTION: exit~ {syntax:} (exit [{int}]) Exits newLISP. An optional exit code, {int}, may be supplied. This code can be tested by the host operating system. When newLISP is run in |nl-daemon server mode| using {-d} as a command-line option, only the network connection is closed, while newLISP stays resident, listening for a new connection. > (exit 5) < *newlisp-function-exp* *nl-exp* FUNCTION: exp~ {syntax:} (exp {num}) The expression in {num} is evaluated, and the exponential function is calculated based on the result. |nl-exp| is the inverse function of |nl-log|. > (exp 1) ;→ 2.718281828 (exp (log 1)) ;→ 1 < *newlisp-function-expand* *nl-expand* FUNCTION: expand~ {syntax:} (expand {exp} {sym-1} [{sym-2} ... ]) + {syntax:} (expand {exp} {list-assoc} [{bool}]) + {syntax:} (expand {exp}) In the first syntax, one symbol in {sym} (or more in {sym-2} through {sym-n}) is looked up in a simple or nested expression {exp}. They are then expanded to the current binding of the symbol and the expanded expression is returned. The original list remains unchanged. > (set 'x 2 'a '(d e)) (set 'foo 'a) (expand foo 'a) ;→ (d e) (expand '(a x b) 'x) ;→ (a 2 b) (expand '(a x (b c x)) 'x) ;→ (a 2 (b c 2)) (expand '(a x (b c x)) 'x 'a) ;→ ((d e) 2 (b c 2)) < |nl-expand| is useful when composing lambda expressions or doing variable expansion inside macros. > (define (raise-to power) (expand (fn (base) (pow base power)) 'power)) (define square (raise-to 2)) (define cube (raise-to 3)) (square 5) ;→ 25 (cube 5) ;→ 125 < If more than one symbol is present, |nl-expand| will work in an incremental fashion: > (set 'a '(b c)) (set 'b 1) (expand '(a b c) 'a 'b) ;→ ((1 c) 1 c) < Like the |nl-apply| function, |nl-expand| {reduces} its argument list. {syntax:} (expand {exp} {list-assoc} [{bool}]) The second syntax of |nl-expand| allows expansion bindings to be specified on the fly, without performing a |nl-set| on the participating variables: If the {bool} evaluates to {true}, the value parts in the association list are evaluated. > (expand '(a b c) '((a 1) (b 2))) ;→ (1 2 c) (expand '(a b c) '((a 1) (b 2) (c (x y z)))) ;→ (1 2 (x y z)) (expand '(a b) '((a (+ 1 2)) (b (+ 3 4)))) ;→ ((+ 1 2) (+ 3 4)) (expand '(a b) '((a (+ 1 2)) (b (+ 3 4))) true) ;→ (3 7) < Note that the contents of the variables in the association list will not change. This is different from the |nl-letex| function, where variables are set by evaluating and assigning their association parts. This form of |nl-expand| is frequently used in logic programming, together with the |nl-unify| function. {syntax:} (expand {exp}) A third syntax is used to expand only the contents of variables starting with an uppercase character. This PROLOG mode may also be used in the context of logic programming. As in the first syntax of |nl-expand|, symbols must be preset. Only uppercase variables and those bound to anything other than {nil} will be expanded: > (set 'A 1 'Bvar 2 'C nil 'd 5 'e 6) (expand '(A (Bvar) C d e f)) ;→ (1 (2) C d e f) < Only the symbols {A} and {Bvar} are expanded because they have capitalized names and non-{nil} contents. The {currying} function in the example demonstrating the first syntax of |nl-expand| can now be written even more simply using an uppercase variable: > (define (raise-to Power) (expand (fn (base) (pow base Power)))) > (define cube (raise-to 3)) (lambda (base) (pow base 3)) > (cube 4) 64 > _ < See the |nl-letex| function, which also provides an expansion mechanism, and the function |nl-unify|, which is frequently used together with |nl-expand|. *newlisp-function-explode* *nl-explode* FUNCTION: explode~ |nl-utf8_capable| {syntax:} (explode {str} [{int-chunk} [{bool}]]) + {syntax:} (explode {list} [{int-chunk} [{bool}]]) In the first syntax, |nl-explode| transforms the string ({str}) into a list of single-character strings. Optionally, a chunk size can be specified in {int-chunk} to break the string into multi-character chunks. When specifying a value for {bool} other than {nil}, the last chunk will be omitted if it does not have the full length specified in {int-chunk}. > (explode "newLISP") ;→ ("n" "e" "w" "L" "I" "S" "P") (join (explode "keep it together")) ;→ "keep it together" (explode "newLISP" 2) ;→ ("ne" "wL" "IS" "P") (explode "newLISP" 3) ;→ ("new" "LIS" "P") ; omit last chunk if too short (explode "newLISP" 3 true) ;→ ("new" "LIS") < Only on non UTF8– enabled versions, |nl-explode| also works on binary content: > (explode "\000\001\002\003") ;→ ("\000" "\001" "\002" "\003") < When called in UTF-8–enabled versions of newLISP, |nl-explode| will work on character boundaries rather than byte boundaries. In UTF-8–encoded strings, characters may contain more than one byte. Processing will stop when a zero byte character is found. To explode binary contents on UTF-8–enabled versions of newLISP use |nl-unpack| as shown in the following example: > (set 'str "\001\002\003\004") ;→ "\001\002\003\004" (unpack (dup "c" (length str)) str) ;→ (1 2 3 4) (unpack (dup "s" (length str)) str) ;→ ("\001" "\002" "\003" "\004") < In the second syntax, |nl-explode| explodes a list ({list}) into sublists of chunk size {int-chunk}, which is 1 (one) by default. The following shows an example of the last chunk being omitted when the value for {bool} is other than {nil}, and the chunk does not have the full length specified in {int-chunk}. > (explode '(a b c d e f g h)) ;→ ((a) (b) (c) (d) (e) (f) (g) (h)) (explode '(a b c d e f g) 2) ;→ ((a b) (c d) (e f) (g)) ; omit last chunk if too short (explode '(a b c d e f g) 2 true) ;→ ((a b) (c d) (e f)) (transpose (explode '(a b c d e f g h) 2)) ;→ ((a c e g) (b d f h)) < The |nl-join| and |nl-append| functions are inverse operations of |nl-explode|. *newlisp-function-extend* *nl-extend* FUNCTION: extend~ |nl-destructive| {syntax:} (extend {list-1} [{list-2} ... ]) + {syntax:} (extend {string-1} [{string-2} ... ]) The list in {list-1} is extended by appending {list-2}. More than one list may be appended. The string in {string-1} is extended by appending {string-2}. More than one string may be appended. The string can contain binary {0} (zero) characters. The first parameter can be an un-initialized variable. The extended list or string is returned. > ; extending lists (extend lst '(a b) '(c d)) ;→ (a b c d) (extend lst '(e f g)) ;→ (a b c d e f) lst ;→ (a b c d e f g) ; extending strings (extend str "ab" "cd") ;→ "abcd" (extend str "efg") ;→ "abcdefg" str ;→ "abcdefg" ; extending in place (set 'L '(a b "CD" (e f))) (extend (L 2) "E") L ;→ (a b "CDE" (e f)) (extend (L 3) '(g)) L ;→ (a b "CDE" (e f g)) < For a non-destructive list or string extension see |nl-append|. *newlisp-function-factor* *nl-factor* FUNCTION: factor~ {syntax:} (factor {int}) Factors the number in {int} into its prime components. When floating point numbers are passed, they are truncated to their integer part first. > (factor 123456789123456789) ;→ (3 3 7 11 13 19 3607 3803 52579) ;; check correctness of factoring (= (apply * (factor 123456789123456789)) 123456789123456789) ;→ true ;; factor the biggest integer (factor 9223372036854775807) ;→ (7 7 73 127 337 92737 649657) ;; primes.lsp - return all primes in a list, up to n (define (primes n , p) (dotimes (e n) (if (= (length (factor e)) 1) (push e p -1))) p) (primes 20) ;→ (2 3 5 7 11 13 17 19) < |nl-factor| returns {nil} for numbers smaller than {2}. For numbers larger than 9,223,372,036,854,775,807 (the largest 64-bit integer) converted from floating point numbers, the largest integer is factored. *newlisp-function-fft* *nl-fft* FUNCTION: fft~ {syntax:} (fft {list-num}) Calculates the discrete Fourier transform on the list of complex numbers in {list-num} using the FFT method (Fast Fourier Transform). Each complex number is specified by its real part followed by its imaginary part. If only real numbers are used, the imaginary part is set to {0.0} (zero). When the number of elements in {list-num} is not a power of 2, |nl-fft| increases the number of elements by padding the list with zeroes. When the imaginary part of a complex number is {0}, simple numbers can be used instead. > (ifft (fft '((1 0) (2 0) (3 0) (4 0)))) ;→ ((1 0) (2 0) (3 0) (4 0)) ;; when imaginary part is 0, plain numbers work, too ;; complex numbers can be intermixed (fft '(1 2 3 4)) ;→ ((10 0) (-2 -2) (-2 0) (-2 2)) (fft '(1 2 (3 0) 4)) ;→ ((10 0) (-2 -2) (-2 0) (-2 2)) < The inverse operation of |nl-fft| is the |nl-ifft| function. *newlisp-function-file-info* *nl-file-info* FUNCTION: file-info~ {syntax:} (file-info {str-name} [{int-index} [{bool-flag}]]) Returns a list of information about the file or directory in {str}name_. The optional index specifies the list member to return. When no {bool-flag} is specified or when {bool-flag} evaluates to {nil} information about the link is returned if the file is a link to an original file. If {bool-flag} evaluates to anything else than {nil}, information about the original file referenced by the link is returned. [cols="1<,4<",width="25%",options="header",] |================================== |offset |contents |0 |size |1 |mode (differs with {true} flag) |2 |device mode |3 |user ID |4 |group ID |5 |access time |6 |modification time |7 |status change time |================================== Depending on {bool-flag} set, the function reports on either the link (no flag or {nil} flag) or on the original linked file ({true} flag). > (file-info ".bashrc") ;→ (124 33188 0 500 0 920951022 920951022 920953074) (file-info ".bashrc" 0) ;→ 124 (date (file-info "/etc" -1)) ;→ "Mon Mar 8 18:23:17 2005" < In the second example, the last status change date for the directory {/etc} is retrieved. |nl-file-info| gives file statistics (size) for a linked file, not the link, except for the {mode} field. *newlisp-function-file?* *nl-file?* FUNCTION: file?~ {syntax:} (file? {str-path-name} [{bool}]) Checks for the existence of a file in {str-name}. Returns {true} if the file exists; otherwise, it returns {nil}. This function will also return {true} for directories. If the optional {bool} value is {true}, {str-path-name} is returned. The existence of a file does not imply anything about its read or write permissions. A file may exist while not having the permissions to read from or write to it by the current user. > (if (file? "afile") (set 'fileNo (open "afile" "read"))) (file? "/usr/bin/newlisp" true) ;→ "/usr/bin/newlisp" (file? "/usr/bin/foo" true) ;→ nil < *newlisp-function-filter* *nl-filter* FUNCTION: filter~ {syntax:} (filter {exp-predicate} {exp-list}) The predicate {exp-predicate} is applied to each element of the list {exp-list}. A list is returned containing the elements for which {exp-predicate} is true. |nl-filter| works like |nl-clean|, but with a negated predicate. > (filter symbol? '(1 2 d 4 f g 5 h)) ;→ (d f g h) (define (big? x) (> x 5)) ;→ (lambda (x) (> x 5)) (filter big? '(1 10 3 6 4 5 11)) ;→ (10 6 11) ; filter with comparison functor (set 'L '((a 10 2 7) (b 5) (a 8 3) (c 8) (a 9))) (filter (curry match '(a *)) L) ;→ ((a 10 2 7) (a 8 3) (a 9)) (filter (curry match '(? ?)) L) ;→ ((b 5) (c 8) (a 9)) (filter (curry match '(* 8 *)) L) ;→ ((a 8 3) (c 8)) < The predicate may be a built-in predicate, a user-defined function, or a lambda expression. For filtering a list of elements with the elements from another list, use the |nl-difference| function or |nl-intersect| (with the {list} option). See also the related function |nl-index|, which returns the indices of the filtered elements and |nl-clean|, which returns all elements of a list for which a predicate is false. *newlisp-function-find* *nl-find* FUNCTION: find~ {syntax:} (find {exp-key} {list} [{func-compare} | {int-regex-option}]) + {syntax:} (find {str-key} {str-data} [{int-regex-option} [{int-offset}]]) Find an expression in a list ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ If the second argument evaluates to a {list}, then |nl-find| returns the index position (offset) of the element derived from evaluating {exp-key}. Optionally, an operator or user-defined function can be specified in {func-compare}. If the {exp-key} is a string, a regular expression option can be specified with the {int-regex-option} parameter. When using regular expressions or comparison functors the system variable {$0} is set to the last element found. > ; find an expression in a list (find '(1 2) '((1 4) 5 6 (1 2) (8 9))) ;→ 3 (find "world" '("hello" "world")) ;→ 1 (find "hi" '("hello" "world")) ;→ nil (find "newlisp" '("Perl" "Python" "newLISP") 1) ;→ 2 ; use the comparison functor (find 3 '(8 4 3 7 2 6) >) ;→ 4 $0 ;→ 2 (find "newlisp" '("Perl" "Python" "newLISP") (fn (x y) (regex x y 1))) ;→ 2 $0 ;→ "newLISP" (find 5 '((l 3) (k 5) (a 10) (z 22)) (fn (x y) (= x (last y)))) ;→ 1 $0 ;→ (k 5) (find '(a ?) '((l 3) (k 5) (a 10) (z 22)) match) ;→ 2 $0 ;→ (a 10) (find '(X X) '((a b) (c d) (e e) (f g)) unify) ;→ 2 $0 ;→ (e e) ; define the comparison functor first for better readability (define (has-it-as-last x y) (= x (last y))) (find 22 '((l 3) (k 5) (a 10) (z 22)) has-it-as-last) ;→ 3 $0 ;→ (z 22) < Using |nl-match| and |nl-unify|, list searches can be formulated which are as powerful as regular expression searches are for strings. Find a string in a string ^^^^^^^^^^^^^^^^^^^^^^^^^ If the second argument, {str-data}, evaluates to a string, then the offset position of the string {str-key} (found in the first argument, {str-data}) is returned. In this case, |nl-find| also works on binary {str-data}. The offset position returned is always based on counting single byte characters even when running the UTF-8 enabled version of newLISP. The presence of a third parameter specifies a search using the regular expression pattern specified in {str-pattern}, as well as an option number specified in {int-regex-option} (i.e., 1 (one) for case-insensitive search or {0} (zero) for no special options). If {int-regex-option} is specified an optional {int-offset} argument can be specified too to start the search not at the beginning but at the offset given. In any case the position returned by |nl-find| is calculated relative to the beginning of the string. To specify {int-offset} in a simple string search without regular expressions, specify {nil} for {int-regex-option}. In newLISP, regular expressions are standard Perl Compatible Regular Expression (PCRE) searches. Found expressions or subexpressions are returned in the system variables {$0}, {$1}, {$2}, etc., which can be used like any other symbol. As an alternative, the contents of these variables can also be accessed by using {($ 0)}, {($ 1)}, {($ 2)}, etc. This method allows indexed access (i.e., {($ i)}, where {i} is an integer). See |nl-regex| for the meaning of the option numbers and more information on regular expression searching. > ; simple string search (find "world" "Hello world") ;→ 6 (find "WORLD" "Hello woRLd") ;→ nil ; case-insensitive regex (find "WorlD" "Hello woRLd" 1) ;→ 6 (find "hi" "hello world") ;→ nil (find "Hello" "Hello world") ;→ 0 ; regex with default options (find "cat|dog" "I have a cat" 0) ;→ 9 $0 ;→ "cat" (find "cat|dog" "my dog" 0) ;→ 3 $0 ;→ "dog" (find "cat|dog" "MY DOG" 1) ;→ 3 $0 ;→ "DOG" ; use an optional offset (find "cat|dog" "I have a cat and a dog" 0) ;→ 9 (find "cat|dog" "I have a cat and a dog" 0 12) ;→ 19 ;; find with subexpressions in regular expression ;; and access with system variables (set 'str "http://nuevatec.com:80") (find "http://(.*):(.*)" str 0) ;→ 0 $0 ;→ "http://nuevatec.com:80" $1 ;→ "nuevatec.com" $2 ;→ "80" ;; system variables as an indexed expression (since 8.0.5) ($ 0) ;→ "http://nuevatec.com:80" ($ 1) ;→ "nuevatec.com" ($ 2) ;→ "80" < For other functions using regular expressions, see |nl-directory|, |nl-find-all|, |nl-parse|, |nl-regex|, |nl-replace|, and |nl-search|. To find expressions in nested or multidimensional lists, use the |nl-ref| and |nl-ref-all| functions. *newlisp-function-find-all* *nl-find-all* FUNCTION: find-all~ {syntax:} (find-all {str-regex-pattern} {str-text} [{exp} [{int-regex-option}]]) + {syntax:} (find-all {list-match-pattern} {list-lists} [{exp}]) + {syntax:} (find-all {exp-key} {list} {exp} {func-compare}) In the first syntax, |nl-find-all| finds all occurrences of {str-regex-pattern} in the text {str-text}, returning a list containing all matching strings. The empty list {()} is returned if no matches are found. Optionally, an expression can be specified to process the found string or regular subexpressions before placing them into the returned list. An additional option, {int-option}, specifies special regular expression options (see |nl-regex| for further details). > (find-all {\d+} "lkjhkljh34ghfdhgfd678gfdhfgd9") ;→ ("34" "678" "9") (find-all {(new)(lisp)} "newLISPisNEWLISP" (append $2 $1) 1) ;→ ("LISPnew" "LISPNEW") (unique (sort (find-all {[a-zA-Z]+} (replace "<[^>]+>" (get-url "http://newlisp.org") "" 0) ) )) ;→ ("A" "ACC" "AI" "API" "About" "All" "Amazing" "Apps" ... "where" "whole" "width" "wiki" "will" "with" "work" "written") < The first example discovers all numbers in a text. The second example shows how an optional expression in {exp} can work on subexpressions found by the regular expression pattern in {str-pattern}. The last example retrieves a web page, cleans out all HTML tags, and then collects all words into a unique and sorted list. Note that |nl-find-all| with strings always performs a regular expression search, even if the option in {int-option} is omitted. In the second syntax, |nl-find-all| searches for all list |nl-match| patterns {list-match-pattern} in {list-lists}. As in |nl-find-all| for strings, an expression can be specified in {exp} to process further the matched sublist: > (find-all '(? 2) '((a 1) (b 2) (a 2) (c 4))) ;→ ((b 2) (a 2)) (find-all '(? 2) '((a 1) (b 2) (a 2) (c 4)) (first $it)) ;→ (b a) < |nl-find-all| for list matches always uses |nl-match| to compare when searching for sublists and always needs a list for the pattern expression. In the third syntax, |nl-find-all| can specify a built-in or user-defined function used for comparing list elements with the key expression in {exp-key}: > (find-all 5 '(2 7 4 5 9 2 4 9 7 4 8) $it <) ;→ (7 9 9 7 8) ; process the found element available in $it (find-all 5 '(2 7 4 5 9 2 4 9 7 4 8) (* 3 $it) <) ;→ (21 27 27 21 24) ; same as (find-all 5 '(2 7 4 5 9 2 4 9 7 4 8) (* 3 $it) (fn (x y) (< x y))) ;→ (21 27 27 21 24) (find-all 5 '(2 7 4 5 9 2 4 9 7 4 8) ("abcdefghijk" $it) <) ;→ ("h" "j" "j" "h" "i") < Any type of expression can be searched for or can be contained in the list. |nl-find-all| in this syntax works similar to |nl-filter| but with the added benefit of being able to define a processing expression for the found element. *newlisp-function-first* *nl-first* FUNCTION: first~ |nl-utf8_capable| {syntax:} (first {list}) + {syntax:} (first {array}) + {syntax:} (first {str}) Returns the first element of a list or the first character of a string. The operand is not changed. This function is equivalent to {car} or {head} in other Lisp dialects. > (first '(1 2 3 4 5)) ;→ 1 (first '((a b) c d)) ;→ (a b) (set 'aList '(a b c d e)) ;→ (a b c d e) (first aList) ;→ a aList ;→ (a b c d e) (set 'A (array 3 2 (sequence 1 6))) ;→ ((1 2) (3 4) (5 6)) (first A) ;→ (1 2) (first '()) ;→ ERR: list is empty < In the third syntax, the first character is returned from the string in {str} as a string. > (first "newLISP") ;→ "n" (first (rest "newLISP")) ;→ "e" < Note that |nl-first| works on character boundaries rather than byte boundaries when the UTF-8–enabled version of newLISP is used. See also the functions |nl-last| and |nl-rest|. *newlisp-function-flat* *nl-flat* FUNCTION: flat~ {syntax:} (flat {list}) Returns a flattened list from a list: > (set 'lst '(a (b (c d)))) (flat lst) ;→ (a b c d) (map (fn (x) (ref x lst)) (flat lst)) ;→ ((0) (1 0) (1 1 0) (1 1 1)) < |nl-flat| can be used to iterate through nested lists. *newlisp-function-float* *nl-float* FUNCTION: float~ {syntax:} (float {exp} [{exp-default}]) If the expression in {exp} evaluates to a number or a string, the argument is converted to a float and returned. If {exp} cannot be converted to a float then {nil} or, if specified, the evaluation of {exp-default} will be returned. This function is mostly used to convert strings from user input or when reading and parsing text. The string must start with a digit or the |nl-+| (plus sign), |nl--| (minus sign), or {.} (period). If {exp} is invalid, |nl-float| returns {nil} as a default value. Floats with exponents larger than 1e308 or smaller than -1e308 are converted to +INF or -INF, respectively. The display of +INF and -INF differs on different platforms and compilers. > (float "1.23") ;→ 1.23 (float " 1.23") ;→ 1.23 (float ".5") ;→ 0.50 (float "-1.23") ;→ -1.23 (float "-.5") ;→ nil (float "#1.23") ;→ nil (float "#1.23" 0.0) ;→ 0 (float? 123) ;→ nil (float? (float 123)) ;→ true (float '(a b c)) ;→ nil (float '(a b c) 0) ;→ 0 (float nil 0) ;→ 0 (float "abc" "not a number") ;→ "not a number" (float "1e500") ;→ inf (float "-1e500") ;→ -inf (print "Enter a float num:") (set 'f-num (float (read-line))) < Use the |nl-int| function to parse integer numbers. *newlisp-function-float?* *nl-float?* FUNCTION: float?~ {syntax:} (float? {exp}) {true} is returned only if {exp} evaluates to a floating point number; otherwise, {nil} is returned. > (set 'num 1.23) (float? num) ;→ true < *newlisp-function-floor* *nl-floor* FUNCTION: floor~ {syntax:} (floor {number}) Returns the next lowest integer below {number} as a floating point. > (floor -1.5) ;→ -2 (floor 3.4) ;→ 3 < See also the |nl-ceil| function. *newlisp-function-flt* *nl-flt* FUNCTION: flt~ {syntax:} (flt {number}) Converts {number} to a 32-bit float represented by an integer. This function is used when passing 32-bit floats to library routines. newLISP floating point numbers are 64-bit and are passed as 64-bit floats when calling imported C library routines. > (flt 1.23) ;→ 1067282596 ;; pass 32-bit float to C-function: foo(float value) (import "mylib.so" "foo") (foo (flt 1.23)) (get-int (pack "f" 1.23)) ;→ 1067282596 (unpack "f" (pack "ld" (flt 1.2345))) ;→ (1.234500051) < The last two statements illustrate the inner workings of |nl-flt|. Use the |nl-import| function to import libraries. *newlisp-function-fn* *nl-fn* FUNCTION: fn~ {syntax:} (fn ({list-parameters}) {exp-body}) |nl-fn| is used to define anonymous functions, which are frequently used in |nl-map|, |nl-sort|, and many other functions where functions can be used as arguments. Using an anonymous function eliminates the need to define a new function with |nl-define|. Instead, a function is defined on the fly: > (map (fn (x) (+ x x)) '(1 2 3 4 5)) ;→ (2 4 6 8 10) (sort '(".." "..." "." ".....") (fn (x y) (> (length x) (length y)))) ;→ ("....." "..." ".." ".") < The example defines the function {fn(x)}, which takes an integer ({x}) and doubles it. The function is {mapped} onto a list of arguments using |nl-map|. The second example shows strings being sorted by length. The |nl-lambda| function (the longer, traditional form) can be used in place of |nl-fn|. *newlisp-function-for* *nl-for* FUNCTION: for~ {syntax:} (for ({sym} {num-from} {num-to} [{num-step} [{exp-break}]]) {body}) Repeatedly evaluates the expressions in {body} for a range of values specified in {num-from} and {num-to}, inclusive. A step size may be specified with {num-step}. If no step size is specified, {1} is assumed. Optionally, a condition for early loop exit may be defined in {exp-break}. If the break expression evaluates to any non-{nil} value, the |nl-for| loop returns with the value of {exp-break}. The break condition is tested before evaluating {body}. If a break condition is defined, {num-step} must be defined, too. The symbol {sym} is local in dynamic scope to the |nl-for| expression. It takes on each value successively in the specified range as an integer value if no step size is specified, or as a floating point value when a step size is present. After evaluation of the |nl-for| statement {sym} assumes its previous value. > > (for (x 1 10 2) (println x)) 1 3 5 7 9 > (for (x 8 6 0.5) (println x)) 8 7.5 7 6.5 6 > (for (x 1 100 2 (> (* x x) 30)) (println x)) 1 3 5 true > _ < The second example uses a range of numbers from highest to lowest. Note that the step size is always a positive number. In the third example, a break condition is tested. Use the |nl-sequence| function to make a sequence of numbers. *newlisp-function-for-all* *nl-for-all* FUNCTION: for-all~ {syntax:} (for-all {func-condition} {list}) Applies the function in {func-condition} to all elements in {list}. If all elements meet the condition in {func-condition}, the result is {true}; otherwise, {nil} is returned. > (for-all number? '(2 3 4 6 7)) ;→ true (for-all number? '(2 3 4 6 "hello" 7)) ;→ nil (for-all (fn (x) (= x 10)) '(10 10 10 10 10)) ;→ true < Use the |nl-exists| function to check if at least one element in a list meets a condition. *newlisp-function-fork* *nl-fork* FUNCTION: fork~ {syntax:} (fork {exp}) The expression in {exp} is launched as a newLISP child process-thread of the platforms OS. The new process inherits the entire address space, but runs independently so symbol or variable contents changed in the child process will not affect the parent process or vice versa. The child process ends when the evaluation of {exp} finishes. On success, |nl-fork| returns with the child process ID; on failure, {nil} is returned. See also the |nl-wait-pid| function, which waits for a child process to finish. This function is only available on Linux/Unix versions of newLISP and is based on the {fork()} implementation of the underlying OS. A much simpler automated method to launch processes and collect results is available with |nl-spawn| and the |nl-Cilk API|. > > (set 'x 0) 0 > (fork (while (< x 20) (println (inc x)) (sleep 1000))) 176 > 1 2 3 4 5 6 < The example illustrates how the child process-thread inherits the symbol space and how it is independent of the parent process. The |nl-fork| statement returns immediately with the process ID {176}. The child process increments the variable {x} by one each second and prints it to standard out (boldface). In the parent process, commands can still be entered. Type {x} to see that the symbol {x} still has the value {0} (zero) in the parent process. Although statements entered will mix with the display of the child process output, they will be correctly input to the parent process. The second example illustrates how |nl-pipe| can be used to communicate between processes. > #!/usr/bin/newlisp (define (count-down-proc x channel) (while (!= x 0) (write-line channel (string x)) (dec x))) (define (observer-proc channel) (do-until (= i "1") (println "process " (setq i (read-line channel))))) (map set '(in out) (pipe)) (set 'observer (fork (observer-proc in))) (set 'counter (fork (count-down-proc 5 out))) ; avoid zombies (wait-pid observer) (wait-pid counter) (exit) < The following output is generated by observer-proc --------- process 5 process 4 process 3 process 2 process 1 --------- The {count-down-proc} writes numbers to the communication pipe, where they are picked up by the {observer-process} and displayed. A forked process can either exit by itself or it can be destroyed using the |nl-destroy| function. > (define (fork-destroy-demo) (set 'pid (fork (dotimes (i 1000) (println i) (sleep 10)))) (sleep 50) (destroy pid) ) > (fork-destroy-demo) 0 1 2 3 4 true > < The process started by {fork-destroy-demo} will not finish but is destroyed 50 milli-seconds after start by a call to |nl-destroy|. Use the |nl-semaphore| function for synchronizing processes and |nl-share| for sharing memory between processes. See |nl-spawn| for a much simpler and automated way to synchronize processes and collect results. *newlisp-function-format* *nl-format* FUNCTION: format~ {syntax:} (format {str-format exp-data-1} [{exp-data-2} ... ]) + {syntax:} (format {str-format} {list-data}) Constructs a formatted string from {exp-data-1} using the format specified in the evaluation of {str-format}. The format specified is identical to the format used for the {printf()} function in the ANSI C language. Two or more {exp-data} arguments can be specified for more than one format specifier in {str-format}. In an alternative syntax, the data to be formatted can be passed inside a list in {list-data}. |nl-format| checks for a valid format string, matching data type, and the correct number of arguments. Wrong formats or data types result in error messages. |nl-int|, |nl-float|, or |nl-string| can be used to ensure correct data types and to avoid error messages. The format string has the following general format: *"%w.pf"* The |nl-%| (percent sign) starts a format specification. To display a |nl-%| inside a format string, double it: {%%} The {w} represents the width field. Data is right-aligned, except when preceded by a minus sign, in which case it is left-aligned. If preceded by a |nl-+| (plus sign), positive numbers are displayed with a |nl-+|. When preceded by a {0} (zero), the unused space is filled with leading zeroes. The width field is optional and serves all data types. The {p} represents the precision number of decimals (floating point only) or strings and is separated from the width field by a period. Precision is optional. When using the precision field on strings, the number of characters displayed is limited to the number in {p}. The {f} represents a type flag and is essential; it cannot be omitted. Below are the types in {f}: [cols="1<,10<",width="30%",options="header",] |=================================================== |format |description |s |text string |c |character (value 1 - 255) |d |decimal (32-bit) |u |unsigned decimal (32-bit) |x |hexadecimal lowercase |X |hexadecimal uppercase |o |octal (32-bits) (not supported on all compilers) |f |floating point |e |scientific floating point |E |scientific floating point |g |general floating point |=================================================== Formatting 64-bit numbers using 32-bit format specifiers will truncate and format the lower 32 bits of the number. For 64-bit numbers use the following format strings on Unix-like operating systems: [cols="1<,10<",width="20%",options="header",] |================================== |format |description |lld |decimal (64-bit) |llu |unsigned decimal (64-bit) |llx |hexadecimal (64-bit) |llX |hexadecimal uppercase(64-bit) |================================== For 64-bit numbers (since version 8.9.7) use the following format strings on Tru64 Unix: [cols="1<,10<",width="20%",options="header",] |================================= |format |description |ld |decimal (64-bit) |lu |unsigned decimal (64-bit) |lx |hexadecimal (64-bit) |lX |hexadecimal uppercase(64-bit) |================================= On Win32 platforms the following characters apply for 64 bit numbers: [cols="1<,10<",width="20%",options="header",] |=================================== |format |description |I64d |decimal (64-bit) |I64u |unsigned decimal (64-bit) |I64x |hexadecimal (64-bit) |I64X |hexadecimal uppercase(64-bit) |=================================== Other text may occur between, before, or after the format specs. Note that on Tru64 Unix the format character {i} can be used instead of {d}. > (format ">>>%6.2f<<<" 1.2345) ;→ ">>> 1.23<<<" (format ">>>%-6.2f<<<" 1.2345) ;→ ">>>1.23 <<<" (format ">>>%+6.2f<<<" 1.2345) ;→ ">>> +1.23<<<" (format ">>>%+6.2f<<<" -1.2345) ;→ ">>> -1.23<<<" (format ">>>%-+6.2f<<<" -1.2345) ;→ ">>>-1.23 <<<" (format "%e" 123456789) ;→ "1.234568e+08" (format "%12.10E" 123456789) ;→ "1.2345678900E+08" (format "%10g" 1.23) ;→ " 1.23" (format "%10g" 1.234) ;→ " 1.234" (format "Result = %05d" 2) ;→ "Result = 00002" (format "%-15s" "hello") ;→ "hello " (format "%15s %d" "hello" 123) ;→ " hello 123" (format "%5.2s" "hello") ;→ " he" (format "%-5.2s" "hello") ;→ "he " (format "%o" 80) ;→ "120" (format "%x %X" -1 -1) ;→ "ffffffff FFFFFFFF" ; 64 bit numbers on Windows (format "%I64X" 123456789012345678) ;→ "1B69B4BA630F34E" ; 64 bit numbers on Unix (except TRU64) (format "%llX" 123456789012345678) ;→ "1B69B4BA630F34E" (format "%c" 65) ;→ "A" < The data to be formatted can be passed inside a list: > (set 'L '("hello" 123)) (format "%15s %d" L) ;→ " hello 123" < If the format string requires it, newLISP's |nl-format| will automatically convert integers into floating points or floating points into integers: > (format "%f" 123) ;→ 123.000000 (format "%d" 123.456) ;→ 123 < *newlisp-function-fv* *nl-fv* FUNCTION: fv~ {syntax:} (fv {num-rate} {num-nper} {num-pmt} {num-pv} [{int-type}]) Calculates the future value of a loan with constant payment {num-pmt} and constant interest rate {num-rate} after {num-nper} period of time and a beginning principal value of {num-pv}. If payment is at the end of the period, {int-type} is {0} (zero) or {int-type} is omitted; for payment at the beginning of each period, {int-type} is 1. > (fv (div 0.07 12) 240 775.30 -100000) ;→ -0.5544645052 < The example illustrates how a loan of $100,000 is paid down to a residual of $0.55 after 240 monthly payments at a yearly interest rate of 7 percent. See also the functions |nl-irr|, |nl-nper|, |nl-npv|, |nl-pmt|, and |nl-pv|. *newlisp-function-gammai* *nl-gammai* FUNCTION: gammai~ {syntax:} (gammai {num-a} {num-b}) Calculates the incomplete Gamma function of values {a} and {b} in {num-a} and {num-b}, respectively. > (gammai 4 5) ;→ 0.7349740847 < The incomplete Gamma function is used to derive the probability of Chi² to exceed a given value for a degree of freedom, df, as follows: {_}{_}{_}{_}{_}{_}{_}{_}{_}{_}{_}{_}{_}{_}{_}{_}{_}{_}_ {*Q(Chi²|df) = Q(df/2, Chi²/2) = gammai(df/2, Chi²/2)*} {_}{_}{_}{_}{_}{_}{_}{_}{_}{_}{_}{_}{_}{_}{_}{_}{_}{_}_ See also the |nl-prob-chi2| function. *newlisp-function-gammaln* *nl-gammaln* FUNCTION: gammaln~ {syntax:} (gammaln {num-x}) Calculates the log Gamma function of the value {x} in {num-x}. > (exp (gammaln 6)) ;→ 120 < The example uses the equality of {n! = gamma(n + 1)} to calculate the factorial value of 5. The log Gamma function is also related to the Beta function, which can be derived from it: {_}{_}{_}{_}{_}{_}{_}{_}{_}{_}{_}{_}{_}{_}{_}{_}{_}{_}{_}__ {*Beta(z,w) = Exp(Gammaln(z) + Gammaln(w) - Gammaln(z+w))*} {_}{_}{_}{_}{_}{_}{_}{_}{_}{_}{_}{_}{_}{_}{_}{_}{_}{_}{_}__ *newlisp-function-gcd* *nl-gcd* FUNCTION: gcd~ {syntax:} (gcd {int-1} [{int-2} ... ]) Calculates the greatest common divisor of a group of integers. The greatest common divisor of two integers that are not both zero is the largest integer that divides both numbers. |nl-gcd| will calculate the greatest common divisor for the first two integers in {int-i} and then further reduce the argument list by calculating the greatest common divisor of the result and the next argument in the parameter list. > (gcd 0) ;→ 0 (gcd 0 0) ;→ 0 (gcd 10) ;→ 10 (gcd 12 36) ;→ 12 (gcd 15 36 6) ;→ 3 < See http://en.wikipedia.org/wiki/Greatest{common}divisor[Wikipedia] for details and theory about gcd numbers in mathematics. *newlisp-function-get-char* *nl-get-char* FUNCTION: get-char~ {syntax:} (get-char {int-address}) Gets an 8-bit character from an address specified in {int-address}. This function is useful when using imported shared library functions with |nl-import|. > char * foo(void) { char * result; result = "ABCDEFG"; return(result); } < Consider the above C function from a shared library, which returns a character pointer (address to a string). > (import "mylib.so" "foo") (print (get-char (foo) )) ;→ 65 ; ASCII "A" (print (get-char (+ (foo) 1))) ;→ 66 ; ASCII "B" < Note that it is unsafe to use the |nl-get-char| function with an incorrect address in {int-address}. Doing so could result in the system crashing or becoming unstable. See also the |nl-address|, |nl-get-int|, |nl-get-long|, |nl-get-float|, |nl-get-string|, |nl-pack|, and |nl-unpack| functions. *newlisp-function-get-float* *nl-get-float* FUNCTION: get-float~ {syntax:} (get-float {int-address}) Gets a 64-bit double float from an address specified in {int-address}. This function is helpful when using imported shared library functions (with |nl-import|) that return an address pointer to a double float or a pointer to a structure containing double floats. > double float * foo(void) { double float * result; … *result = 123.456; return(result); } < The previous C function is compiled into a shared library. > (import "mylib.so" "foo") (get-float (foo)) ;→ 123.456 < {foo} is imported and returns a pointer to a double float when called. Note that |nl-get-float| is unsafe when used with an incorrect address in {int-address} and may result in the system crashing or becoming unstable. See also the |nl-address|, |nl-get-int|, |nl-get-long|, |nl-get-char|, |nl-get-string|, |nl-pack|, and |nl-unpack| functions. *newlisp-function-get-int* *nl-get-int* FUNCTION: get-int~ {syntax:} (get-int {int-address}) Gets a 32-bit integer from the address specified in {int-address}. This function is handy when using imported shared library functions with |nl-import|, a function returning an address pointer to an integer, or a pointer to a structure containing integers. > int * foo(void) { int * result; … *result = 123; return(result); } int foo-b(void) { int result; … result = 456; return(result); } < Consider the C function {foo} (from a shared library), which returns an integer pointer (address of an integer). > (import "mylib.so" "foo") (get-int (foo)) ;→ 123 (foo-b) ;→ 456 < Note that using |nl-get-int| with an incorrect address in {int-address} is unsafe and could result in the system crashing or becoming unstable. See also the |nl-address|, |nl-get-char|, |nl-get-float|, |nl-get-long|, |nl-get-string|, |nl-pack|, and |nl-unpack| functions. *newlisp-function-get-long* *nl-get-long* FUNCTION: get-long~ {syntax:} (get-long {int-address}) Gets a 64-bit integer from the address specified in {int-address}. This function is handy when using |nl-import| to import shared library functions, a function returning an address pointer to a long integer, or a pointer to a structure containing long integers. > long long int * foo(void) { int * result; … *result = 123; return(result); } long long int foo-b(void) { int result; … result = 456; return(result); } < Consider the C function {foo} (from a shared library), which returns an integer pointer (address of an integer). > (import "mylib.so" "foo") (get-int (foo)) ;→ 123 (foo-b) ;→ 456 < Note that using |nl-get-long| with an incorrect address in {int-address} is unsafe and could result in the system crashing or becoming unstable. See also the |nl-address|, |nl-get-char|, |nl-get-float|, |nl-get-int|, |nl-get-string|, |nl-pack|, and |nl-unpack| functions. *newlisp-function-get-string* *nl-get-string* FUNCTION: get-string~ {syntax:} (get-string {int-address}) Gets a character string from the address specified in {int-address}. This function is helpful when using imported shared library functions with |nl-import|. > char * foo(void) { char * result; result = "ABCDEFG"; return(result); } < Consider the above C function from a shared library, which returns a character pointer (address to a string). > (import "mylib.so" "foo") (print (get-string (foo))) ;→ "ABCDEFG" < When a string is passed as an argument, |nl-get-string| will take its address as the argument. Because |nl-get-string| always breaks off at the first first {\000} (null character) it encounters, it can be used to retrieve a string from a buffer: > (set 'buff "ABC\000\000\000DEF") ;→ "ABC\000\000\000DEF" (length buff) ;→ 9 (get-string buff) ;→ "ABC" (length (get-string buff)) ;→ 3 ; get a string from offset into a buffer (get-string (+ (address buff) 6)) ;→ "DEF" ; use unpack to get the whole buffer (unpack "s9" buff) ;→ ("ABC\000\000\000DEF") < See also the |nl-get-char|, |nl-get-int|, |nl-get-float|, |nl-pack|, and |nl-unpack| functions. Note that |nl-get-string| can crash the system or make it unstable if the wrong address is specified. *newlisp-function-get-url* *nl-get-url* FUNCTION: get-url~ {syntax:} (get-url {str-url} [{str-option}] [{int-timeout} [{str-header}]]) Reads a web page or file specified by the URL in {str-url} using the HTTP GET protocol. Both {http://} and {file://} URLs are handled. {"header"} can be specified in the optional argument {str-option} to retrieve only the header. The option {"list"} causes header and page information to be returned as separate strings in a list. A {"debug"} option can be specified either alone or after the {"header"} or {"list"} option separated by one character, i.e. {"header debug"} or {"list debug"}. Including "debug" outputs all outgoing information to the console window. The optional argument {int-timeout} can specify a value in milliseconds. If no data is available from the host after the specified timeout, |nl-get-url| returns the string {ERR: timeout}. When other error conditions occur, |nl-get-url| returns a string starting with {ERR:} and the description of the error. |nl-get-url| handles redirection if it detects a {Location:} spec in the received header and automatically does a second request. |nl-get-url| also understands the {Transfer-Encoding: chunked} format and will unpack data into an unchunked format. |nl-get-url| requests are also understood by newLISP server nodes. > (get-url "http://www.nuevatec.com") (get-url "http://www.nuevatec.com" 3000) (get-url "http://www.nuevatec.com" "header") (get-url "http://www.nuevatec.com" "header" 5000) (get-url "http://www.nuevatec.com" "list") (get-url "file:///home/db/data.txt") ; access local file system (env "HTTP_PROXY" "http://ourproxy:8080") (get-url "http://www.nuevatec.com/newlisp/") < The index page from the site specified in {str-url} is returned as a string. In the third line, only the HTTP header is returned in a string. Lines 2 and 4 show a timeout value being used. The second example shows usage of a {file://} URL to access {/home/db/data.txt} on the local file system. The third example illustrates the use of a proxy server. The proxy server's URL must be in the operating system's environment. As shown in the example, this can be added using the |nl-env| function. The {int-timeout} can be followed by an optional custom header in {str-header}: Custom header ^^^^^^^^^^^^^ The custom header may contain options for browser cookies or other directives to the server. When no {str-header} is specified, newLISP sends certain header information by default. After the following request: > (get-url "http://somehost.com" 5000) < newLISP will configure and send the request and header below: ------------------------- GET / HTTP/1.1 Host: somehost.com User-Agent: newLISP v8800 Connection: close ------------------------- As an alternative, the {str-header} option could be used: > (get-url "http://somehost.com" 5000 "User-Agent: Mozilla/4.0\r\nCookie: name=fred\r\n") < newLISP will now send the following request and header: ----------------------- GET / HTTP/1.1 Host: somehost.com User-Agent: Mozilla/4.o Cookie: name=fred Connection: close ----------------------- Note that when using a custom header, newLISP will only supply the {GET} request line, as well as the {Host:} and {Connection:} header entries. newLISP inserts all other entries supplied in the custom header between the {Host:} and {Connection:} entries. Each entry must end with a carriage return line-feed pair: {\r\n}. See an HTTP transactions reference for valid header entries. Custom headers can also be used in the |nl-put-url| and |nl-post-url| functions. *newlisp-function-global* *nl-global* FUNCTION: global~ {syntax:} (global {sym-1} [{sym-2} ... ]) One or more symbols in {sym-1} [{sym-2} ... ] can be made globally accessible from contexts other than MAIN. The statement has to be executed in the MAIN context, and only symbols belonging to MAIN can be made global. |nl-global| returns the last symbol made global. > (global 'aVar 'x 'y 'z) ;→ z (define (foo x) (…)) (constant (global 'foo)) < The second example shows how |nl-constant| and |nl-global| can be combined into one statement, protecting and making a previous function definition global. *newlisp-function-global?* *nl-global?* FUNCTION: global?~ {syntax:} (global? {sym}) Checks if symbol in {sym} is global. Built-in functions, context symbols, and all symbols made global using the function |nl-global| are global: > global? 'print) ;→ true (global 'var) ;→ var (global? 'var) ;→ true (constant (global 'foo)) (global? 'foo) ;→ true < *newlisp-function-if* *nl-if* FUNCTION: if~ {syntax:} (if {exp-condition} {exp-1} [{exp-2}]) + {syntax:} (if {exp-cond-1} {exp-1} {exp-cond-2} {exp-2} [ ... ]) If the value of {exp-condition} is neither {nil} nor an empty list, the result of evaluating {exp-1} is returned; otherwise, the value of {exp-2} is returned. If {exp-2} is absent, the value of {exp-condition} is returned. > (set 'x 50) ;→ 50 (if (< x 100) "small" "big") ;→ "small" (set 'x 1000) ;→ 1000 (if (< x 100) "small" "big") ;→ "big" (if (> x 2000) "big") ;→ nil < The second form of |nl-if| works similarly to |nl-cond|, except it does not take parentheses around the condition-body pair of expressions. In this form, |nl-if| can have an unlimited number of arguments. > (define (classify x) (if (< x 0) "negative" (< x 10) "small" (< x 20) "medium" (>= x 30) "big" "n/a")) (classify 15) ;→ "medium" (classify 100) ;→ "big" (classify 22) ;→ "n/a" (classify -10) ;→ "negative" < The last expression, {"n/a"}, is optional. When this option is omitted, the evaluation of {(>= x 30)} is returned, behaving exactly like a traditional |nl-cond| but without requiring parentheses around the condition-expression pairs. In any case, the whole |nl-if| expression always returns the last expression or condition evaluated. See also the |nl-unless| function. *newlisp-function-ifft* *nl-ifft* FUNCTION: ifft~ {syntax:} (ifft {list-num}) Calculates the inverse discrete Fourier transform on a list of complex numbers in {list-num} using the FFT method (Fast Fourier Transform). Each complex number is specified by its real part, followed by its imaginary part. In case only real numbers are used, the imaginary part is set to {0.0} (zero). When the number of elements in {list-num} is not an integer power of 2, |nl-ifft| increases the number of elements by padding the list with zeroes. When complex numbers are {0} in the imaginary part, simple numbers can be used. > (ifft (fft '((1 0) (2 0) (3 0) (4 0)))) ;→ ((1 0) (2 0) (3 0) (4 0)) ;; when imaginary part is 0, plain numbers work too (ifft (fft '(1 2 3 4))) ;→ ((1 0) (2 0) (3 0) (4 0)) < The inverse operation of |nl-ifft| is the |nl-fft| function. *newlisp-function-import* *nl-import* FUNCTION: import~ {syntax:} (import {str-lib-name} {str-function-name} ["cdecl"]) + {syntax:} (import {str-lib-name} {str-function-name} {str-return-type} [{str-param-type} . . .]) + {syntax:} (import {str-lib-name}) Imports the function specified in {str-function-name} from a shared library named in {str-lib-name}. Depending on the syntax used, string labels for return and parameter types can be specified If the libary in {str-lib-name} is not in the system's library path, the full path name should be specified. A function can be imported only once. A repeated import of the same function will simply return the same - already allocated - function address. On {libffi} enabled versions - capable of the second extended syntax - imported symbols are protected against change and can only be modified using |nl-constant|. The third syntax - on OSX, Linux and other Unix only - allows loading libraries without importing functions. This is necessary when other libraries need access to functions they need internally. The simple |nl-import| syntax ^^^^^^^^^^^^^^^^^^^^^^^^^^ Most library functions can be imported using the simpler first syntax. The API expects all function arguments to be passed on the stack in either {cdecl} or {stdcall} conventions. On 32-bit platforms, integers, pointers to strings and buffers sometimes floating point values can be passed as parameters. On 64-bit platforms only integers can be passed but no floating point values. As return values only 32-bit or 64-bit values and pointers are allowed. No floating point numbers can be returned. Strings must be retrieved with the |nl-get-string| helper function. Regardless of these limitations, most modules included in the distribution use this simple import API. If pointers are returned to strings or structures the following helper functions can be used extract data: |nl-get-char|, |nl-get-int|, |nl-get-float|, |nl-get-string|, |nl-unpack| To pass pointers for data structures the following functions help to pack data and calculate addresses: |nl-address|, |nl-pack|. To transform newLISP data types into the data types needed by the imported function, use the functions |nl-float| for 64-bit double floats, |nl-flt| for 32-bit floats, and |nl-int| for 32-bit integers. By default, newLISP passes floating point numbers as 64-bit double floats, integers as 32-bit integers, and strings as 32-bit integers for string addresses (pointers in C). Floats can only be used with 32-bit versions of newLISP and libraries. To use floating point numbers in a 64-bit environment use the link:#extended_import[extended |nl-import| syntax]. > ;; define LIBC platform independent (define LIBC (lookup ostype '( ("Win32" "msvcrt.dll") ("OSX" "libc.dylib") (printf "%g %s %d %c\n" 1.23 "hello" 999 65) 1.23 hello 999 A ;→ 17 ; return value ;; import Win32 DLLs in Win32 versions (import "kernel32.dll" "GetTickCount") ;→ GetTickCount (import "user32.dll" "MessageBoxA") ;→ MessageBoxA (GetTickCount) ;→ 3328896 < In the first example, the string "1.23 hello 999 A" is printed as a side effect, and the value 17 (number of characters printed) is returned. Any C function can be imported from any shared library in this way. The message box example pops up a Windows dialog box, which may be hidden behind the console window. The console prompt does not return until the 'OK' button is pressed in the message box. > ;;this pops up a message box (MessageBoxA 0 "This is the body" "Caption" 1) < The other examples show several imports of Win32 DLL functions and the details of passing values {by value} or {by reference}. Whenever strings or numbers are passed by reference, space must be reserved beforehand. > (import "kernel32.dll" "GetWindowsDirectoryA") ;; allocating space for a string return value (set 'str (dup "\000" 64)) ; reserve space and initialize (GetWindowsDirectoryA str (length str)) str ;→ "C:\\WINDOWS\000\000\000 ... " ;; use trim or get-string to cut of binary zeros (get-string str) ;→ "C:\\WINDOWS" (trim str) ;→ "C:\\WINDOWS" (import "kernel32.dll" "GetComputerNameA") ;; allocate memory and initialize to zeros (set 'str (dup "\000" 64)) (set 'len (length str) ;; call the function ;; the length of the string is passed as address reference ;; string str is automatically past by address (C pointer) (GetComputerNameA str (address len)) str ;→ "LUTZ-PC\000\000 ... " (trim str) ;→ "LUTZ-PC" < |nl-import| returns the address of the function, which can be used to assign a different name to the imported function. > (set 'imprime (import "libc.so.6" "printf")) ;→ printf@400862A0 (imprime "%s %d" "hola" 123) ;→ "hola 123" < The Win32 and Cygwin versions of newLISP uses standard call {stdcall} conventions to call DLL library routines by default. This is necessary for calling DLLs that belong to the Win32 operating system. Most third-party DLLs are compiled for C declaration {cdecl} calling conventions and may need to specify the string {"cdecl"} as an additional last argument when importing functions. newLISP compiled for Mac OS X, Linux and other Unix systems uses the {cdecl} calling conventions by default and ignores any additional string. > ;; force cdecl calling conventions on Win32 (import "sqlite.dll" "sqlite_open" "cdecl") ;→ sqlite_open <673D4888> < Imported functions may take up to fourteen arguments. Note that floating point arguments take up two spaces each (e.g., passing five floats takes up ten of the fourteen parameters). The extended |nl-import| syntax ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The extended import API works with the second syntax. It is based on the popular {libffi} library and is pre-installed on most OS platforms. The API works with all atomic C data types for passed parameters and return values. The extended API requires that parameter types are specified in the |nl-import| statement as string type labels. Programs written with extended import API will run without change on 32-bit and 64-bit newLISP and libraries. Integers, floating point values and strings can be returned without using helper functions. The following types can be specified for the return value in {str-return-type} and for function parameters in {str-param-type}: [cols="1<,3<,3<",width="75%",options="header",] |======================================================================= |label |C type for return value and arguments |newLISP return and argument type |"void" |void (only as return type) |{nil} is returned |"byte" |byte unsigned 8 bit |integer |"char" |char signed 8 bit |integer |"unsigned short int" |unsigned short int 16 bit |integer |"short int" |short int signed 16 bit |integer |"unsigned int" |unsigned int 32 bit |integer |"int" |int signed 32 bit |integer |"long" |long signed 32 or 64 bit depending on platform |integer |"long long" |long long signed 64 bit |integer |"float" |float 32 bit |IEEE-754 64 bit float cut to 32-bit precision |"double" |double 64 bit |IEEE-754 64 bit float |"char*" |char* 32 or 64 bit ptr depending on platform |displayable string return (zero terminated) + string buffer arg (no addr. since 10.4.2) |"void*" |void* 32 or 64 bit ptr depending on platform |integer address return + either string buffer or integer address arg |======================================================================= The types {"char*"} and {"void*} can be interchanged and are treated identical inside {libffi}. Depending on the type of arguments passed and the type of return values, one or the other is used. Aggregate types can be composed using the |nl-struct| function. The following examples show how the extended |nl-import| syntax can handle return values of floating point values and strings: > ;; return a float value, LIBC was defined earlier ; name return arg (import LIBC "atof" "double" "char*") (atof "3.141") ;→ 3.141 ;; return a copied string ; name return arg-1 arg-2 (import LIBC "strcpy" "char*" "char*" "char*") (set 'from "Hello World") (set 'to (dup "\000" (length from))) ; reserve memory (strcpy to from) ;→ "Hello World" < The {char*} type takes a string buffer only. The {"void*} type can take either a string buffer or a memory address number as input. When using {"void*"} as a return type the address number of the result bufffer will be returned. This is useful when returning pointers to data structures. These pointers can then be used with |nl-unpack| and |nl-struct| for destructuring. In the following example the return type is changed to {void*}: > (import LIBC "strcpy" "void*" "char*" "char*") (set 'from "Hello World") (set 'to (dup "\000" (length from))) (strcpy to from) ;→ 2449424 (address to) ;→ 2449424 (unpack "s11" 2449424) ;→ "Hello World" (get-string 2449424) ;→ "Hello World" to ;→ "Hello World" < A newLISP string is always passed by it's address reference. For a more complex example see this http://www.newlisp.org/syntax.cgi?code/opengl-demo-ffi-lsp.txt[OpenGL demo]. Memory management ^^^^^^^^^^^^^^^^^ Any allocation performed by imported foreign functions has to be de-allocated manually if there's no call in the imported API to do so. See the http://www.newlisp.org/CodePatterns.html[Code Patterns in newLISP] document for an example. In case of calling foreign functions with passing by reference, memory for variables needs to be allocated beforehand by newLISP — see import of {GetWindowsDirectoryA} above — and hence, memory needs not be deallocated manually, because it is managed automatically by newLISP. *newlisp-function-inc* *nl-inc* FUNCTION: inc~ |nl-destructive| {syntax:} (inc {place} [{num}]) Increments the number in {place} by {1.0} or by the optional number {num} and returns the result. |nl-inc| performs float arithmetic and converts integer numbers passed into floating point type. {place} is either a symbol or a place in a list structure holding a number, or a number returned by an expression. > (set 'x 0) ;→ 0 (inc x) ;→ 1 x ;→ 1 (inc x 0.25) ;→ 1.25 x ;→ 1.25 (inc x) ;→ 2.25 < If a symbol for {place} contains {nil}, it is treated as if containing {0.0}: > z ;→ nil (inc z) ;→ 1 (set 'z nil) (inc z 0.01) ;→ 0.01 < Places in a list structure or a number returned by another expression can be updated too: > (set 'l '(1 2 3 4)) (inc (l 3) 0.1) ;→ 4.1 (inc (first l)) ;→ 2 l ;→ (2 2 3 4.1) (inc (+ 3 4)) ;→ 8 < Use the |nl-++| function for incrementing numbers in integer mode. Use |nl-dec| to decrement numbers in floating point mode. *newlisp-function-index* *nl-index* FUNCTION: index~ {syntax:} (index {exp-predicate} {exp-list}) Applies the predicate {exp-predicate} to each element of the list {exp-list} and returns a list containing the indices of the elements for which {exp-predicate} is true. > (index symbol? '(1 2 d 4 f g 5 h)) ;→ (2 4 5 7) (define (big? x) (> x 5)) ;→ (lambda (x) (> x 5)) (index big? '(1 10 3 6 4 5 11)) ;→ (1 3 6) (select '(1 10 3 6 4 5 11) '(1 3 6)) ;→ (1 3 6) < The predicate may be a built-in predicate, a user-defined function, or a lambda expression. Use the |nl-filter| function to return the elements themselves. *newlisp-function-inf?* *nl-inf?* FUNCTION: inf?~ {syntax:} (inf? {float}) If the value in {float} is infinite the function returns {true} else {nil}. > (inf? (div 1 0)) ;→ true (div 0 0) ;→ NaN < Note that an integer division by zero e.g. {(/ 1 0)} will throw an "division by zero" error and not yield infinity. See also |nl-NaN?| to check if a floating point number is valid. *newlisp-function-int* *nl-int* FUNCTION: int~ {syntax:} (int {exp} [{exp-default} [{int-base}]]) If the expression in {exp} evaluates to a number or a string, the result is converted to an integer and returned. If {exp} cannot be converted to an integer, then {nil} or the evaluation of {exp-default} will be returned. This function is mostly used when translating strings from user input or from parsing text. If {exp} evaluates to a string, the string must start with a digit; one or more spaces; or the |nl-+| or |nl--| sign. The string must begin with '{0x}' for hexadecimal strings or '{0}' (zero) for octal strings. If {exp} is invalid, |nl-int| returns {nil} as a default value if not otherwise specified. A second optional parameter can be used to force the number base of conversion to a specific value. Integers larger than 9,223,372,036,854,775,807 are truncated to 9,223,372,036,854,775,807. Integers smaller than -9,223,372,036,854,775,808 are truncated to -9,223,372,036,854,775,808. When converting from a float (as in the second form of |nl-int|), floating point values larger or smaller than the integer maximum or minimum are also truncated. A floating point expression evaluating to {NaN} is converted to {0} (zero). > (int "123") ;→ 123 (int " 123") ;→ 123 (int "a123" 0) ;→ 0 (int (trim " 123")) ;→ 123 (int "0xFF") ;→ 255 (int "055") ;→ 45 (int "1.567") ;→ 1 (int 1.567) ;→ 1 (integer? 1.00) ;→ nil (integer? (int 1.00)) ;→ true (int "1111" 0 2) ;→ 15 ; base 2 conversion (int "0FF" 0 16) ;→ 255 ; base 16 conversion (int 'xyz) ;→ nil (int 'xyz 0) ;→ 0 (int nil 123) ;→ 123 (int "abc" (throw-error "not a number")) ;→ ERR: user error : not a number (print "Enter a num:") (set 'num (int (read-line))) (int (bits 12345) 0 2) ;→ 12345 < The inverse function to |nl-int| with base {2} is |nl-bits|. Use the |nl-float| function to convert arguments to floating point numbers. *newlisp-function-integer?* *nl-integer?* FUNCTION: integer?~ {syntax:} (integer? {exp}) Returns {true} only if the value of {exp} is an integer; otherwise, it returns {nil}. > (set 'num 123) ;→ 123 (integer? num) ;→ true < *newlisp-function-intersect* *nl-intersect* FUNCTION: intersect~ {syntax:} (intersect {list-A} {list-B}) + {syntax:} (intersect {list-A} {list-B} {bool}) In the first syntax, |nl-intersect| returns a list containing one copy of each element found both in {list-A} and {list-B}. > (intersect '(3 0 1 3 2 3 4 2 1) '(1 4 2 5)) ;→ (2 4 1) < In the second syntax, |nl-intersect| returns a list of all elements in {list-A} that are also in {list-B}, without eliminating duplicates in {list-A}. {bool} is an expression evaluating to {true} or any other value not {nil}. > (intersect '(3 0 1 3 2 3 4 2 1) '(1 4 2 5) true) ;→ (1 2 4 2 1) < See also the set functions |nl-difference|, |nl-unique| and |nl-union|. *newlisp-function-invert* *nl-invert* FUNCTION: invert~ {syntax:} (invert {matrix} [{float-pivot}]) Returns the inversion of a two-dimensional matrix in {matrix}. The matrix must be square, with the same number of rows and columns, and {non-singular} (invertible). Matrix inversion can be used to solve systems of linear equations (e.g., multiple regression in statistics). newLISP uses LU-decomposition of the matrix to find the inverse. Optionally {0.0} or a very small value can be specified in {float-pivot}. This value substitutes pivot elements in the LU-decomposition algorithm, which result in zero when the algorithm deals with a singular matrix. The dimensions of a matrix are defined by the number of rows times the number of elements in the first row. For missing elements in non-rectangular matrices, {0.0} (zero) is assumed. A matrix can either be a nested list or an |nl-array|. > (set 'A '((-1 1 1) (1 4 -5) (1 -2 0))) (invert A) ;→ ((10 2 9) (5 1 4) (6 1 5)) (invert (invert A)) ;→ ((-1 1 1) (1 4 -5) (1 -2 0)) ; solve Ax = b for x (multiply (invert A) '((1) (2) (3))) ;→ ((41) (19) (23)) ; treatment of singular matrices (invert '((2 -1) (4 -2))) ;→ nil (invert '((2 -1) (4 -2)) 0.0) ;→ ((inf -inf) (inf -inf)) (invert '((2 -1) (4 -2)) 1e-20) ;→ ((5e+19 -2.5e+19) (1e+20 -5e+19)) < |nl-invert| will return {nil} if the matrix is {singular} and cannot be inverted, and {float-pivot} is not specified. All operations shown here on lists can be performed on arrays, as well. See also the matrix functions |nl-det|, |nl-mat|, |nl-multiply| and |nl-transpose|. *newlisp-function-irr* *nl-irr* FUNCTION: irr~ {syntax:} (irr {list-amounts} [{list-times} [{num-guess}]]) Calculates the internal rate of return of a cash flow per time period. The internal rate of return is the interest rate that makes the present value of a cash flow equal to {0.0} (zero). In-flowing (negative values) and out-flowing (positive values) amounts are specified in {list-amounts}. If no time periods are specified in {list-times}, amounts in {list-amounts} correspond to consecutive time periods increasing by 1 (1, 2, 3—). The algorithm used is iterative, with an initial guess of 0.5 (50 percent). Optionally, a different initial guess can be specified. The algorithm returns when a precision of 0.000001 (0.0001 percent) is reached. {nil} is returned if the algorithm cannot converge after 50 iterations. {irr} is often used to decide between different types of investments. > (irr '(-1000 500 400 300 200 100)) ;→ 0.2027 (npv 0.2027 '(500 400 300 200 100)) ;→ 1000.033848 ; ~ 1000 (irr '(-1000 500 400 300 200 100) '(0 3 4 5 6 7)) ;→ 0.0998 (irr '(-5000 -2000 5000 6000) '(0 3 12 18)) ;→ 0.0321 < If an initial investment of 1,000 yields 500 after the first year, 400 after two years, and so on, finally reaching {0.0} (zero) after five years, then that corresponds to a yearly return of about 20.2 percent. The next line demonstrates the relation between |nl-irr| and |nl-npv|. Only 9.9 percent returns are necessary when making the first withdrawal after three years. In the last example, securities were initially purchased for 5,000, then for another 2,000 three months later. After a year, securities for 5,000 are sold. Selling the remaining securities after 18 months renders 6,000. The internal rate of return is 3.2 percent per month, or about 57 percent in 18 months. See also the |nl-fv|, |nl-nper|, |nl-npv|, |nl-pmt|, and |nl-pv| functions. *newlisp-function-join* *nl-join* FUNCTION: join~ {syntax:} (join {list-of-strings} [{str-joint} [{bool-trail-joint}]]) Concatenates the given list of strings in {list-of-strings}. If {str-joint} is present, it is inserted between each string in the join. If {bool-trail-joint} is {true} then a joint string is also appended to the last string. > (set 'lst '("this" "is" "a" "sentence")) (join lst " ") ;→ "this is a sentence" (join (map string (slice (now) 0 3)) "-") ;→ "2003-11-26" (join (explode "keep it together")) ;→ "keep it together" (join '("A" "B" "C") "-") ;→ "A-B-C" (join '("A" "B" "C") "-" true) ;→ "A-B-C-" < See also the |nl-append|, |nl-string|, and |nl-explode| functions, which are the inverse of the |nl-join| operation. *newlisp-function-lambda* *nl-lambda* FUNCTION: lambda~ See the description of |nl-fn|, which is a shorter form of writing {lambda}. *newlisp-function-lambda-macro* *nl-lambda-macro* FUNCTION: lambda-macro~ See the description of |nl-define-macro|. *newlisp-function-lambda?* *nl-lambda?* FUNCTION: lambda?~ {syntax:} (lambda? {exp}) Returns {true} only if the value of {exp} is a lambda expression; otherwise, returns {nil}. > (define (square x) (* x x)) ;→ (lambda (x) (* x x)) square ;→ (lambda (x) (* x x)) (lambda? square) ;→ true < See |nl-define| and |nl-define-macro| for more information about {lambda} expressions. *newlisp-function-last* *nl-last* FUNCTION: last~ |nl-utf8_capable| {syntax:} (last {list}) + {syntax:} (last {array}) + {syntax:} (last {str}) Returns the last element of a list or a string. > (last '(1 2 3 4 5)) ;→ 5 (last '(a b (c d))) ;→ (c d) (set 'A (array 3 2 (sequence 1 6))) ;→ ((1 2) (3 4) (5 6)) (last A) ;→ (5 6) (last '()) ;→ ERR: list is empty < In the second version the last character in the string {str} is returned as a string. > (last "newLISP") ;→ "P" < Note that |nl-last| works on character boundaries rather than byte boundaries when the UTF-8–enabled version of newLISP is used. See also |nl-first|, |nl-rest| and |nl-nth|. *newlisp-function-last-error* *nl-last-error* FUNCTION: last-error~ {syntax:} (last-error) + {syntax:} (last-error {int-error}) Reports the last error generated by newLISP due to syntax errors or exhaustion of some resource. For a summary of all possible errors see the chapter |nl-Error codes| in the appendix. If no error has occurred since the newLISP session was started, {nil} is returned. When {int-error} is specified, a list of the number and the error text is returned. > (last-error) ;→ nil (abc) ERR: invalid function : (abc) (last-error) ;→ (24 "ERR: invalid function : (abc)") (last-error 24) ;→ (24 "invalid function") (last-error 1) ;→ (1 "not enough memory") (last-error 12345) ;→ (12345 "Unknown error") < For error numbers out of range the string {"Unknown error"} is given for the error text. Errors can be trapped by |nl-error-event| and userdefined error handlers. See also |nl-net-error| for errors generated by networking conditions and |nl-sys-error| for errors generated by the operating system. *newlisp-function-legal?* *nl-legal?* FUNCTION: legal?~ {syntax:} (legal? {str}) The token in {str} is verified as a legal newLISP symbol. Non-legal symbols can be created using the |nl-sym| function (e.g. symbols containing spaces, quotes, or other characters not normally allowed). Non-legal symbols are created frequently when using them for associative data access: > (symbol? (sym "one two")) ;→ true (legal? "one two") ;→ nil ; contains a space (set (sym "one two") 123) ;→ 123 (eval (sym "one two")) ;→ 123 < The example shows that the string {"one two"} does not contain a legal symbol although a symbol can be created from this string and treated like a variable. *newlisp-function-length* *nl-length* FUNCTION: length~ {syntax:} (length {exp}) Returns the number of elements in a list, the number of rows in an array, or the number of bytes in a string. |nl-length| applied to a symbol returns the length of the symbol name. Applied to a number, |nl-length| returns the number of bytes needed in memory to store that number: 4 or 8 for integers and 8 for floating point numbers. > (length '(a b (c d) e)) ;→ 4 (length '()) ;→ 0 (set 'someList '(q w e r t y)) ;→ (q w e r t y) (length someList) ;→ 6 (set 'ary (array 2 4 '(0))) ;→ ((1 2 3 4) (5 6 7 8)) (length ary) ;→ 2 (length "Hello World") ;→ 11 (length "") ;→ 0 (length 'someVar) ;→ 7 (length 123) ;→ 8 (length 1.23) ;→ 8 (length (get-int "\000\000\000\001")) ;→ 4 < Use |nl-utf8len| to calculate the number of UTF-8 characters in a string. *newlisp-function-let* *nl-let* FUNCTION: let~ {syntax:} (let ( ({sym1} [{exp-init1}]) [({sym2} [{exp-init2}]) ... ]) {body}) + {syntax:} (let ({sym1} {exp-init1} [{sym2} {exp-init2} ... ]) {body}) One or more variables {sym1}, {sym2}, ... are declared locally and initialized with expressions in {exp-init1}, {exp-init2}, etc. In the fully parenthesized first syntax, initializers are optional and assumed {nil} if missing. When the local variables are initialized, the initializer expressions evaluate using symbol bindings as before the |nl-let| statement. To incrementally use symbol bindings as evaluated during the initialization of locals in |nl-let|, use |nl-letn|. One or more expressions in {exp-body} are evaluated using the local definitions of {sym1}, {sym2} etc. |nl-let| is useful for breaking up complex expressions by defining local variables close to the place where they are used. The second form omits the parentheses around the variable expression pairs but functions identically. > (define (sum-sq a b) (let ((x (* a a)) (y (* b b))) (+ x y))) (sum-sq 3 4) ;→ 25 (define (sum-sq a b) ; alternative syntax (let (x (* a a) y (* b b)) (+ x y))) < The variables {x} and {y} are initialized, then the expression {(+ x y)} is evaluated. The let form is just an optimized version and syntactic convenience for writing: > ((lambda (sym1 [sym2 ... ]) exp-body ) exp-init1 [ exp-init2 ]) < See also |nl-letn| for an incremental or nested form of |nl-let| and local for initializing to {nil}. *newlisp-function-letex* *nl-letex* FUNCTION: letex~ {syntax:} (letex ( ({sym1} [{exp-init1}]) [({sym2} [{exp-init2}]) ... ]) {body}) + {syntax:} (letex ({sym1} {exp-init1} [{sym2} {exp-init2} ... ]) {body}) This function combines |nl-let| and |nl-expand| to expand local variables into an expression before evaluating it. In the fully parenthesized first syntax initializers are optional and assumed {nil} if missing. Both forms provide the same functionality, but in the second form the parentheses around the initializers can be omitted: > (letex (x 1 y 2 z 3) '(x y z)) ;→ (1 2 3) (letex ( (x 1) (y '(a b c)) (z "hello") ) '(x y z)) ;→ (1 (a b c) "hello") < Before the expression {'(x y z)} gets evaluated, {x, y} and {z} are literally replaced with the initializers from the |nl-letex| initializer list. The final expression which gets evaluated is {'(1 2 3)}. In the second example a function {make-adder} is defined for making adder functions: > (define (make-adder n) (letex (c n) (lambda (x) (+ x c)))) (define add3 (make-adder 3)) ;→ (lambda (x) (+ x 3)) (add3 10) ;→ 13 < |nl-letex| evaluates {n} to the constant {3} and replaces {c} with it in the lambda expression. *newlisp-function-letn* *nl-letn* FUNCTION: letn~ {syntax:} (letn ( ({sym1} [{exp-init1}]) [({sym2} [{exp-init2}]) ... ]) {body}) + {syntax:} (letn ({sym1} {exp-init1} [{sym2} {exp-init2} ... ]) {body}) |nl-letn| is like a {nested let} and works similarly to |nl-let|, but will incrementally use the new symbol bindings when evaluating the initializer expressions as if several |nl-let| were nested. In the fully parenthesized first syntax, initializers are optional and assumed {nil} if missing. The following comparison of |nl-let| and |nl-letn| show the difference: > (set 'x 10) (let ((x 1) (y (+ x 1))) (list x y)) ;→ (1 11) (letn ((x 1) (y (+ x 1))) (list x y)) ;→ (1 2) < While in the first example using |nl-let| the variable {y} is calculated using the binding of {x} before the |nl-let| expression, in the second example using |nl-letn| the variable {y} is calculated using the new local binding of {x}. > (letn (x 1 y x) (+ x y)) ;→ 2 ;; same as nested let's (let (x 1) (let (y x) (+ x y))) ;→ 2 < |nl-letn| works like several {nested} |nl-let|. The parentheses around the initializer expressions can be omitted. *newlisp-function-list* *nl-list* FUNCTION: list~ {syntax:} (list {exp-1} [{exp-2} ... ]) The {exp} are evaluated and the values used to construct a new list. Note that arguments of array type are converted to lists. > (list 1 2 3 4 5) ;→ (1 2 3 4 5) (list 'a '(b c) (+ 3 4) '() '*) ;→ (a (b c) 7 () *) < See also |nl-cons| and |nl-push| for other forms of building lists. *newlisp-function-list?* *nl-list?* FUNCTION: list?~ {syntax:} (list? {exp}) Returns {true} only if the value of {exp} is a list; otherwise returns {nil}. Note that lambda and lambda-macro expressions are also recognized as special instances of a list expression. > (set 'var '(1 2 3 4)) ;→ (1 2 3 4) (list? var) ;→ true (define (double x) (+ x x)) (list? double) ;→ true < *newlisp-function-load* *nl-load* FUNCTION: load~ {syntax:} (load {str-file-name-1} [{str-file-name-2} ... ] [{sym-context}]) Loads and translates newLISP from a source file specified in one or more {str-file-name} and evaluates the expressions contained in the file(s). When loading is successful, |nl-load| returns the result of the last expression in the last file evaluated. If a file cannot be loaded, |nl-load| throws an error. An optional {sym-context} can be specified, which becomes the context of evaluation, unless such a context switch is already present in the file being loaded. By default, files which do not contain |nl-context| switches will be loaded into the {MAIN} context. The {str-file-name} specs can contain URLs. Both {http://} and { file://} URLs are supported. > (load "myfile.lsp") (load "a-file.lsp" "b-file.lsp") (load "file.lsp" "http://mysite.org/mypro") (load "http://192.168.0.21:6000//home/test/program.lsp") (load "a-file.lsp" "b-file.lsp" 'MyCTX) (load "file:///usr/share/newlisp/mysql.lsp") < In case expressions evaluated during the |nl-load| are changing the |nl-context|, this will not influence the programming module doing the |nl-load|. The current context after the |nl-load| statement will always be the same as before the |nl-load|. Normal file specs and URLs can be mixed in the same load command. |nl-load| with {HTTP} URLs can also be used to load code remotely from newLISP server nodes running on a Unix-like operating system. In this mode, |nl-load| will issue an HTTP GET request to the target URL. Note that a double backslash is required when path names are specified relative to the root directory. |nl-load| in {HTTP} mode will observe a 60-second timeout. The second to last line causes the files to be loaded into the context {MyCTX}. The quote forces the context to be created if it did not exist. The {file://} URL is followed by a third |nl-/| for the directory spec. *newlisp-function-log* *nl-log* FUNCTION: log~ {syntax:} (log {num}) + {syntax:} (log {num} {num-base}) In the first syntax, the expression in {num} is evaluated and the natural logarithmic function is calculated from the result. > (log 1) ;→ 0 (log (exp 1)) ;→ 1 < In the second syntax, an arbitrary base can be specified in {num-base}. > (log 1024 2) ;→ 10 (log (exp 1) (exp 1)) ;→ 1 < See also |nl-exp|, which is the inverse function to |nl-log| with base *{e}* (2.718281828). *newlisp-function-lookup* *nl-lookup* FUNCTION: lookup~ {syntax:} (lookup {exp-key} {list-assoc} [{int-index} [{exp-default}]]) Finds in {list-assoc} an association, the key element of which has the same value as {exp-key}, and returns the {int-index} element of association (or the last element if {int-index} is absent). Optionally, {exp-default} can be specified, which is returned if an association matching {exp-key} cannot be found. If the {exp-default} is absent and no association has been found, {nil} is returned. See also |nl-Indexing elements of strings and lists|. |nl-lookup| is similar to |nl-assoc| but goes one step further by extracting a specific element found in the list. > (set 'params '( (name "John Doe") (age 35) (gender "M") (balance 12.34) )) (lookup 'age params) ;→ 35 ; use together with setf to modify and association list (setf (lookup 'age params) 42) ;→ 42 (lookup 'age params) ;→ 42 (set 'persons '( ("John Doe" 35 "M" 12.34) ("Mickey Mouse" 65 "N" 12345678) )) (lookup "Mickey Mouse" persons 2) ;→ "N" (lookup "Mickey Mouse" persons -3) ;→ 65 (lookup "John Doe" persons 1) ;→ 35 (lookup "John Doe" persons -2) ;→ "M" (lookup "Jane Doe" persons 1 "N/A") ;→ "N/A" < See also |nl-assoc| [[lower-case]] function::lower-case[utf8] {syntax:} (lower-case {str}) Converts the characters of the string in {str} to lowercase. A new string is created, and the original is left unaltered. > (lower-case "HELLO WORLD") ;→ "hello world" (set 'Str "ABC") (lower-case Str) ;→ "abc" Str ;→ "ABC" < See also the |nl-upper-case| and |nl-title-case| functions. *newlisp-function-macro?* *nl-macro?* FUNCTION: macro?~ {syntax:} (macro? {exp}) returns {true} if {exp} evaluates to a lambda-macro expression; otherwise, {nil} is returned. > (define-macro (mysetq lv rv) (set lv (eval rv))) (macro? mysetq) ;→ true < *newlisp-function-main-args* *nl-main-args* FUNCTION: main-args~ {syntax:} (main-args) + {syntax:} (main-args {int-index}) |nl-main-args| returns a list with several string members, one for program invocation and one for each of the command-line arguments. > newlisp 1 2 3 > (main-args) ("/usr/bin/newlisp" "1" "2" "3") < After {newlisp 1 2 3} is executed at the command prompt, |nl-main-args| returns a list containing the name of the invoking program and three command-line arguments. Optionally, |nl-main-args| can take an {int-index} for indexing into the list. Note that an index out of range will cause {nil} to be returned, not the last element of the list like in list-indexing. > newlisp a b c > (main-args 0) "/usr/bin/newlisp" > (main-args -1) "c" > (main-args 2) "b" > (main-args 10) nil < Note that when newLISP is executed from a script, |nl-main-args| also returns the {name} of the script as the second argument: > #!/usr/bin/newlisp # # script to show the effect of 'main-args' in script file (print (main-args) "\n") (exit) # end of script file ;; execute script in the OS shell: script 1 2 3 ("/usr/bin/newlisp" "./script" "1" "2" "3") < Try executing this script with different command-line parameters. *newlisp-function-make-dir* *nl-make-dir* FUNCTION: make-dir~ {syntax:} (make-dir {str-dir-name} [{int-mode}]) Creates a directory as specified in {str-dir-name}, with the optional access mode {int-mode}. Returns {true} or {nil} depending on the outcome. If no access mode is specified, most Unix systems default to {drwxr-xr-x}. On Unix systems, the access mode specified will also be masked by the OS's {user-mask} set by the system administrator. The {user-mask} can be retrieved on Unix systems using the command {umask} and is usually {0022} (octal), which masks write (and creation) permission for non-owners of the file. > ;; 0 (zero) in front of 750 makes it an octal number (make-dir "adir" 0750) < This example creates a directory named {adir} in the current directory with an access mode of {0750} (octal 750 = {drwxr-x---}). *newlisp-function-map* *nl-map* FUNCTION: map~ {syntax:} (map {exp-functor} {list-args-1} [{list-args-2} ... ]) Successively applies the primitive function, defined function, or lambda expression {exp-functor} to the arguments specified in _list-args-1, list-args-2—_, returning all results in a list. > (map + '(1 2 3) '(50 60 70)) ;→ (51 62 73) (map if '(true nil true nil true) '(1 2 3 4 5) '(6 7 8 9 10)) ;→ '(1 7 3 9 5) (map (fn (x y) (* x y)) '(3 4) '(20 10)) ;→ (60 40) < The second example shows how to dynamically create a function for |nl-map|: > (define (foo op p) (append (lambda (x)) (list (list op p 'x)))) < We can also use the shorter |nl-fn|: > (define (foo op p) (append (fn (x)) (list (list op p 'x)))) < {foo} now works like a function-maker: > (foo 'add 2) ;→ (lambda (x) (add 2 x)) (map (foo add 2) '(1 2 3 4 5)) ;→ (3 4 5 6 7) (map (foo mul 3) '(1 2 3 4 5)) ;→ (3 6 9 12 15) < Note that the quote before the operand can be omitted because primitives evaluate to themselves in newLISP. By incorporating |nl-map| into the function definition, we can do the following: > (define (list-map op p lst) (map (lambda (x) (op p x)) lst)) (list-map + 2 '(1 2 3 4)) ;→ (3 4 5 6) (list-map mul 1.5 '(1 2 3 4)) ;→ (1.5 3 4.5 6) < |nl-map| also sets the internal list index {$idx}. > (map (fn (x) (list $idx x)) '(a b c)) ;→ ((0 a) (1 b) (2 c)) < The number of arguments used is determined by the length of the first argument list. Arguments missing in other argument lists cause map to stop collecting parameters for that level of arguments. This ensures that the nth parameter list gets converted to the nth column during the transposition occurring. If an argument list contains too many elements, the extra ones will be ignored. Special forms which use parentheses as syntax cannot be mapped (i.e. |nl-case|). *newlisp-function-mat* *nl-mat* FUNCTION: mat~ {syntax:} (mat {+} | {-} | {*} | {/} {matrix-A matrix-B}) + {syntax:} (mat {+} | {-} | {*} | {/} {matrix-A number}) Using the first syntax, this function performs fast floating point scalar operations on two-dimensional matrices in {matrix-A} or {matrix-B}. The type of operation is specified by one of the four arithmetic operators |nl-+|, |nl--|, |nl-star|, or |nl-/|. This type of arithmetic operator is typically used for integer operations in newLISP. In the case of |nl-mat|, however, all operations will be performed as floating point operations (|nl-add|, |nl-sub|, |nl-mul|, |nl-div|). Matrices in newLISP are two-dimensional lists or arrays. Internally, newLISP translates lists and arrays into fast, accessible C-language data objects. This makes matrix operations in newLISP as fast as those coded directly in C. The same is true for the matrix operations |nl-multiply| and |nl-invert|. > (set 'A '((1 2 3) (4 5 6))) (set 'B A) (mat + A B) ;→ ((2 4 6) (8 10 12)) (mat - A B) ;→ ((0 0 0) (0 0 0)) (mat * A B) ;→ ((1 4 9) (16 25 36)) (mat / A B) ;→ ((1 1 1) (1 1 1)) ; specify the operator in a variable (set 'op +) (mat op A B) ;→ ((2 4 6) (8 10 12)) < Using the second syntax, all cells in {matrix-A} are operated on with a scalar in {number}: > (mat + A 5) ;→ ((6 7 8) (9 10 11)) (mat - A 2) ;→ ((-1 0 1) (2 3 4)) (mat * A 3) ;→ ((3 6 9) (12 15 18)) (mat / A 10) ;→ ((.1 .2 .3) (.4 .5 .6)) < See also the other matrix operations |nl-det|, |nl-invert|, |nl-multiply|, and |nl-transpose|. *newlisp-function-match* *nl-match* FUNCTION: match~ {syntax:} (match {list-pattern} {list-match} [{bool}]) The pattern in {list-pattern} is matched against the list in {list-match}, and the matching expressions are returned in a list. The three wildcard characters {?}, |nl-+|, and |nl-star| can be used in {list-pattern}. Wildcard characters may be nested. |nl-match| returns a list of matched expressions. For each {?} (question mark), a matching expression element is returned. For each |nl-+| (plus sign) or |nl-star| (asterisk), a list containing the matched elements is returned. If the pattern cannot be matched against the list in {list-match}, |nl-match| returns {nil}. If no wildcard characters are present in the pattern an empty list is returned. Optionally, the Boolean value {true} (or any other expression not evaluating to {nil}) can be supplied as a third argument. This causes |nl-match| to show all elements in the returned result. |nl-match| is frequently employed as a functor parameter in |nl-find|, |nl-ref|, |nl-ref-all| and |nl-replace| and is internally used by |nl-find-all| for lists. > (match '(a ? c) '(a b c)) ;→ (b) (match '(a ? ?) '(a b c)) ;→ (b c) (match '(a ? c) '(a (x y z) c)) ;→ ((x y z)) (match '(a ? c) '(a (x y z) c) true) ;→ (a (x y z) c) (match '(a ? c) '(a x y z c)) ;→ nil (match '(a * c) '(a x y z c)) ;→ ((x y z)) (match '(a (b c ?) x y z) '(a (b c d) x y z)) ;→ (d) (match '(a (*) x ? z) '(a (b c d) x y z)) ;→ ((b c d) y) (match '(+) '()) ;→ nil (match '(+) '(a)) ;→ ((a)) (match '(+) '(a b)) ;→ ((a b)) (match '(a (*) x ? z) '(a () x y z)) ;→ (() y) (match '(a (+) x ? z) '(a () x y z)) ;→ nil < Note that the |nl-star| operator tries to grab the fewest number of elements possible, but |nl-match| backtracks and grabs more elements if a match cannot be found. The |nl-+| operator works similarly to the |nl-star| operator, but it requires at least one list element. The following example shows how the matched expressions can be bound to variables. > (map set '(x y) (match '(a (? c) d *) '(a (b c) d e f))) x ;→ b y ;→ (e f) < Note that |nl-match| for strings has been eliminated. For more powerful string matching, use |nl-regex|, |nl-find|, |nl-find-all| or |nl-parse|. |nl-unify| is another function for matching expressions in a PROLOG like manner. *newlisp-function-max* *nl-max* FUNCTION: max~ {syntax:} (max {num-1} [{num-2} ... ]) Evaluates the expressions {num-1}— and returns the largest number. > (max 4 6 2 3.54 7.1) ;→ 7.1 < See also the |nl-min| function. *newlisp-function-member* *nl-member* FUNCTION: member~ {syntax:} (member {exp} {list}) + {syntax:} (member {str-key} {str} [{num-option}]) In the first syntax, |nl-member| searches for the element {exp} in the list {list}. If the element is a member of the list, a new list starting with the element found and the rest of the original list is constructed and returned. If nothing is found, {nil} is returned. When specifying {num-option}, |nl-member| performs a regular expression search. > (set 'aList '(a b c d e f g h)) ;→ (a b c d e f g h) (member 'd aList) ;→ (d e f g h) (member 55 aList) ;→ nil < In the second syntax, |nl-member| searches for {str-key} in {str}. If {str-key} is found, all of {str} (starting with {str-key}) is returned. {nil} is returned if nothing is found. > (member "LISP" "newLISP") ;→ "LISP" (member "LI" "newLISP") ;→ "LISP" (member "" "newLISP") ;→ "newLISP" (member "xyz" "newLISP") ;→ nil (member "li" "newLISP" 1) ;→ "LISP" < See also the related functions |nl-slice| and |nl-find|. *newlisp-function-min* *nl-min* FUNCTION: min~ {syntax:} (min {num-1} [{num-2} ... ]) Evaluates the expressions {num-1}— and returns the smallest number. > (min 4 6 2 3.54 7.1) ;→ 2 < See also the |nl-max| function. *newlisp-function-mod* *nl-mod* FUNCTION: mod~ {syntax:} (mod {num-1} {num-2} [{num-3} ... ]) + {syntax:} (mod {num-1}) Calculates the modular value of the numbers in {num-1} and {num-2}. |nl-mod| computes the remainder from the division of the numerator {num-i} by the denominator {num-i + 1}. Specifically, the return value is {numerator - n * denominator}, where {n} is the quotient of the numerator divided by the denominator, rounded towards zero to an integer. The result has the same sign as the numerator and its magnitude is less than the magnitude of the denominator. In the second syntax {1} is assumed for {num-2} and the result is the fractional part of {num-1}. > (mod 10.5 3.3) ;→ 0.6 (mod -10.5 3.3) ;→ -0.6 (mod -10.5) ;→ -0.5 < Use the |nl-%| (percent sign) function when working with integers only. *newlisp-function-mul* *nl-mul* FUNCTION: mul~ {syntax:} (mul {num-1} {num-2} [{num-3} ... ]) Evaluates all expressions {num-1}—, calculating and returning the product. |nl-mul| can perform mixed-type arithmetic, but it always returns floating point numbers. Any floating point calculation with {NaN} also returns {NaN}. > (mul 1 2 3 4 5 1.1) ;→ 132 (mul 0.5 0.5) ;→ 0.25 < *newlisp-function-multiply* *nl-multiply* FUNCTION: multiply~ {syntax:} (multiply {matrix-A} {matrix-B}) Returns the matrix multiplication of matrices in {matrix-A} and {matrix-B}. If {matrix-A} has the dimensions {n} by {m} and {matrix-B} the dimensions {k} by {l} ({m} and {k} must be equal), the result is an {n} by {l} matrix. { multiply} can perform mixed-type arithmetic, but the results are always double precision floating points, even if all input values are integers. The dimensions of a matrix are determined by the number of rows and the number of elements in the first row. For missing elements in non-rectangular matrices, {0.0} is assumed. A matrix can either be a nested list or |nl-array|. > (set 'A '((1 2 3) (4 5 6))) (set 'B '((1 2) (1 2) (1 2))) (multiply A B) ;→ ((6 12) (15 30)) (set 'v '(10 20 30)) (multiply A (transpose (list v))) ;→ ((140) (320)) < When multiplying a matrix with a vector of {n} elements, the vector must be transformed into {n} rows by {1} column matrix using |nl-transpose|. All operations shown here on lists can be performed on arrays, as well. See also the matrix operations |nl-det|, |nl-invert|, |nl-mat| and |nl-transpose|. *newlisp-function-name* *nl-name* FUNCTION: name~ This function is deprecated, use |nl-term| instead. *newlisp-function-NaN?* *nl-NaN?* FUNCTION: NaN?~ {syntax:} (NaN? {float}) Tests if the result of a floating point math operation is a {NaN}. Certain floating point operations return a special IEEE 754 number format called a {NaN} for 'Not a Number'. > ; floating point operation on NaN yield NaN (set 'x (sqrt -1)) ;→ NaN (NaN? x) ;→ true (add x 123) ;→ NaN (mul x 123) ;→ NaN ; integer operations treat NaN as zero (+ x 123) ;→ 123 (* x 123) ;→ 0 ; comparisons with NaN values yield nil (> x 0) ;→ nil (<= x 0) ;→ nil (= x x) ;→ nil (set 'infinity (mul 1.0e200 1.0e200)) ;→ inf (NaN? (sub infinity infinity)) ;→ true < Note that all floating point arithmetic operations with a {NaN} yield a {NaN}. All comparisons with {NaN} return {nil}, but {true} when comparing to itself. Comparison with itself, however, would result in {not} {true} when using ANSI C. Integer operations treat {NaN} as {0} (zero) values. See also |nl-inf?| for testing a floating point value for infinity. *newlisp-function-net-accept* *nl-net-accept* FUNCTION: net-accept~ {syntax:} (net-accept {int-socket}) Accepts a connection on a socket previously put into listening mode. Returns a newly created socket handle for receiving and sending data on this connection. > (set 'socket (net-listen 1234)) (net-accept socket) < Note that for ports less than 1024, newLISP must be started in superuser mode on Unix-like operating systems. See also the files {server} and {client} examples in the {examples/} directory of the source distribution. *newlisp-function-net-close* *nl-net-close* FUNCTION: net-close~ {syntax:} (net-close {int-socket} [{true}]) Closes a network socket in {int-socket} that was previously created by a |nl-net-connect| or |nl-net-accept| function. Returns {true} on success and {nil} on failure. > (net-close aSock) < The optional {true} flag suppresses immediate shutdown of sockets by waiting for pending data transmissions to finish. *newlisp-function-net-connect* *nl-net-connect* FUNCTION: net-connect~ {syntax:} (net-connect {str-remote-host} {int-port} [{int-timeout-ms}]) + {syntax:} (net-connect {str-remote-host} {int-port} [{str-mode} [{int-ttl}]]) + {syntax:} (net-connect {str-file-path}) In the first syntax, connects to a remote host computer specified in {str-remote-host} and a port specified in {int-port}. Returns a socket handle after having connected successfully; otherwise, returns {nil}. > (set 'socket (net-connect "example.com" 80)) (net-send socket "GET /\r\n\r\n") (net-receive socket buffer 10000) (println buffer) (exit) < If successful, the |nl-net-connect| function returns a socket number which can be used to send and receive information from the host. In the example a HTTP GET request is sent and subsequently a web page received. Note that newLISP has already a buit-in function |nl-get-url| offering the same functionality. Optionally a timeout value {int-timeout} in milli seconds can be specified. Without a timeout value the function will wait up to 10 seconds for an open port. With a timeout value the function can be made to return on an unavailable port much earlier or later. The following example shows a port scanner looking for open ports: > (set 'host (main-args 2)) (println "Scanning: " host) (for (port 1 1024) (if (set 'socket (net-connect host port 500)) (println "open port: " port " " (or (net-service port "tcp") "")) (print port "\r")) ) < The programs takes the host string from the shell command line as either a domain name or an IP number in dot notation then tries to open each port from 1 to 1024. For each openport the port number and the service description string is printed. If no description is available, an empty string "" is output. For closed ports the function outputs numbers in the shell window staying on the same line. On Unix {net-connnect} may return with {nil} before the timeout expires, when the port is not available. On Win32 |nl-net-connect| will always wait for the timout to expire before failing with {nil}. UDP communications ^^^^^^^^^^^^^^^^^^ In the second syntax, a third parameter, the string {"udp"} or {"u"} can be specified in the optional {str-mode} to create a socket suited for UDP (User Datagram Protocol) communications. In UDP mode, |nl-net-connect| does {not} try to connect to the remote host, but creates the socket and binds it to the remote address, if an address is specified. A subsequent |nl-net-send| will send a UDP packet containing that target address. When using |nl-net-send-to|, only one of the two functions |nl-net-connect| or |nl-net-send-to| should provide a target address. The other function should specify and empty string {""} as the target address. > ;; example server (net-listen 4096 "226.0.0.1" "udp") ;→ 5 (net-receive-from 5 20) ;; example client I (net-connect "226.0.0.1" 4096 "udp") ;→ 3 (net-send 3 "hello") ;; example client II (net-connect "" 4096 "udp") ;→ 3 (net-send-to "226.0.0.1" 4096 "hello" 3) < The functions |nl-net-receive| and |nl-net-receive-from| can both be used and will perform UDP communications when the {"udp"} option as been used in |nl-net-listen| or |nl-net-connect|. |nl-net-select| and |nl-net-peek| can be used to check for received data in a non-blocking fashion. |nl-net-listen| binds a specific local address and port to the socket. When |nl-net-connect| is used, the local address and port will be picked by the socket-stack functions of the host OS. UDP multicast communications ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ When specifying {"multi"} or {"m"} as a third parameter for {str-mode}, a socket for UDP multicast communications will be created. Optionally, the fourth parameter {int-ttl} can be specified as a TTL (time to live) value. If no {int-ttl} value is specified, a value of 3 is assumed. Note that specifying UDP multicast mode in |nl-net-connect| does not actually establish a connection to the target multicast address but only puts the socket into UDP multicasting mode. On the receiving side, use |nl-net-listen| together with the UDP multicast option. > ;; example client I (net-connect "" 4096 "multi") ;→ 3 (net-send-to "226.0.0.1" 4096 "hello" 3) ;; example client II (net-connect "226.0.0.1" 4096 "multi") ;→ 3 (net-send 3 "hello") ;; example server (net-listen 4096 "226.0.0.1" "multi") ;→ 5 (net-receive-from 5 20) ;→ ("hello" "192.168.1.94" 32769) < On the server side, |nl-net-peek| or |nl-net-select| can be used for non-blocking communications. In the above example, the server would block until a datagram is received. The address {226.0.0.1} is just one multicast address in the Class D range of multicast addresses from {224.0.0.0} to {239.255.255.255}. The |nl-net-send| and |nl-net-receive| functions can also be used instead of |nl-net-send-to| and |nl-net-receive-from|. UDP broadcast communications ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Specifying the string {"broadcast"} or {"b"} in the third parameter, {str-mode}, causes UDP broadcast communications to be set up. In this case, the broadcast address ending in 255 is used. > ;; example client (net-connect "192.168.2.255" 3000 "broadcast") ;→ 3 (net-send 3 "hello") ;; example server (net-listen 3000 "" "udp") ;→ 5 (net-receive 5 buff 10) buff ;→ "hello" ;; or (net-receive-from 5 10) ;→ ("hello" "192.168.2.1" 46620) < Note that on the receiving side, |nl-net-listen| should be used with the default address specified with an {""} (empty string). Broadcasts will not be received when specifying an address. As with all UDP communications, |nl-net-listen| does not actually put the receiving side in listen mode, but rather sets up the sockets for the specific UDP mode. The |nl-net-select| or |nl-net-peek| functions can be used to check for incoming communications in a non-blocking fashion. Local domain Unix sockets ^^^^^^^^^^^^^^^^^^^^^^^^^ In the third syntax, |nl-net-connect| connects to a server on the local file system via a {local domain Unix socket} named using {str-file-path}. Returns a socket handle after having connected successfully; otherwise, returns {nil}. > (net-connect "/tmp/mysocket") ;→ 3 ; on OS/2 use "\\socket\\" prefix (net-connect "\\socket\\mysocket") < A {local domain} file system socket is created and returned. On the server side, {local domain} sockets have been created using |nl-net-listen| and |nl-net-accept|. After the connection has been established the functions |nl-net-select|, |nl-net-send| and |nl-net-receive| can be used as usual for TCP/IP stream communications. This type of connection can be used as a fast bi-directional communications channel between processes on the same file system. This type of connection is not available on Win32 platforms. *newlisp-function-net-error* *nl-net-error* FUNCTION: net-error~ {syntax:} (net-error) + {syntax:} (net-error {int-error}) Retrieves the last error that occurred when calling a any of the following functions: |nl-net-accept|, |nl-net-connect|, |nl-net-eval|, |nl-net-listen|, |nl-net-lookup|, |nl-net-receive|, |nl-net-receive-udp|, |nl-net-select|, |nl-net-send|, |nl-net-send-udp|, and |nl-net-service|. Whenever one of these functions fails, it returns {nil} and |nl-net-error| can be used to retrieve more information. Functions that communicate using sockets close the socket automatically and remove it from the |nl-net-sessions| list. Each successful termination of a |nl-net-star| function clears the error number. The following messages are returned: [cols="1<,5<",width="40%",options="header",] |===================================== |no |description |1 |Cannot open socket |2 |DNS resolution failed |3 |Not a valid service |4 |Connection failed |5 |Accept failed |6 |Connection closed |7 |Connection broken |8 |Socket send() failed |9 |Socket recv() failed |10 |Cannot bind socket |11 |Too many sockets in net-select |12 |Listen failed |13 |Badly formed IP |14 |Select failed |15 |Peek failed |16 |Not a valid socket |17 |Cannot unblock socket |18 |Operation timed out |19 |HTTP bad formed URL |20 |HTTP file operation failed |21 |HTTP transfer failed |22 |HTTP invalid response from server |23 |HTTP no response from server |24 |HTTP document empty |25 |HTTP error in header |26 |HTTP error in chunked format |===================================== > (net-error) ;→ nil (net-connect "jhghjgkjhg" 80) ;→ nil (net-error) ;→ (2 "ERR: "DNS resolution failed") < When {int-error} is specified the number and error text for that error number is returned. > (net-error 10) ;→ (10 "Cannot bind socket") < See also |nl-last-error| and |nl-sys-error|. *newlisp-function-net-eval* *nl-net-eval* FUNCTION: net-eval~ {syntax:} (net-eval {str-host} {int-port} {exp} [{int-timeout} [{func-handler}]]) + {syntax:} (net-eval '( ({str-host} {int-port} {exp}) ... ) [{int-timeout} [{func-handler}]]) Can be used to evaluate source remotely on one or more newLISP servers. This function handles all communications necessary to connect to the remote servers, send source for evaluation, and wait and collect responses. The expression in {exp} evaluates to either a string or an expression which will be evaluated remotely in the environment of the target node. The remote TCP/IP servers are started in the following way: > newlisp -c -d 4711 & ; or with logging connections newlisp -l -c -d 4711 & ; communicate via Uix local domain socket newlisp -c /tmp/mysocket < Instead of {4711}, any other port number can be used. Multiple nodes can be started on different hosts and with the same or different port numbers. The {-l} or {-L} logging options can be specified to log connections and remote commands. The {-d} daemon mode allows newLISP to maintain state between connections. When keeping state between connections is not desired, the |nl-inetd daemon mode| offers more advantages. The Internet {inetd} or {xinetd} services daemon will start a new newLISP process for each client connection. This makes for much faster servicing of multiple connections. In {-d} daemon mode, each new client request would have to wait for the previous request to be finished. See the chapter |nl-inetd daemon mode| on how to configure this mode correctly. In the first syntax, |nl-net-eval| talks to only one remote newLISP server node, sending the host in {str-host} on port {int-port} a request to evaluate the expression {exp}. If {int-timeout} is not given, |nl-net-eval| will wait up to 60 seconds for a response after a connection is made. Otherwise, if the timeout in milliseconds has expired, {nil} is returned; else, the evaluation result of {exp} is returned. > ; the code to be evaluated is given in a quoted expression (net-eval "192.168.1.94" 4711 '(+ 3 4)) ;→ 7 ; expression as a string (net-eval "192.168.1.94" 4711 "(+ 3 4)") ;→ 7 ; with timeout (net-eval "192.168.1.94" 4711 '(+ 3 4) 1) ;→ nil ; timeout to short (net-error) ;→ (17 "ERR: Operation timed out") (net-eval "192.168.1.94" 4711 '(+ 3 4) 1000) ;→ 7 ; program contained in a variable (set 'prog '(+ 3 4)) (net-eval "192.168.1.94" 4711 prog) ;→ 7 ; specify a local-domain Unix socket (not available on Win32) (net-eval "/tmp/mysocket" 0 '(+ 3 4)) ;→ 7 < The second syntax of |nl-net-eval| returns a list of the results after all of the responses are collected or timeout occurs. Responses that time out return {nil}. The last example line shows how to specify a local-domain Unix socket specifying the socket path and a port number of {0}. Connection errors or errors that occur when sending information to nodes are returned as a list of error numbers and descriptive error strings. See the function |nl-net-error| for a list of potential error messages. > ; two different remote nodes different IPs (net-eval '( ("192.168.1.94" 4711 '(+ 3 4)) ("192.168.1.95" 4711 '(+ 5 6)) ) 5000) ;→ (7 11) ; two persistent nodes on the same CPU different ports (net-eval '( ("localhost" 8081 '(foo "abc")) ("localhost" 8082 '(myfunc 123)') ) 3000) ; inetd or xinetd nodes on the same server and port ; nodes are loaded on demand (net-eval '( ("localhost" 2000 '(foo "abc")) ("localhost" 2000 '(myfunc 123)) ) 3000) < The first example shows two expressions evaluated on two different remote nodes. In the second example, both nodes run on the local computer. This may be useful when debugging or taking advantage of multiple CPUs on the same computer. When specifying {0} for the port number , |nl-net-eval| takes the host name as the file path to the local-domain Unix socket. Note that definitions of {foo} and {myfunc} must both exist in the target environment. This can be done using a |nl-net-eval| sending |nl-define| statements before. It also can be done by preloading code when starting remode nodes. When nodes are inetd or xinetd-controlled, several nodes may have the same IP address and port number. In this case, the Unix daemon inetd or xinetd will start multiple newLISP servers on demand. This is useful when testing distributed programs on just one machine. The last example illustrates this case. It is also useful on multi core CPUs, where the platform OS can distribute different processes on to different CPU cores. The source sent for evaluation can consist of entire multiline programs. This way, remote nodes can be loaded with programs first, then specific functions can be called. For large program files, the functions |nl-put-url| or |nl-save| (with a URL file name) can be used to transfer programs. The a |nl-net-eval| statement could load these programs. Optionally, a handler function can be specified. This function will be repeatedly called while waiting and once for every remote evaluation completion. > (define (myhandler param) (if param (println param)) ) (set 'Nodes '( ("192.168.1.94" 4711) ("192.168.1.95" 4711) )) (set 'Progs '( (+ 3 4) (+ 5 6) )) (net-eval (map (fn (n p) (list (n 0) (n 1) p)) Nodes Progs) 5000 myhandler) ;→ ("192.168.1.94" 4711 7) ("192.168.1.95" 4711 11) < The example shows how the list of node specs can be assembled from a list of nodes and sources to evaluate. This may be useful when connecting to a larger number of remote nodes. > (net-eval (list (list (Nodes 0 0) (Nodes 0 1) (Progs 0)) (list (Nodes 1 0) (Nodes 1 1) (Progs 1)) ) 3000 myhandler) < While waiting for input from remote hosts, {myhandler} will be called with {nil} as the argument to {param}. When a remote node result is completely received, {myhandler} will be called with {param} set to a list containing the remote host name or IP number, the port, and the resulting expression. |nl-net-eval| will return {true} before a timeout or {nil} if the timeout was reached or exceeded. All remote hosts that exceeded the timeout limit will contain a {nil} in their results list. For a longer example see this program: http://www.newlisp.org/syntax.cgi?code/mapreduce.txt[mapreduce]. The example shows how a word counting task gets distributed to three remote nodes. The three nodes count words in different texts and the master node receives and consolidates the results. *newlisp-function-net-interface* *nl-net-interface* FUNCTION: net-interface~ {syntax:} (net-interface {str-ip-addr}) + {syntax:} (net-interface) Sets the default local interface address to be used for network connections. If not set then network functions will default to an internal default address, except when overwritten by an optional interface address given in |nl-net-listen|. When no {str-ip-addr} is specified, the current default is returned. If the |nl-net-interface| has not been used yet to specify an IP address, the address {0.0.0.0} is returned. This means that all network routines will use the default address preconfigured by the underlying operating system. This function has only usage on multihomed servers with either multiple network interface hardware or otherwise supplied multiple IP numbers. On all other machines network functions will automatically select the single network interface installed. On error the function returns {nil} and |nl-net-error| can be used to report the error. > (net-interface "192.168.1.95") ;→ "192.168.1.95" (net-interface "localhost") ;→ "127.0.0.1" < An interface address can be defined as either an IP address or a name. The return value is the address given in {str-ip-addr} *newlisp-function-net-ipv* *nl-net-ipv* FUNCTION: net-ipv~ {syntax:} (net-ipv {int-version}) + {syntax:} (net-ipv) Switches between IPv4 and IPv6 internet protocol versions. {int-version} contains either a 4 for IPv4 or a 6 for IPv6. When no parameter is given, |nl-net-ipv| returns the current setting. > (net-ipv) ;→ 4 (net-ipv 6) ;→ 6 < By default newLISP starts up in IPv4 mode. The IPv6 protocol mode can also be specified from the commandline when starting newlisp: > newlisp -6 < Once a socket is connected with either |nl-net-connect| or listened on with |nl-net-listen|, the |nl-net-accept|, |nl-net-select|, |nl-net-send|, |nl-net-receive| and |nl-net-receive-from| functions automatically adjust to the address protocol used when creating the sockets. Different connections with different IPv4/6 settings can be open at the same time. Note, that currently |nl-net-packet| does not support IPv6 and will work in IPv4 mode regardless of settings. *newlisp-function-net-listen* *nl-net-listen* FUNCTION: net-listen~ {syntax:} (net-listen {int-port} [{str-ip-addr} [{str-mode}]]) + {syntax:} (net-listen {str-file-path}) Listens on a port specified in {int-port}. A call to |nl-net-listen| returns immediately with a socket number, which is then used by the blocking |nl-net-accept| function to wait for a connection. As soon as a connection is accepted, |nl-net-accept| returns a socket number that can be used to communicate with the connecting client. > (set 'port 1234) (set 'listen (net-listen port)) (unless listen (begin (print "listening failed\n") (exit))) (print "Waiting for connection on: " port "\n") (set 'connection (net-accept listen)) (if connection (while (net-receive connection buff 1024 "\n") (print buff) (if (= buff "\r\n") (exit))) (print "Could not connect\n")) < The example waits for a connection on port 1234, then reads incoming lines until an empty line is received. Note that listening on ports lower than 1024 may require superuser access on Unix systems. On computers with more than one interface card, specifying an optional interface IP address or name in {str-ip-addr} directs |nl-net-listen| to listen on the specified address. > ;; listen on a specific address (net-listen port "192.168.1.54") < Local domain Unix sockets ^^^^^^^^^^^^^^^^^^^^^^^^^ In the second syntax, |nl-net-listen| listens for a client on the local file system via a {local domain Unix socket} named using {str-file-path}. If successful, returns a socket handle that can be used with |nl-net-accept| to accept a client connection; otherwise, returns {nil}. > (net-listen "/tmp/mysocket") ;→ 5 ; on OS/2 use "\\socket\\" prefix (net-listen "\\socket\\mysocket") (net-accept 5) < A {local domain} file system socket is created and listened on. A client will try to connect using the same {str-file-path}. After a connection has been accepted the functions |nl-net-select|, |nl-net-send| and |nl-net-receive| can be used as usual for TCP/IP stream communications. This type of connection can be used as a fast bi-directional communications channel between processes on the same file system. This type of connection is not available on Win32 platforms. UDP communications ^^^^^^^^^^^^^^^^^^ As a third parameter, the optional string {"udp"} or {"u"} can be specified in {str-mode} to create a socket suited for UDP (User Datagram Protocol) communications. A socket created in this way can be used directly with |nl-net-receive-from| to await incoming UDP data {without} using |nl-net-accept|, which is only used in TCP communications. The |nl-net-receive-from| call will block until a UDP data packet is received. Alternatively, |nl-net-select| or |nl-net-peek| can be used to check for ready data in a non-blocking fashion. To send data back to the address and port received with |nl-net-receive-from|, use |nl-net-send-to|. Note that |nl-net-peer| will not work, as UDP communications do not maintain a connected socket with address information. > (net-listen 10002 "192.168.1.120" "udp") (net-listen 10002 "" "udp") < The first example listens on a specific network adapter, while the second example listens on the default adapter. Both calls return a socket number that can be used in subsequent |nl-net-receive|, |nl-net-receive-from|, |nl-net-send-to|, |nl-net-select|, or |nl-net-peek| function calls. Both a UDP server {and} UDP client can be set up using |nl-net-listen| with the {"udp"} option. In this mode, |nl-net-listen| does not really {listen} as in TCP/IP communications; it just binds the socket to the local interface address and port. For a working example, see the files {examples/client} and {examples/server} in the newLISP source distribution. Instead of |nl-net-listen| and the {"udp"} option, the functions |nl-net-receive-udp| and |nl-net-send-udp| can be used for short transactions consisting only of one data packet. |nl-net-listen|, |nl-net-select|, and |nl-net-peek| can be used to facilitate non-blocking reading. The listening/reading socket is not closed but is used again for subsequent reads. In contrast, when the |nl-net-receive-udp| and |nl-net-send-udp| pair is used, both sides close the sockets after sending and receiving. UDP multicast communications ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ If the optional string {str-mode} is specified as {"multi"} or {"m"}, |nl-net-listen| returns a socket suitable for multicasting. In this case, {str-ip-addr} contains one of the multicast addresses in the range {224.0.0.0} to {239.255.255.255}. |nl-net-listen| will register {str-ip-addr} as an address on which to receive multicast transmissions. This address should not be confused with the IP address of the server host. > ;; example client (net-connect "226.0.0.1" 4096 "multi") ;→ 3 (net-send-to "226.0.0.1" 4096 "hello" 3) ;; example server (net-listen 4096 "226.0.0.1" "multi") ;→ 5 (net-receive-from 5 20) ;→ ("hello" "192.168.1.94" 32769) < On the server side, |nl-net-peek| or |nl-net-select| can be used for non-blocking communications. In the example above, the server would block until a datagram is received. The |nl-net-send| and |nl-net-receive| functions can be used instead of |nl-net-send-to| and |nl-net-receive-from|. Packet divert sockets and ports ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ If {str-mode} is specified as {"divert"}, a divert socket can be created for a divert port in {int-port} on BSD like platforms. The content of IP address in {str-ip-addr} is ignored and can be specifed as an empty string. Only the {int-port} is relevant and will be bound to the raw socket returned. To use the divert option in |nl-net-listen|, newLISP must run in super-user mode. This option is only available on Unix like platforms. The divert socket will receive all raw packets diverted to the divert port. Packets may also be written back to a divert socket, in which case they re-enter OS kernel IP packet processing. Rules for packet diversion to the divert port must be defined using either the {ipfw} BSD or {ipchains} Linux configuration utilities. The |nl-net-receive-from| and |nl-net-send-to| functions are used to read and write raw packets on the divert socket created and returned by the |nl-net-listen| statement. The same address received by |nl-net-receive-from| is used in the |nl-net-send-to| call when re-injecting the packet: > ; rules have been previously configured for a divert port (set 'divertSocket (net-listen divertPort "" "divert")) (until (net-error) (set 'rlist (net-receive-from divertSocket maxBytes)) (set 'buffer (rlist 1)) ; buffer can be processed here before reinjecting (net-send-to (rlist 0) divertPort buffer divertSocket) ) < For more information see the Unix man pages for {divert} and the {ipfw} (BSDs) or {ipchains} (Linux) configuration utilities. *newlisp-function-net-local* *nl-net-local* FUNCTION: net-local~ {syntax:} (net-local {int-socket}) Returns the IP number and port of the local computer for a connection on a specific {int-socket}. > (net-local 16) ;→ ("204.179.131.73" 1689) < Use the |nl-net-peer| function to access the remote computer's IP number and port. *newlisp-function-net-lookup* *nl-net-lookup* FUNCTION: net-lookup~ {syntax:} (net-lookup {str-ip-number}) + {syntax:} (net-lookup {str-hostname} [{bool}]) Returns either a hostname string from {str-ip-number} in IP dot format or the IP number in dot format from {str-hostname}: > (net-lookup "209.24.120.224") ;→ "www.nuevatec.com" (net-lookup "www.nuevatec.com") ;→ "209.24.120.224" (net-lookup "216.16.84.66.sbl-xbl.spamhaus.org" true) ;→ "216.16.84.66" < Optionally, a {bool} flag can be specified in the second syntax. If the expression in {bool} evaluates to anything other than {nil}, host-by-name lookup will be forced, even if the name string starts with an IP number. *newlisp-function-net-packet* *nl-net-packet* FUNCTION: net-packet~ {syntax:} (net-packet {str-packet}) The function allows custom configured network packets to be sent via a {raw sockets} interface. The packet in {str-packet} must start with an IP (Internet Protocol) header followed by either a TCP, UDP or ICMP header and optional data. newLISP must be run with super user privileges, and this function is only available on Mac OS X, Linux and other Unix operating systems and only for IPv4. Currently |nl-net-packet| is IPv4 only and has been tested on MAC OS X, Linux and OpenBSD. On success the function returns the number of bytes sent. On failure the function returns {nil} and both, |nl-net-error| and |nl-sys-error|, should be inspected. When custom configured packets contains zeros in the checksum fields, |nl-net-packet| will calculate and insert the correct checksums. Already existing checksums stay untouched. The following example injects a UDP packet for IP number {192.168.1.92}. The IP header consists of 20 bytes ending with the target IP number. The following UDP header has a length of 8 bytes and is followed by the data string {Hello World}. The checksum bytes in both headers are left as {0x00 0x00} and will be recalculated internally. > ; packet as generated by: (net-send-udp "192.168.1.92" 12345 "Hello World") (set 'udp-packet (pack (dup "b" 39) '( 0x45 0x00 0x00 0x27 0x4b 0x8f 0x00 0x00 0x40 0x11 0x00 0x00 192 168 1 95 192 168 1 92 0xf2 0xc8 0x30 0x39 0x00 0x13 0x00 0x00 0x48 0x65 0x6c 0x6c 0x6f 0x20 0x57 0x6f 0x72 0x6c 0x64))) (unless (net-packet udp-packet) (println "net-error: " (net-error)) (println "sys-error: " (sys-error))) < The |nl-net-packet| function is used when testing net security. Its wrong application can upset the correct functioning of network routers and other devices connected to a network. For this reason the function should only be used on well isolated, private intra-nets and only by network professionals. For other examples of packet configuration, see the file {qa-specific-tests/qa-packet} in the newLISP source distribution. *newlisp-function-net-peek* *nl-net-peek* FUNCTION: net-peek~ {syntax:} (net-peek {int-socket}) Returns the number of bytes ready for reading on the network socket {int-socket}. If an error occurs or the connection is closed, {nil} is returned. > (set 'aSock (net-connect "aserver.com" 123)) (while ( = (net-peek aSock) 0) (do-something-else)) (net-receive aSock buff 1024) < After connecting, the program waits in a while loop until {aSock} can be read. Use the |nl-peek| function to check file descriptors and {stdin}. *newlisp-function-net-peer* *nl-net-peer* FUNCTION: net-peer~ {syntax:} (net-peer {int-socket}) Returns the IP number and port number of the remote computer for a connection on {int-socket}. > (net-peer 16) ;→ ("192.100.81.100" 13) < Use the |nl-net-local| function to access the local computer's IP number and port number. *newlisp-function-net-ping* *nl-net-ping* FUNCTION: net-ping~ {syntax:} (net-ping {str-address} [{int-timeout} [{int-count} {bool}]]]) + {syntax:} (net-ping {list-addresses} [{int-timeout} [{int-count} {bool}]]]) This function is only available on Unix-based systems and must be run in superuser mode, i.e. using: {sudo newlisp} to start newLISP on Mac OS X or other BSD's, or as the root user on Linux. Broadcast mode and specifying ranges with the |nl--| (hyphen) or {*} (star) are not available on IPv6 address mode. Since version 10.1.7, superuser mode is not required on Mac OS X. In the first syntax, |nl-net-ping| sends a ping ICMP 64-byte echo request to the address specified in {str-address}. If it is a broadcast address, the ICMP packet will be received by all addresses on the subnet. Note that for security reasons, many computers do not answer ICMP broadcast ping (ICMP_ECHO) requests. An optional timeout parameter can be specified in {int-timeout}. If no timeout is specified, a waiting time of 1000 milliseconds (one second) is assumed. |nl-net-ping| returns either a list of lists of IP strings and round-trip time in microseconds for which a response was received or an empty list if no response was received. A return value of {nil} indicates a failure. Use the |nl-net-error| function to retrieve the error message. If the message reads {Cannot open socket}, it is probably because newLISP is running without root permissions. newLISP can be started using: > sudo newlisp < Alternatively, newLISP can be installed with the set-user-ID bit set to run in superuser mode. > (net-ping "newlisp.org") ;→ (("66.235.209.72" 634080)) (net-ping "127.0.0.1") ;→ (("127.0.0.1" 115)) (net-ping "yahoo.com" 3000) ;→ nil < In the second syntax, |nl-net-ping| is run in {batch mode}. Only one socket is opened in this mode, but multiple ICMP packets are sent out—one each to multiple addresses specified in a list or specified by range. Packets are sent out as fast as possible. In this case, multiple answers can be received. If the same address is specified multiple times, the receiving IP address will be flooded with ICMP packets. To limit the number of responses to be waited for in broadcast or batch mode, an additional argument indicating the maximum number of responses to receive can be specified in {int-count}. Usage of this parameter can cause the function to return sooner than the specified timeout. When a given number of responses has been received, |nl-net-ping| will return before the timeout has occurred. Not specifying {int-count} or specifying {0} assumes an {int-count} equal to the number of packets sent out. As third optional parameter, a {true} value can be specified. This setting will return an error string instead of the response time, if the host does not answer. > (net-ping '("newlisp.org" "192.168.1.255") 2000 20) ;→ (("66.235.209.72" 826420) ("192.168.1.1" 124) ("192.168.1.254" 210)) (net-ping "192.168.1.*" 500) ; from 1 to 254 ;→ (("192.168.1.1" 120) ("192.168.1.2" 245) ("192.168.2.3" 180) ("192.168.2.254" 234)) (net-ping "192.168.1.*" 500 2) ; returns after 2 responses ;→ (("192.168.1.3" 115) ("192.168.1.1" 145)) (net-ping "192.168.1.1-10" 1000) ; returns after 1 second ;→ (("192.168.1.3" 196) ("192.168.1.1" 205)) (net-ping '("192.168.1.100-120" "192.168.1.124-132") 2000) ; returns after 2 seconds ;→ () < Broadcast or batch mode—as well as normal addresses and IP numbers or hostnames— can be mixed in one |nl-net-ping| statement by putting all of the IP specs into a list. The second and third lines show how the batch mode of |nl-net-ping| can be initiated by specifying the |nl-star| (asterisk) as a wildcard character for the last subnet octet in the IP number. The fourth and fifth lines show how an IP range can be specified for the last subnet octet in the IP number. |nl-net-ping| will iterate through all numbers from either 1 to 254 for the star |nl-star| or the range specified, sending an ICMP packet to each address. Note that this is different from the {broadcast} mode specified with an IP octet of {255}. While in broadcast mode, |nl-net-ping| sends out only one packet, which is received by multiple addresses. Batch mode explicitly generates multiple packets, one for each target address. When specifying broadcast mode, {int-count} should be specified, too. When sending larger lists of IPs in batch mode over one socket, a longer timeout may be necessary to allow enough time for all of the packets to be sent out over one socket. If the timeout is too short, the function |nl-net-ping| may return an incomplete list or the empty list {()}. In this case, |nl-net-error| will return a timeout error. On error, {nil} is returned and |nl-net-error| can be used to retrieve an error message. On some systems only lists up to a specific length can be handled regardless of the timeout specified. In this case, the range should be broken up into sub-ranges and used with multiple |nl-net-ping| invocations. In any case, |nl-net-ping| will send out packages as quickly as possible. *newlisp-function-net-receive* *nl-net-receive* FUNCTION: net-receive~ |nl-destructive| {syntax:} (net-receive {int-socket} {sym-buffer} {int-max-bytes} [{wait-string}]) Receives data on the socket {int-socket} into a string contained in {sym-buffer}. {sym-buffer} can also be a default functor specified by a context symbol for reference passing in and out of user-defined functions. A maximum of {int-max-bytes} is received. |nl-net-receive| returns the number of bytes read. If there is a break in the connection, {nil} is returned. The space reserved in {sym-buffer} is exactly the size of bytes read. Note that |nl-net-receive| is a blocking call and does not return until the data arrives at {int-socket}. Use |nl-net-peek| or |nl-net-select| to find out if a socket is ready for reading. Optionally, a {wait-string} can be specified as a fourth parameter. |nl-net-receive| then returns after a character or string of characters matching {wait-string} is received. The {wait-string} will be part of the data contained in {sym-buffer}. > (define (gettime) (net-connect "netcom.com" 13) (net-receive socket buf 256) (print buf "\n") (net-close socket)) < When calling {gettime}, the program connects to port 13 of the server netcom.com. Port 13 is a date-time service on most server installations. Upon connection, the server sends a string containing the date and time of day. > (define (net-receive-line socket sBuff) (net-receive socket sBuff 256 "\n")) (set 'bytesReceived (net-receive-line socket 'sm)) < The second example defines a new function {net-receive-line}, which returns after receiving a newline character (a string containing one character in this example) or 256 characters. The "\n" string is part of the contents of sBuff. Note that when the fourth parameter is specified, |nl-net-receive| is slower than the normal version because information is read character-by-character. In most situations, the speed difference can be neglected. *newlisp-function-net-receive-from* *nl-net-receive-from* FUNCTION: net-receive-from~ {syntax:} (net-receive-from {int-socket} {int-max-size}) |nl-net-receive-from| can be used to set up non-blocking UDP communications. The socket in {int-socket} must previously have been opened by either |nl-net-listen| or |nl-net-connect| (both using the {"udp"} option). {int-max-size} specifies the maximum number of bytes that will be received. On Linux/BSD, if more bytes are received, those will be discarded; on Win32, |nl-net-receive-from| returns {nil} and closes the socket. On success |nl-net-receive| returns a list of the data string, remote IP number and remote port used. On failure it returns {nil}. > ;; listen on port 1001 on the default address (net-listen 1001 "" "udp") ;→ 1980 ;; optionally poll for arriving data with 100ms timeout (while (not (net-select 1980 "r" 100000)) (do-something ... )) (net-receive-from 1980 20) ;→ ("hello" "192.168.0.5" 3240) ;; send answer back to sender (net-send-to "192.168.0.5" 3240 "hello to you" 1980) (net-close 1980) ; close socket < The second line in this example is optional. Without it, the |nl-net-receive-from| call would block until data arrives. A UDP server could be set up by listening and polling several ports, serving them as they receive data. Note that |nl-net-receive| could not be used in this case because it does not return the sender's address and port information, which are required to talk back. In UDP communications, the data packet itself contains the address of the sender, {not} the socket over which communication takes place. |nl-net-receive| can also be used for TCP/IP communications. See also the |nl-net-connect| function with the {"udp"} option and the |nl-net-send-to| function for sending UDP data packets over open connections. For blocking short UDP transactions, see the |nl-net-send-udp| and |nl-net-receive-udp| functions. *newlisp-function-net-receive-udp* *nl-net-receive-udp* FUNCTION: net-receive-udp~ {syntax:} (net-receive-udp {int-port} {int-maxsize} [{int-microsec} [{str-addr-if}]]) Receives a User Datagram Protocol (UDP) packet on port {int-port}, reading {int-maxsize} bytes. If more than {int-maxsize} bytes are received, bytes over {int-maxsize} are discarded on Linux/BSD; on Win32, |nl-net-receive-udp| returns {nil}. |nl-net-receive-udp| blocks until a datagram arrives or the optional timeout value in {int-microsec} expires. When setting up communications between datagram sender and receiver, the |nl-net-receive-udp| statement must be set up first. No previous setup using |nl-net-listen| or |nl-net-connect| is necessary. |nl-net-receive-udp| returns a list containing a string of the UDP packet followed by a string containing the sender's IP number and the port used. > ;; wait for datagram with maximum 20 bytes (net-receive-udp 10001 20) ;; or (net-receive-udp 10001 20 5000000) ; wait for max 5 seconds ;; executed on remote computer (net-send-udp "nuevatec.com" 1001 "Hello") ;→ 4 ;; returned from the net-receive-udp statement ;→ ("Hello" "128.121.96.1" 3312) ;; sending binary information (net-send-udp "ahost.com" 2222 (pack "c c c c" 0 1 2 3)) ;→ 4 ;; extracting the received info (set 'buff (first (net-receive-udp 2222 10))) (print (unpack "c c c c" buff)) ;→ (0 1 2 3) < See also the |nl-net-send-udp| function for sending datagrams and the |nl-pack| and |nl-unpack| functions for packing and unpacking binary information. To listen on a specified address on computers with more than one interface card, an interface IP address or name can be optionally specified in {str-addr-if}. When specifying {str-addr-if}, a timeout must also be specified in {int-wait}. As an alternative, UDP communication can be set up using |nl-net-listen|, or |nl-net-connect| together with the {"udp"} option to make non-blocking data exchange possible with |nl-net-receive-from| and |nl-net-send-to|. *newlisp-function-net-select* *nl-net-select* FUNCTION: net-select~ {syntax:} (net-select {int-socket} {str-mode} {int-micro-seconds}) + {syntax:} (net-select {list-sockets} {str-mode} {int-micro-seconds}) In the first form, |nl-net-select| finds out about the status of one socket specified in {int-socket}. Depending on {str-mode}, the socket can be checked if it is ready for reading or writing, or if the socket has an error condition. A timeout value is specified in {int-micro-seconds}. In the second syntax, |nl-net-select| can check for a list of sockets in {list-sockets}. The following value can be given for {str-mode}: {"read"} or {"r"} to check if ready for reading or accepting. + {"write"} or {"w"} to check if ready for writing. + {"exception"} or {"e"} to check for an error condition. + Read, send, or accept operations can be handled without blocking by using the |nl-net-select| function. |nl-net-select| waits for a socket to be ready for the value given in {int-micro-seconds}, then returns {true} or {nil} depending on the readiness of the socket. During the select loop, other portions of the program can run. On error, |nl-net-error| is set. When {-1} is specified for {int-micro-seconds}, |nl-net-select| will never time out. > (set 'listen-socket (net-listen 1001)) ;; wait for connection (while (not (net-select listen-socket "read" 1000)) (if (net-error) (print (net-error)))) (set 'connection (net-accept listen-socket)) (net-send connection "hello") ;; wait for incoming message (while (not (net-select connection "read" 1000)) (do-something)) (net-receive connection buff 1024) < When |nl-net-select| is used, several listen and connection sockets can be watched, and multiple connections can be handled. When used with a list of sockets, |nl-net-select| will return a list of ready sockets. The following example would listen on two sockets and continue accepting and servicing connections: > (set 'listen-list '(1001 1002)) ; accept-connection, read-connection and write-connection ; are userdefined functions (while (not (net-error)) (dolist (conn (net-select listen-list "r" 1000)) (accept-connection conn)) ; build an accept-list (dolist (conn (net-select accept-list "r" 1000)) (read-connection conn)) ; read on connected sockets (dolist (conn (net-select accept-list "w" 1000)) (write-connection conn))) ; write on connected sockets < In the second syntax, a list is returned containing all the sockets that passed the test; if timeout occurred, an empty list is returned. An error causes |nl-net-error| to be set. Note that supplying a nonexistent socket to |nl-net-select| will cause an error to be set in |nl-net-error|. *newlisp-function-net-send* *nl-net-send* FUNCTION: net-send~ {syntax:} (net-send {int-socket} {str-buffer} [{int-num-bytes}]) Sends the contents of {str-buffer} on the connection specified by {int-socket}. If {int-num-bytes} is specified, up to {int-num-bytes} are sent. If {int-num-bytes} is not specified, the entire contents will be sent. |nl-net-send| returns the number of bytes sent or {nil} on failure. On failure, use |nl-net-error| to get more error information. > (set 'buf "hello there") (net-send sock buf) ;→ 11 (net-send sock buf 5) ;→ 5 (net-send sock "bye bye") ;→ 7 < The first |nl-net-send| sends the string {"hello there"}, while the second |nl-net-send| sends only the string {"hello"}. *newlisp-function-net-send-to* *nl-net-send-to* FUNCTION: net-send-to~ {syntax:} (net-send-to {str-remotehost} {int-remoteport} {str-buffer} {int-socket}) Can be used for either UDP or TCP/IP communications. The socket in {int-socket} must have previously been opened with a |nl-net-connect| or |nl-net-listen| function. If the opening functions was used with the {"udp"} option, |nl-net-listen| or |nl-net-connect| are not used to listen or to connect but only to create the UDP socket. The host in {str-remotehost} can be specified either as a hostname or as an IP-number string. When using |nl-net-connect| together with |nl-net-send-to|, then only one of the functions should specify the remote host. The other should leave the address as an empty string. > ;;;;;;;;;;;;;;;;;; UDP server (set 'socket (net-listen 10001 "" "udp")) (if socket (println "server listening on port " 10001) (println (net-error))) (while (not (net-error)) (set 'msg (net-receive-from socket 255)) (println "-> " msg) (net-send-to (nth 1 msg) (nth 2 msg) (upper-case (first msg)) socket)) ;;;;;;;;;;;;;;;;;; UDP client (set 'socket (net-listen 10002 "" "udp")) (if (not socket) (println (net-error))) (while (not (net-error)) (print "> ") (net-send-to "127.0.0.1" 10001 (read-line) socket) (net-receive socket buff 255) (println "-> " buff)) < In the examples both, the client and the server use |nl-net-listen| to create the UDP socket for sending and receiving. The server extracts the client address and port from the message received and uses it in the |nl-net-send-to| statement. See also the |nl-net-receive-from| function and the |nl-net-listen| function with the {"udp"} option. For blocking short UDP transactions use |nl-net-send-udp| and |nl-net-receive-udp|. *newlisp-function-net-send-udp* *nl-net-send-udp* FUNCTION: net-send-udp~ {syntax:} (net-send-udp {str-remotehost} {int-remoteport} {str-buffer} [{bool}]) Sends a User Datagram Protocol (UDP) to the host specified in {str-remotehost} and to the port in {int-remoteport}. The data sent is in {str-buffer}. The theoretical maximum data size of a UDP packet on an IPv4 system is 64K minus IP layer overhead, but much smaller on most Unix flavors. 8k seems to be a safe size on Mac OS X, BSDs and Linux. No previous setup using |nl-net-connect| or |nl-net-listen| is necessary. |nl-net-send-udp| returns immediately with the number of bytes sent and closes the socket used. If no |nl-net-receive-udp| statement is waiting at the receiving side, the datagram sent is lost. When using datagram communications over insecure connections, setting up a simple protocol between sender and receiver is recommended for ensuring delivery. UDP communication by itself does not guarantee reliable delivery as TCP/IP does. > (net-send-udp "somehost.com" 3333 "Hello") ;→ 5 < |nl-net-send-udp| is also suitable for sending binary information (e.g., the zero character or other non-visible bytes). For a more comprehensive example, see |nl-net-receive-udp|. Optionally, the sending socket can be put in broadcast mode by specifying {true} or any expression not evaluating to {nil} in {bool}: > (net-send-udp "192.168.1.255" 2000 "Hello" true) ;→ 5 < The UDP will be sent to all nodes on the {192.168.1} network. Note that on some operating systems, sending the network mask {255} without the {bool} {true} option will enable broadcast mode. As an alternative, the |nl-net-connect| function using the {"udp"} option—together with the |nl-net-send-to| function—can be used to talk to a UDP listener in a non-blocking fashion. *newlisp-function-net-service* *nl-net-service* FUNCTION: net-service~ {syntax:} (net-service {str-service} {str-protocol}) + {syntax:} (net-service {int-port} {str-protocol}) In the first syntax |nl-net-service| makes a lookup in the {services} database and returns the standard port number for this service. In the second syntax a service port is supplied in {int-port} to look up the service name. Returns {nil} on failure. > ; get the port number from the name (net-service "ftp" "tcp") ;→ 21 (net-service "http" "tcp") ;→ 80 (net-service "net-eval" "tcp") ;→ 4711 ; if configured ; get the service name from the port number (net-service 22 "tcp") ;→ "ssh" < *newlisp-function-net-sessions* *nl-net-sessions* FUNCTION: net-sessions~ {syntax:} (net-sessions) Returns a list of active listening and connection sockets. *newlisp-function-new* *nl-new* FUNCTION: new~ {syntax:} (new {context-source} {sym-context-target} [{bool}]) + {syntax:} (new {context-source}) The context {context-source} is copied to {sym-context-target}. If the target context does not exist, a new context with the same variable names and user-defined functions as in {context-source} is created. If the target context already exists, then new symbols and definitions are added. Existing symbols are only overwritten when the expression in {bool} evaluates to anything other than {nil}; otherwise, the content of existing symbols will remain. This makes {mixins} of context objects possible. |nl-new| returns the target context, which cannot be MAIN. In the second syntax, the existing context in {context-source} gets copied into the current context as the target context. All references to symbols in the originating context will be translated to references in the target context. This way, all functions and data structures referring to symbols in the original context will now refer to symbols in the target context. > (new CTX 'CTX-2) ;→ CTX-2 ;; force overwrite of existing symbols (new CTX MyCTX true) ;→ MyCTX < The first line in the example creates a new context called {CTX-2} that has the exact same structure as the original one. Note that {CTX} is not quoted because contexts evaluate to themselves, but CTX-2 must be quoted because it does not exist yet. The second line merges the context {CTX} into {MyCTX}. Any existing symbols of the same name in {MyCTX} will be overwritten. Because {MyCTX} already exists, the quote before the context symbol can be omitted. Context symbols need not be mentioned explicitly, but they can be contained in variables: > (set 'foo:x 123) (set 'bar:y 999) (set 'ctxa foo) (set 'ctxb bar) (new ctxa ctxb) ; from foo to bar bar:x ;→ 123 ; x has been added to bar bar:y ;→ 999) < The example refers to contexts in variables and merges context {foo} into {bar}. See also the function |nl-def-new| for moving and merging single functions instead of entire contexts. See the |nl-context| function for a more comprehensive example of |nl-new|. *newlisp-function-nil?* *nl-nil?* FUNCTION: nil?~ {syntax:} (nil? {exp}) If the expression in {exp} evaluates to {nil}, then |nl-nil?| returns {true}; otherwise, it returns {nil}. > (map nil? '(x nil 1 nil "hi" ())) ;→ (nil true nil true nil nil) (nil? nil) ;→ true (nil? '()) ;→ nil ; nil? means strictly nil (nil? (not '())) ;→ nil < The |nl-nil?| predicate is useful for distinguishing between {nil} and the empty list {()}. Note that |nl-nil?| means {strictly} {nil} while |nl-true?| means everything not {nil} or the empty list {()}. *newlisp-function-normal* *nl-normal* FUNCTION: normal~ {syntax:} (normal {float-mean} {float-stdev} {int-n}) + {syntax:} (normal {float-mean} {float-stdev}) In the first form, |nl-normal| returns a list of length {int-n} of random, continuously distributed floating point numbers with a mean of {float-mean} and a standard deviation of {float-stdev}. The random generator used internally can be seeded using the |nl-seed| function. > (normal 10 3 10) ;→ (7 6.563476562 11.93945312 6.153320312 9.98828125 7.984375 10.17871094 6.58984375 9.42578125 12.11230469) < In the second form, |nl-normal| returns a single normal distributed floating point number: > (normal 0 1) ;→ 0.6630859375 < See also the |nl-random| and |nl-rand| functions for evenly distributed numbers, |nl-amb| for randomizing evaluation in a list of expressions, and |nl-seed| for setting a different start point for pseudo random number generation. *newlisp-function-not* *nl-not* FUNCTION: not~ {syntax:} (not {exp}) If {exp} evaluates to {nil} or the empty list {()}, then {true} is returned; otherwise, {nil} is returned. > (not true) ;→ nil (not nil) ;→ true (not '()) ;→ true (not (< 1 10)) ;→ nil (not (not (< 1 10))) ;→ true < *newlisp-function-now* *nl-now* FUNCTION: now~ {syntax:} (now [{int-minutes-offset} [{int-index}]]) Returns information about the current date and time as a list of integers. An optional time-zone offset can be specified in minutes in {int-minutes-offset}. This causes the time to be shifted forward or backward in time, before being split into separate date values. An optional list-index in {int-index} makes |nl-now| return a specific member in the result list. > (now) ;→ (2002 2 27 18 21 30 140000 57 3 -300 0) (now 0 -2) ;→ -300 ; minutes west of GMT (apply date-value (now)) ;→ 1014834090 < The numbers represent the following date-time fields: [cols="1<,3<",width="50%",options="header",] |======================================================================= |format |description |year |Gregorian calendar |month |(1–12) |day |(1–31) |hour |(0–23) UTC |minute |(0–59) |second |(0–59) |microsecond |(0–999999) OS-specific, millisecond resolution |day of current year |Jan 1st is 1 |day of current week |(1–7) starting Monday |time zone offset in minutes |west of GMT |daylight savings time type |(0–6) on Linux/Unix or bias in minutes on Win32 |======================================================================= The second example returns the Coordinated Universal Time (UTC) time value of seconds after January 1, 1970. Ranging from 0 to 23, hours are given in UTC and are not adjusted for the local time zone. The resolution of the {microseconds} field depends on the operating system and platform. On some platforms, the last three digits of the {microseconds} field are always {0} (zero). The "day of the week" field starts with 1 on Monday comforming to the ISO 8601 international standard for date and time representation. On some platforms, the daylight savings time flag is not active and returns {0} (zero) even during daylight savings time (dst). Depending on the geographical area, the daylight savings time type (dst) has a different value from 1 to 6: [cols="1<,5<",width="15%",options="header",] |======================= |type |area |0 |not on dst |1 |USA style dst |2 |Australian style dst |3 |Western European dst |4 |Middle European dst |5 |Eastern European dst |6 |Canada dst |======================= See also the |nl-date|, |nl-date-list|, |nl-date-parse|, |nl-date-value|, |nl-time|, and |nl-time-of-day| functions. *newlisp-function-nper* *nl-nper* FUNCTION: nper~ {syntax:} (nper {num-interest} {num-pmt} {num-pv} [{num-fv} [{int-type}]]) Calculates the number of payments required to pay a loan of {num-pv} with a constant interest rate of {num-interest} and payment {num-pmt}. If payment is at the end of the period, {int-type} is {0} (zero) or {int-type} is omitted; for payment at the beginning of each period, {int-type} is 1. > (nper (div 0.07 12) 775.30 -100000) ;→ 239.9992828 < The example calculates the number of monthly payments required to pay a loan of $100,000 at a yearly interest rate of 7 percent with payments of $775.30. See also the |nl-fv|, |nl-irr|, |nl-npv|, |nl-pmt|, and |nl-pv| functions. *newlisp-function-npv* *nl-npv* FUNCTION: npv~ {syntax:} (npv {num-interest} {list-values}) Calculates the net present value of an investment with a fixed interest rate {num-interest} and a series of future payments and income in {list-values}. Payments are represented by negative values in {list-values}, while income is represented by positive values in {list-values}. > (npv 0.1 '(1000 1000 1000)) ;→ 2486.851991 (npv 0.1 '(-2486.851991 1000 1000 1000)) ;→ -1.434386832e-08 ; ~ 0.0 (zero) < In the example, an initial investment of $2,481.85 would allow for an income of $1,000 after the end of the first, second, and third years. See also the |nl-fv|, |nl-irr|, |nl-nper|, |nl-pmt|, and |nl-pv| functions. *newlisp-function-nth* *nl-nth* FUNCTION: nth~ |nl-utf8_capable| {syntax:} (nth {int-index} {list}) + {syntax:} (nth {int-index} {array}) + {syntax:} (nth {int-index} {str}) + {syntax:} (nth {list-indices} {list}) + {syntax:} (nth {list-indices} {array}) In the first syntax group |nl-nth| uses {int-index} an index into the {list}, {array} or {str} found and returning the element found at that index. See also |nl-Indexing elements of strings and lists|. Multiple indices may be specified to recursively access elements in nested lists or arrays. If there are more indices than nesting levels, the extra indices are ignored. When multiple indices are used, they must be put in a list as shown in the second syntax group. > (set 'L '(a b c)) (nth 0 L) ;→ a ; or simply (L 0) ;→ a (set 'names '(john martha robert alex)) ;→ (john martha robert alex) (nth 2 names) ;→ robert ; or simply (names 2) ;→ robert (names -1) ;→ alex ; multiple indices (set 'persons '((john 30) (martha 120) ((john doe) 17))) (persons 1 1) ;→ 120 (nth '(2 0 1) persons) ;→ doe ; or simply (persons 2 0 1) ;→ doe ; multiple indices in a vector (set 'v '(2 0 1)) (persons v) ;→ doe (nth v persons) ;→ doe ; negative indices (persons -2 0) ;→ martha ; out-of-bounds indices cause error (persons 10) ;→ ERR: list index out of bounds (person -5) ;→ ERR: list index out of bounds < The list {L} can be the context of the default functor {L:L}. This allows lists passed by reference: > (set 'L:L '(a b c d e f g)) (define (second ctx) (nth 1 ctx)) (reverse L) ;→ (g f e d c b a) L:L ;→ (g f e d c b a) ;; passing the list in L:L by reference (second L) ;→ b ;; passing the list in L:L by value (second L:L) ;→ b < Reference passing is faster and uses less memory in big lists and should be used on lists with more than a few hundred items. Note that the {implicit indexing} version of |nl-nth| is not breaking newLISP syntax rules but should be understood as a logical expansion of newLISP syntax rules to other data types than built-in functions or lambda expressions. A list in the functor position of an s-expression assumes self-indexing functionality using the index arguments following. The implicit indexed syntax forms are faster but the other form with an explicit |nl-nth| may be more readable in some situations. |nl-nth| works on |nl-arrays| just like it does on lists: > (set 'aArray (array 2 3 '(a b c d e f))) ;→ ((a b c) (d e f)) (nth 1 aArray) ;→ (d e f) (aArray 1) ;→ (d e f) (nth '(1 0) aArray) ;→ d (aArray 1 0) ;→ d (aArray '(1 0)) ;→ d (set 'vec '(1 0)) (aArray vec) ;→ d < In the String version, |nl-nth| returns the character found at the position {int-index} in {str} and returns it as a string. > (nth 0 "newLISP") ;→ "n" ("newLISP" 0) ;→ "n" ("newLISP" -1) ;→ "P" < Note that |nl-nth| works on character boundaries rather than byte boundaries when using the UTF-8–enabled version of newLISP. To access ASCII and binary string buffers on single byte boundaries use |nl-slice|. See also |nl-setf| for modifying multidimensional lists and arrays and |nl-push| and |nl-pop| for modifying lists. *newlisp-function-null?* *nl-null?* FUNCTION: null?~ {syntax:} (null? {exp}) Checks if an expression evaluates to {nil}, the empty list {()}, the empty string {""}, {NaN} (not a number), or {0} (zero), in which case it returns {true}. In all other cases, |nl-null?| returns {nil}. The predicate |nl-null?| is useful in conjunction with the functions |nl-filter| or |nl-clean| to check the outcome of other newLISP operations. > (set 'x (sqrt -1)) ;→ NaN ; or nan on UNIX (null? x) ;→ true (map null? '(1 0 0.0 2 "hello" "" (a b c) () true)) ;→ (nil true true nil nil true nil true nil) (filter null? '(1 0 2 0.0 "hello" "" (a b c) () nil true)) ;→ (0 0 "" () nil) (clean null? '(1 0 2 0.0 "hello" "" (a b c) () nil true)) ;→ (1 2 "hello" (a b c) true) < See also the predicates |nl-empty?|, |nl-nil?| and |nl-zero?|. *newlisp-function-number?* *nl-number?* FUNCTION: number?~ {syntax:} (number? {exp}) {true} is returned only if {exp} evaluates to a floating point number or an integer; otherwise, {nil} is returned. > (set 'x 1.23) (set 'y 456) (number? x) ;→ true (number? y) ;→ true (number? "678") ;→ nil < See the functions |nl-float?| and |nl-integer?| to test for a specific number type. *newlisp-function-odd?* *nl-odd?* FUNCTION: odd?~ {syntax:} (odd? {int-number}) Checks the parity of an integer number. If the number is not _even divisable{ by {2}, it has }odd_ parity. When a floating point number is passed for {int-number}, it will be converted first to an integer by cutting off its fractional part. > (odd? 123) ;→ true (odd? 8) ;→ nil (odd? 8.7) ;→ nil < Use |nl-even?| to check if an integer is even, divisable by {2}. *newlisp-function-open* *nl-open* FUNCTION: open~ {syntax:} (open {str-path-file} {str-access-mode} [{str-option}]) The {str-path-file} is a file name, and {str-access-mode} is a string specifying the file access mode. |nl-open| returns an integer, which is a file handle to be used on subsequent read or write operations on the file. On failure, |nl-open| returns {nil}. The access mode {"write"} creates the file if it doesn't exist, or it truncates an existing file to {0} (zero) bytes in length. The following strings are legal access modes: {"read"} or {"r"} for read only access + {"write"} or {"w"} for write only access + {"update"} or {"u"} for read/write access + {"append"} or {"a"} for append read/write access + > (device (open "newfile.data" "write")) ;→ 5 (print "hello world\n") ;→ "hello world" (close (device)) ;→ 5 (set 'aFile (open "newfile.data" "read")) (seek aFile 6) (set 'inChar (read-char aFile)) (print inChar "\n") (close aFile) < The first example uses |nl-open| to set the device for |nl-print| and writes the word {"hello world"} into the file {newfile.data}. The second example reads a byte value at offset 6 in the same file (the ASCII value of {'w'} is 119). Note that using |nl-close| on |nl-(device)| automatically resets |nl-device| to {0} (zero). As an additional {str-option}, {"non-block"} or {"n"} can be specified after the {"read"} or {"write"} option. Only available on Unix systems, non-blocking mode can be useful when opening {named pipes} but is not required to perform I/O on named pipes. To create a named pipe in newLISP, use the |nl-exec| or |nl-import| function: > (exec "mkfifo myfifo") ;; or alternatively (import "/lib/libc.so.6" "mkfifo") (mkfifo "/tmp/myfifo" 0777) < The named pipe can now be used like a file with |nl-open|, |nl-read|, and |nl-write|. *newlisp-function-or* *nl-or* FUNCTION: or~ {syntax:} (or {exp-1} [{exp-2} ... ]) Evaluates expressions {exp-x} from left to right until finding a result that does not evaluate to {nil} or the empty list {()}. The result is the return value of the |nl-or| expression. > (set 'x 10) (or (> x 100) (= x 10)) ;→ true (or "hello" (> x 100) (= x 10)) ;→ "hello" (or '()) ;→ () (or true) ;→ true (or) ;→ nil < *newlisp-function-ostype* *nl-ostype* FUNCTION: ostype~ {syntax:} ostype {ostype} is a built-in system constant containing the name of the operating system newLISP is running on. > ostype ;→ "Win32" < One of the following strings is returned: {"Linux", "BSD", "OSX", "Tru64Unix", "Solaris", "SunOS", "Win32", or "OS/2"}. {ostype} can be used to write platform-independent code: > (if (= ostype "Linux") (import "libz.so") (= ostype "BSD") (import "libz.so") (= ostype "OSX") (import "libz.dylib") ... (println "cannot import libz on this platform") ) < Use |nl-sys-info| to learn more about the current flavor of newLISP running. For a table of other built-in system variables and symbols see the chapter |nl-System Symbols and Constants| in the appendix. *newlisp-function-pack* *nl-pack* FUNCTION: pack~ {syntax:} (pack {str-format} {exp-1} [{exp-2} ... ]) + {syntax:} (pack {str-format} {list}) + {syntax:} (pack {struct} {exp-1} [{exp-2} ... ]) + {syntax:} (pack {struct} {list}) When the first parameter is a string, |nl-pack| packs one or more expressions ({exp-1} to {exp-n}) into a binary format specified in the format string {str-format}, and returning the binary structure in a string buffer. The symmetrical |nl-unpack| function is used for unpacking. The expression arguments can also be given in a {list}. |nl-pack| and |nl-unpack| are useful when reading and writing binary files (see |nl-read| and |nl-write|) or when unpacking binary structures from return values of imported C functions using |nl-import|. When the first parameter is the symbol of a |nl-struct| definition, |nl-pack| uses the format as specified in {struct}. While |nl-pack| with {str-format} literally packs as specified, |nl-pack| with {struct} will insert structure aligning pad-bytes depending on data type, order of elements and CPU architecture. Refer to the description of the |nl-struct| function for more detail. The following characters are used in {str-format}: [cols="1<,5<",width="40%",options="header",] |================================================== |format |description |{c } |a signed 8-bit number |{b } |an unsigned 8-bit number |{d } |a signed 16-bit short number |{u } |an unsigned 16-bit short number |{ld} |a signed 32-bit long number |{lu} |an unsigned 32-bit long number |{Ld} |a signed 64-bit long number |{Lu} |an unsigned 64-bit long number |{f } |a float in 32-bit representation |{lf} |a double float in 64-bit representation |{sn} |a string of {n} null padded ASCII characters |{nn} |{n} null characters ||nl->| |switch to big endian byte order ||nl-<| |switch to little endian byte order |================================================== |nl-pack| will convert all floats into integers when passed to {b}, {c}, {d}, {ld}, or {lu} formats. It will also convert integers into floats when passing them to {f} and {lf} formats. > (pack "c c c" 65 66 67) ;→ "ABC" (unpack "c c c" "ABC") ;→ (65 66 67) (pack "c c c" 0 1 2) ;→ "\000\001\002" (unpack "c c c" "\000\001\002") ;→ (0 1 2) (set 's (pack "c d u" 10 12345 56789)) (unpack "c d u" s) ;→ (10 12345 56789) (set 's (pack "s10 f" "result" 1.23)) (unpack "s10 f" s) ;→ ("result\000\000\000\000" 1.230000019) (pack "n10") ;→ "\000\000\000\000\000\000\000\000\000\000" (set 's (pack "s3 lf" "result" 1.23)) (unpack "s3 f" s) ;→ ("res" 1.23) (set 's (pack "c n7 c" 11 22)) (unpack "c n7 c" s) ;→ (11 22)) (unpack "b" (pack "b" -1.0)) ;→ (255) (unpack "f" (pack "f" 123)) ;→ (123) < The last two statements show how floating point numbers are converted into integers when required by the format specification. The expressions to pack can also be given in a list: > (set 'lst '("A" "B" "C")) (set 'adr (pack "lululu" lst)) (map get-string (unpack "lululu" adr)) ;→ ("A" "B" "C") < Note that the list should be referenced directly in |nl-pack|, so the pointers passed by {adr} are valid. {adr} would be written as {char * adr[]} in the C-programming language and represents a 32-bit pointer to an array of 32-bit string pointers. The |nl->| and |nl-<| specifiers can be used to switch between {little endian} and {big endian} byte order when packing or unpacking: > (pack "d" 1) ;→ "\001\000" ;; on little endian CPU (pack ">d" 1) ;→ "\000\001" ;; force big endian (pack "ld" 1) ;→ "\001\000\000\000" ;; on little endian CPU (pack "u (set 's (pack "s3" "ABC")) (unpack "c c c" s) ;→ (65 66 67) < The examples show spaces between the format specifiers. These are not required but can be used to improve readability. See also the |nl-address|, |nl-get-int|, |nl-get-long|, |nl-get-char|, |nl-get-string|, and |nl-unpack| functions. *newlisp-function-parse* *nl-parse* FUNCTION: parse~ {syntax:} (parse {str-data} [{str-break} [{int-option}]]) Breaks the string that results from evaluating {str-data} into string tokens, which are then returned in a list. When no {str-break} is given, |nl-parse| tokenizes according to newLISP's internal parsing rules. A string may be specified in {str-break} for tokenizing only at the occurrence of a string. If an {int-option} number is specified, a regular expression pattern may be used in {str-break}. When {str-break} is not specified, the maximum token size is 2048 for quoted strings and 256 for identifiers. In this case, newLISP uses the same faster tokenizer it uses for parsing newLISP source. If {str-break} is specified, there is no limitation on the length of tokens. A different algorithm is used that splits the source string {str-data} at the string in {str-break}. > (parse "hello how are you") ;→ ("hello" "how" "are" "you") (parse "one:two:three" ":") ;→ ("one" "two" "three") (parse "one--two--three" "--") ;→ ("one" "two" "three") (parse "one-two--three---four" "-+" 0) ;→ ("one" "two" "three" "four") (parse "hello regular expression 1, 2, 3" {,\s*|\s+} 0) ;→ ("hello" "regular" "expression" "1" "2" "3") < The last two examples show a regular expression as the break string with the default option {0} (zero). Instead of {{} and {}} (left and right curly brackets), double quotes can be used to delimit the pattern. In this case, double backslashes must be used inside the pattern. The last pattern could be used for parsing CSV (Comma Separated Values) files. For the regular expression option numbers, see |nl-regex|. |nl-parse| will return empty fields around separators as empty strings: > (parse "1,2,3," ",") ;→ ("1" "2" "3" "") (parse "1,,,4" ",") ;→ ("1" "" "" "4") (parse "," ",") ;→ ("" "") (parse "") ;→ () (parse "" " ") ;→ () < This behavior is needed when parsing records with empty fields. Parsing an empty string will always result in an empty list. Use the |nl-regex| function to break strings up and the |nl-directory|, |nl-find|, |nl-find-all|, |nl-regex|, |nl-replace|, and |nl-search| functions for using regular expressions. *newlisp-function-peek* *nl-peek* FUNCTION: peek~ {syntax:} (peek {int-handle}) Returns the number of bytes ready to be read on a file descriptor; otherwise, it returns {nil} if the file descriptor is invalid. |nl-peek| can also be used to check {stdin}. This function is only available on Unix-like operating systems. > (peek 0) ; check # of bytes ready on stdin < Use the |nl-net-peek| function to check for network sockets, or for the number of available bytes on them. On Unix systems, |nl-net-peek| can be used to check file descriptors. The difference is that |nl-net-peek| also sets |nl-net-error|. *newlisp-function-pipe* *nl-pipe* FUNCTION: pipe~ {syntax:} (pipe) Creates an inter-process communications pipe and returns the |nl-read| and |nl-write| handles to it within a list. > (pipe) ;→ (3 4) ; 3 for read, 4 for writing < The pipe handles can be passed to a child process launched via |nl-process| or to |nl-fork| for inter-process communications. Note that the pipe does not block when being written to, but it does block reading until bytes are available. A |nl-read-line| blocks until a newline character is received. A |nl-read| blocks when fewer characters than specified are available from a pipe that has not had the writing end closed by all processes. More than one pipe can be opened if required. newLISP can also use {named pipes}. See the |nl-open| function for further information. *newlisp-function-pmt* *nl-pmt* FUNCTION: pmt~ {syntax:} (pmt {num-interest} {num-periods} {num-principal} [{num-future-value} [{int-type}]]) Calculates the payment for a loan based on a constant interest of {num-interest} and constant payments over {num-periods} of time. {num-future-value} is the value of the loan at the end (typically {0.0}). If payment is at the end of the period, {int-type} is {0} (zero) or {int-type} is omitted; for payment at the beginning of each period, {int-type} is 1. > (pmt (div 0.07 12) 240 100000) ;→ -775.2989356 < The above example calculates a payment of $775.30 for a loan of $100,000 at a yearly interest rate of 7 percent. It is calculated monthly and paid over 20 years (20 * 12 = 240 monthly periods). This illustrates the typical way payment is calculated for mortgages. See also the |nl-fv|, |nl-irr|, |nl-nper|, |nl-npv|, and |nl-pv| functions. *newlisp-function-pop* *nl-pop* FUNCTION: pop~ |nl-destructive| |nl-utf8_capable| {syntax:} (pop {list} [{int-index-1} [{int-index-2} ... ]]) + {syntax:} (pop {list} [{list-indexes}]) + {syntax:} (pop {str} [{int-index} [{int-length}]]) Using |nl-pop|, elements can be removed from lists and characters from strings. In the first syntax, |nl-pop| extracts an element from the list found by evaluating {list}. If a second parameter is present, the element at {int-index} is extracted and returned. See also link:#indexing[Indexing elements of strings and lists]. In the second version, indices are specified in the list {list-indexes}. This way, |nl-pop| works easily together with |nl-ref| and |nl-ref-all|, which return lists of indices. |nl-pop| changes the contents of the target list. The popped element is returned. > (set 'pList '((f g) a b c "hello" d e 10)) (pop pList) ;→ (f g) (pop pList) ;→ a pList ;→ (b c "hello" d e 10) (pop pList 3) ;→ d (pop pList 100) ;→ 10 pList ;→ (b c "hello" e) (pop pList -1) ;→ e pList ;→ (b c "hello") (pop pList -2) ;→ c pList ;→ (b "hello") (set 'pList '(a 2 (x y (p q) z))) (pop pList -1 2 0) ;→ p ;; use indices in a list (set 'pList '(a b (c d () e))) (push 'x pList '(2 2 0)) ;→ (a b (c d (x) e)) pList ;→ (a b (c d (x) e)) (ref 'x pList) ;→ (2 2 0) (pop pList '(2 2 0)) ;→ x < |nl-pop| can also be used on strings with one index: > ;; use pop on strings (set 'str "newLISP") (pop str -4 4) ;→ "LISP" str ;→ "new" (pop str 1) ;→ "e" str ;→ "nw" (set 'str "x") (pop str) ;→ "x" (pop str) ;→ "" < Popping an empty string will return an empty string. See also the |nl-push| function, the inverse operation to |nl-pop|. *newlisp-function-pop-assoc* *nl-pop-assoc* FUNCTION: pop-assoc~ |nl-destructive| {syntax:} (pop-assoc {exp-key} {list-assoc}) + {syntax:} (pop-assoc {list-keys} {list-assoc}) Removes an association referred to by the key in {exp-key} from the association list in {list-assoc} and returns the popped expression. > ;; simple associations (set 'L '((a 1) (b 2) (c 3))) (pop-assoc 'b L) ;→ (b 2) L ;→ ((a 1) (c 3)) ;; nested associations (set 'L '((a (b 1) (c (d 2))))) (pop-assoc 'a L) ;→ (a (b 1) (c (d 2))) L ;→ () (set 'L '((a (b 1) (c (d 2))))) (pop-assoc '(a b) L) ;→ (b 1) L ;→ ((a (c (d 2)))) (set 'L '((a (b 1) (c (d 2))))) (pop-assoc '(a c) L) ;→ (c (d 2)) L ;→ ((a (b 1)))) < See also |nl-assoc| for retrieving associations and |nl-setf| for modifying association lists. *newlisp-function-post-url* *nl-post-url* FUNCTION: post-url~ {syntax:} (post-url {str-url} {str-content} [{str-content-type} [{str-option}] [{int-timeout} [ {str-header}]]]) Sends an HTTP POST request to the URL in {str-url}. POST requests are used to post information collected from web entry forms to a web site. Most of the time, the function |nl-post-url| mimics what a web browser would do when sending information collected in an HTML form to a server, but it can also be used to upload files (see an HTTP reference). The function returns the page returned from the server in a string. When |nl-post-url| encounters an error, it returns a string description of the error beginning with {ERR:}. The last parameter, {int-timeout}, is for an optional timeout value, which is specified in milliseconds. When no response from the host is received before the timeout has expired, the string {ERR: timeout} is returned. > ;; specify content type (post-url "http://somesite.com/form.pl" "name=johnDoe&city=New%20York" "application/x-www-form-urlencoded") ;; specify content type and timeout (post-url "http://somesite.com/form.pl" "name=johnDoe&city=New%20York" "application/x-www-form-urlencoded" 8000) ;; assumes default content type and no timeout (post-url "http://somesite.com/form.pl" "name=johnDoe&city=New%20York" < The above example uploads a user name and city using a special format called {application/x-www-form-urlencoded}. |nl-post-url| can be used to post other content types such as files or binary data. See an HTTP reference for other content-type specifications and data encoding formats. When the content-type parameter is omitted, |nl-post-url| assumes {application/x-www-form-urlencoded} as the default content type. Additional parameters ^^^^^^^^^^^^^^^^^^^^^ When {str-content-type} is specified, the {str-option} {"header"} or {"list"} can be specified as the return page. If the {int-timeout} option is specified, the custom header option {str-header} can be specified, as well. See the function |nl-get-url| for details on both of these options. See also the |nl-get-url| and |nl-put-url| functions. *newlisp-function-pow* *nl-pow* FUNCTION: pow~ {syntax:} (pow {num-1} {num-2} [{num-3} ... ]) + {syntax:} (pow {num-1}) Calculates {num-1} to the power of {num-2} and so forth. > (pow 100 2) ;→ 10000 (pow 100 0.5) ;→ 10 (pow 100 0.5 3) ;→ 1000 (pow 3) ;→ 9 < When {num-1} is the only argument, |nl-pow| assumes 2 for the exponent. *newlisp-function-prefix* *nl-prefix* FUNCTION: prefix~ {syntax:} (prefix {sym}) Returns the context of a symbol in {sym}: > (setf s 'Foo:bar) ;→ Foo:bar (prefix s) ;→ Foo (context? (prefix s)) ;→ true (term s) ;→ "bar" (= s (sym (term s) (prefix s))) ;→ true >(context (prefix s)) ; switches to context Foo Foo Foo> < See also |nl-term| to extract the term part of a symbol. *newlisp-function-pretty-print* *nl-pretty-print* FUNCTION: pretty-print~ {syntax:} (pretty-print [{int-length} [{str-tab} [{str-fp-format}]]) Reformats expressions for |nl-print|, |nl-save|, or |nl-source| and when printing in an interactive console. The first parameter, {int-length}, specifies the maximum line length, and {str-tab} specifies the string used to indent lines. The third parameter {str-fp-format} describes the default format for printing floating point numbers. All parameters are optional. |nl-pretty-print| returns the current settings or the new settings when parameters are specified. > (pretty-print) ;→ (80 " " "%1.10g") ; default setting (pretty-print 90 "\t") ;→ (90 "\t") (pretty-print 100) ;→ (100 "\t") (sin 1) ;→ 0.8414709848 (pretty-print 80 " " "%1.3f") (sin 1) ;→ 0.841 (set 'x 0.0) x ;→ 0.000 < The first example reports the default settings of 80 for the maximum line length and a {space} character for indenting. The second example changes the line length to 90 and the indent to a TAB character. The third example changes the line length only. The last example changes the default format for floating point numbers. This is useful when printing unformatted floating point numbers without fractional parts, and these numbers should still be recognizable as floating point numbers. Without the custom format, {x} would be printed as {0} indistinguishable from floating point number. All situations where unformatted floating point numbers are printed, are affected. Note that |nl-pretty-print| cannot be used to prevent line breaks from being printed. To completely suppress pretty printing, use the function |nl-string| to convert the expression to a raw unformatted string as follows: > ;; print without formatting (print (string my-expression)) < *newlisp-function-primitive?* *nl-primitive?* FUNCTION: primitive?~ {syntax:} (primitive? {exp}) Evaluates and tests if {exp} is a primitive symbol and returns {true} or {nil} depending on the result. > (set 'var define) (primitive? var) ;→ true < *newlisp-function-print* *nl-print* FUNCTION: print~ {syntax:} (print {exp-1} [{exp-2} ... ]) Evaluates and prints {exp-1}— to the current I/O device, which defaults to the console window. See the built-in function |nl-device| for details on how to specify a different I/O device. List expressions are indented by the nesting levels of their opening parentheses. Several special characters may be included in strings encoded with the escape character {\}: [cols="1<,4<",width="40%",options="header",] |================================================================ |character |description |{\n} |the line-feed character (ASCII 10) |{\r} |the carriage-return character (ASCII 13) |{\t} |the tab character (ASCII 9) |{\nnn} |where {nnn} is a decimal ASCII code between 000 and 255 |{\xnn} |where {nn} is a hexadecimal ASCII code between 00 and FF |================================================================ > (print (set 'res (+ 1 2 3))) (print "the result is" res "\n") "\065\066\067" ;→ "ABC" < To finish printing with a line-feed, use |nl-println|. *newlisp-function-println* *nl-println* FUNCTION: println~ {syntax:} (println {exp-1} [{exp-2} ... ]) Evaluates and prints {exp-1}— to the current I/O device, which defaults to the console window. A line-feed is printed at the end. See the built-in function |nl-device| for details on how to specify a different I/O device. |nl-println| works exactly like |nl-print| but emits a line-feed character at the end. See also the |nl-write-line| and |nl-print| functions. *newlisp-function-prob-chi2* *nl-prob-chi2* FUNCTION: prob-chi2~ {syntax:} (prob-chi2 {num-chi2} {int-df}) Returns the probability of an observed {Chi²} statistic in {num-chi2} with {num-df} degrees of freedom to be equal or greater under the null hypothesis. |nl-prob-chi2| is derived from the incomplete Gamma function |nl-gammai|. > (prob-chi2 10 6) ;→ 0.1246520195 < See also the inverse function |nl-crit-chi2|. *newlisp-function-prob-f* *nl-prob-f* FUNCTION: prob-f~ {syntax:} (prob-f {num-f} {int-df1} {int-df2}) Returns the probability of an observed {F} statistic in {num-f} with {int-df1} and {int-df2} degrees of freedom to be equal or greater under the null hypothesis. > (prob-f 2.75 10 12) ;→ 0.0501990804 < See also the inverse function |nl-crit-f|. *newlisp-function-prob-t* *nl-prob-t* FUNCTION: prob-t~ {syntax:} (prob-t {num-t} {int-df1}) Returns the probability of an observed {Student's t} statistic in {num-t} with {int-df} degrees of freedom to be equal or greater under the null hypothesis. > (prob-t 1.76 14) ;→ 0.05011454551 < See also the inverse function |nl-crit-t|. *newlisp-function-prob-z* *nl-prob-z* FUNCTION: prob-z~ {syntax:} (prob-z {num-z}) Returns the probability of {num-z}, not to exceed the observed value where {num-z} is a normal distributed value with a mean of {0.0} and a standard deviation of {1.0}. > (prob-z 0.0) ;→ 0.5 < See also the inverse function |nl-crit-z|. *newlisp-function-process* *nl-process* FUNCTION: process~ {syntax:} (process {str-command}) + {syntax:} (process {str-command} {int-pipe-in} {int-pipe-out} [{int-win32-option}]) + {syntax:} (process {str-command} {int-pipe-in} {int-pipe-out} [{int-unix-pipe-error}]) In the first syntax, |nl-process| launches a process specified in {str-command} and immediately returns with a process ID or {nil} if a process could not be created. This process will execute the program specified or immediately die if {str-command} could not be executed. On Mac OS X and other Unixes, the application or script must be specified with its full path-name. The new process inherits the OS environment from the parent process. Command line arguments are parsed out at spaces. Arguments containing spaces must be delimited using single quotes on Mac OS X and other Unixes. On Win32, double quotes are used. The process id returned can be used to destroy the running process using |nl-destroy|, if the process does not exit by itself. > (process "c:/WINDOWS/system32/notepad.exe") ;→ 1894 ; on Win32 ; find out the path of the program to start using exec, ; if the path is not known (process (first (exec "which xclock"))) ;→ 22607 ; on Unix < If the path of the executable is unknown, |nl-exec| together with the Unix {which} command can be used to start a program. The pid returned can be used to |nl-destroy| the process. In the second syntax, standard input and output of the created process can be redirected to pipe handles. When remapping standard I/O of the launched application to a pipe, it is possible to communicate with the other application via |nl-write-line| and |nl-read-line| or |nl-write| and |nl-read| statements: > ;; Linux/Unix ;; create pipes (map set '(myin bcout) (pipe)) (map set '(bcin myout) (pipe)) ;; launch Unix 'bc' calculator application (process "/usr/bin/bc" bcin bcout) ;→ 7916 (write myout "3 + 4\n") ; bc expects a line-feed (read-line myin) ;→ "7" ;; bc can use bignums with arbitrary precision (write myout "123456789012345 * 123456789012345\n") (read-line myin) ;→ "15241578753238669120562399025" ;; destroy the process (destroy 7916) ;; Win32 (map set '(myin cmdout) (pipe)) (map set '(cmdin myout) (pipe)) (process "c:/Program Files/newlisp/newlisp.exe -c" cmdin cmdout) ;→ 1284 (write-line myout "(+ 3 4)") (read-line myin) ;→ "7" ;; destroy the process (destroy 1284) < On Win32 versions of newLISP, a fourth optional parameter of {int-win32-option} can be specified to control the display status of the application. This option defaults to {1} for showing the application's window, {0} for hiding it, and {2} for showing it minimized on the Windows launch bar. On both Win32 and Linux/Unix systems, standard error will be redirected to standard out by default. On Linux/Unix, an optional pipe handle for standard error output can be defined in {int-unix-pipe-error}. The function |nl-peek| can be used to check for information on the pipe handles: > ;; create pipes (map set '(myin bcout) (pipe)) (map set '(bcin myout) (pipe)) (map set '(errin errout) (pipe)) ;; launch Unix 'bc' calculator application (process "bc" bcin bcout errout) (write myout command) ;; wait for bc sending result or error info (while (and (= (peek myin) 0) (= (peek errin) 0)) (sleep 10)) (if (> (peek errin) 0) (println (read-line errin))) (if (> (peek myin) 0) (println (read-line myin))) < Not all interactive console applications can have their standard I/O channels remapped. Sometimes only one channel, {in} or {out}, can be remapped. In this case, specify {0} (zero) for the unused channel. The following statement uses only the launched application's output: > (process "app" 0 appout) < Normally, two pipes are used: one for communications to the child process and the other one for communications from the child process. See also the |nl-pipe| and |nl-share| functions for inter-process communications and the |nl-semaphore| function for synchronization of several processes. See the |nl-fork| function for starting separate newLISP processes on Linux/Unix. *newlisp-function-prompt-event* *nl-prompt-event* FUNCTION: prompt-event~ {syntax:} (prompt-event {sym-event-handler} | {func-event-handler}) Refines the prompt as shown in the interactive newLISP shell. The {sym-event-handler} or {func-event-handler} is either a symbol of a user-defined function or a lambda expression: > > (prompt-event (fn (ctx) (string ctx ":" (real-path) "$ "))) $prompt-event MAIN:/Users/newlisp$ (+ 3 4) 7 MAIN:/Users/newlisp$ < The current context before calling the |nl-prompt-event| code is passed as a parameter to the function. Computer output is shown in bold. The example redefines the |nl->| prompt to be the current context followed by a colon |nl-:|, followed by the directory name, followed by the dollar symbol. Together with the |nl-command-event| function this can be used to create fully customized shells or custom command interpreters. The function in |nl-prompt-event| must return a string of 63 characters maximum. Not returning a string will leave the prompt unchanged. *newlisp-function-protected?* *nl-protected?* FUNCTION: protected?~ {syntax:} (protected? {sym}) Checks if a symbol in {sym} is protected. Protected symbols are built-in functions, context symbols, and all symbols made constant using the |nl-constant| function: > (protected? 'println) ;→ true (constant 'aVar 123) (protected? 'aVar) ;→ true < *newlisp-function-push* *nl-push* FUNCTION: push~ |nl-destructive| |nl-utf8_capable| {syntax:} (push {exp} {list} [{int-index-1} [{int-index-2} ... ]]) + {syntax:} (push {exp} {list} [{list-indexes}]) + {syntax:} (push {str-1} {str-2} [{int-index}]) Inserts the value of {exp} into the list {list}. If {int-index} is present, the element is inserted at that index. If the index is absent, the element is inserted at index {0} (zero), the first element. |nl-push| is a destructive operation that changes the contents of the target list. The list changed is returned as a reference on which other built-in functions can work. See also link:#indexing[Indexing elements of strings and lists]. If more than one {int-index} is present, the indices are used to access a nested list structure. Improper indices (those not matching list elements) are discarded. The second version takes a list of {list-indexes} but is otherwise identical to the first. In this way, |nl-push| works easily together with |nl-ref| and |nl-ref-all|, which return lists of indices. If {list} does not contain a list, {list} must contain a {nil} and will be initialized to the empty list. Repeatedly using |nl-push| to the end of a list using {-1} as the {int-index} is optimized and as fast as pushing to the front of a list with no index at all. This can be used to efficiently grow a list. > ; inserting in front (set 'pList '(b c)) ;→ (b c) (push 'a pList) ;→ (a b c) pList ;→ (a b c) ; insert at index (push "hello" pList 2) ;→ (a b "hello" c) ; optimized appending at the end (push 'z pList -1) ;→ (a b "hello" c z) ; inserting lists in lists (push '(f g) pList) ;→ ((f g) a b "hello" c z) ; inserting at negative index (push 'x pList -3) ;→ ((f g) a b "hello" x c z) ; using multiple indices (push 'h pList 0 -1) ;→ ((f g h) a b "hello" x c z) ; use indices in a list (set 'pList '(a b (c d () e))) (push 'x pList '(2 2 0)) ;→ (a b (c d (x) e)) (ref 'x pList) ;→ (2 2 0) (pop pList '(2 2 0)) ;→ x ; push on un-initialized symbol aVar ;→ nil (push 999 aVar) ;→ (999) aVar ;→ (999) < |nl-push| and pop can be combined to model a queue: > ; pop and push a as a queue (set 'Q '(a b c d e)) (pop (push 'f Q -1)) ;→ a (pop (push 'g Q -1)) ;→ b Q ;→ (c d e f g) < Because |nl-push| returns a reference to the modified list, |nl-pop| can work on it directly. In the third syntax |nl-push| can be used to change strings. When {int-index} is used, it refers to character positions rather than byte positions. UTF-8 characters may be multi-byte characters. > ;; push on strings (set 'str "abcdefg") (push "hijk" str -1) ;→ "abcdefghijk" str ;→ "abcdefghijk" (push "123" str) ;→ "123abcdefghijk" (push "4" str 3) ;→ "1234abcdefghijk" (set 'str "\u03b1\u03b2\u03b3") ;→ "αβγ" (push "*" str 1) ;→ "α*βγ" ;; push on a string reference (set 'lst '("abc" "xyz")) (push x (lst 0)) ;→ "xabc" lst ;→ ("xabc" "xyz") < See also the |nl-pop| function, which is the inverse operation to |nl-push|. *newlisp-function-put-url* *nl-put-url* FUNCTION: put-url~ {syntax:} (put-url {str-url} {str-content} [{str-option}] [{int-timeout} [{str-header}]]) The HTTP PUT protocol is used to transfer information in {str-content} to a file specified in {str-url}. The lesser-known HTTP PUT mode is frequently used for transferring web pages from HTML editors to Web servers. In order to use PUT mode, the web server's software must be configured correctly. On the Apache web server, use the {'Script PUT'} directive in the section where directory access rights are configured. If {str-url} starts with {file://} then {str-content} is written to the local file system. Optionally, an {int-timeout} value can be specified in milliseconds as the last parameter. |nl-put-url| will return {ERR: timeout} when the host gives no response and the timeout expires. On other error conditions, |nl-put-url| returns a string starting with {ERR:} and the description of the error. |nl-put-url| requests are also understood by newLISP server nodes. > (put-url "http://asite.com/myFile.txt" "Hi there") (put-url "http://asite.com/myFile.txt" "Hi there" 2000) (put-url "http://asite.com/webpage.html" (read-file "webpage.html")) ; write /home/joe/newfile.txt on the local file system (puts-url "file:///home/joe/newfile.txt" "Hello World!") < The first example creates a file called {myFile.txt} on the target server and stores the text string {'Hi there'} in it. In the second example, the local file {webpage.html} is transferred to {asite.com}. On an Apache web server, the following could be configured in {httpd.conf}. > Options All Script PUT /cgi-bin/put.cgi < The script {put.cgi} would contain code to receive content from the web server via STDIN. The following is a working {put.cgi} written in newLISP for the Apache web server: > #!/usr/home/johndoe/bin/newlisp # # # get PUT method data from CGI STDIN # and write data to a file specified # int the PUT request # # (print "Content-Type: text/html\n\n") (set 'cnt 0) (set 'result "") (if (= "PUT" (env "REQUEST_METHOD")) (begin (set 'len (int (env "CONTENT_LENGTH"))) (while (< cnt len) (set 'n (read (device) buffer len)) (if (not n) (set 'cnt len) (begin (inc cnt n) (write result buffer)))) (set 'path (append "/usr/home/johndoe" (env "PATH_TRANSLATED"))) (write-file path result) ) ) (exit) < Note that the script appends ".txt" to the path to avoid the CGI execution of uploaded malicious scripts. Note also that the two lines where the file path is composed may work differently in your web server environment. Check environment variables passed by your web server for composition of the right file path. |nl-put-url| returns content returned by the {put.cgi} script. Additional parameters ^^^^^^^^^^^^^^^^^^^^^ In {str-option}, {"header"} or {"list"} can be specified for the returned page. If the {int-timeout} option is specified, the custom header option {str-header} can be specified, as well. See the function |nl-get-url| for details on both of these options. See also the functions |nl-get-url| and |nl-post-url|, which can be used to upload files when formatting form data as {multipart/form-data}. *newlisp-function-pv* *nl-pv* FUNCTION: pv~ {syntax:} (pv {num-int} {num-nper} {num-pmt} [{num-fv} [{int-type}]]) Calculates the present value of a loan with the constant interest rate {num-interest} and the constant payment {num-pmt} after {num-nper} number of payments. The future value {num-fv} is assumed to be {0.0} if omitted. If payment is at the end of the period, {int-type} is {0} (zero) or {int-type} is omitted; for payment at the beginning of each period, {int-type} is 1. > (pv (div 0.07 12) 240 775.30) ;→ -100000.1373 < In the example, a loan that would be paid off (future value = {0.0}) in 240 payments of $775.30 at a constant interest rate of 7 percent per year would start out at $100,000.14. See also the |nl-fv|, |nl-irr|, |nl-nper|, |nl-npv|, and |nl-pmt| functions. *newlisp-function-quote* *nl-quote* FUNCTION: quote~ {syntax:} (quote {exp}) Returns {exp} without evaluating it. The same effect can be obtained by prepending a {'} (single quote) to {exp}. > (quote x) ;→ x (quote 123) ;→ 123 (quote (a b c)) ;→ (a b c) (= (quote x) 'x) ;→ true < *newlisp-function-quote?* *nl-quote?* FUNCTION: quote?~ {syntax:} (quote? {exp}) Evaluates and tests whether {exp} is quoted. Returns {true} or {nil} depending on the result. > (set 'var ''x) ;→ 'x (quote? var) ;→ true < Note that in the |nl-set| statement, { ''x} is quoted twice because the first quote is lost during the evaluation of the |nl-set| assignment. *newlisp-function-rand* *nl-rand* FUNCTION: rand~ {syntax:} (rand {int-range} [{int-N}]) Evaluates the expression in {int-range} and generates a random number in the range of {0} (zero) to ({int-range} - 1). When {0} (zero) is passed, the internal random generator is initialized using the current value returned by the C {time()} function. Optionally, a second parameter can be specified to return a list of length {int-N} of random numbers. > (dotimes (x 100) (print (rand 2))) => 11100000110100111100111101 ... 10111101011101111101001100001000 (rand 3 100) ;→ (2 0 1 1 2 0 …) < The first line in the example prints equally distributed {0}'s and {1}'s, while the second line produces a list of 100 integers with {0}, {1}, and {2} equally distributed. Use the |nl-random| and |nl-normal| functions to generate floating point random numbers, and use |nl-seed| to vary the initial seed for random number generation. *newlisp-function-random* *nl-random* FUNCTION: random~ {syntax:} (random {float-offset} {float-scale} {int-n}) + {syntax:} (random {float-offset} {float-scale}) In the first form, |nl-random| returns a list of {int-n} evenly distributed floating point numbers scaled (multiplied) by {float-scale}, with an added offset of {float-offset}. The starting point of the internal random generator can be seeded using |nl-seed|. > (random 0 1 10) ;→ (0.10898973 0.69823783 0.56434872 0.041507289 0.16516733 0.81540917 0.68553784 0.76471068 0.82314585 0.95924564) < When used in the second form, |nl-random| returns a single evenly distributed number: > (random 10 5) ;→ 11.0971 < See also the |nl-normal| and |nl-rand| functions. *newlisp-function-randomize* *nl-randomize* FUNCTION: randomize~ {syntax:} (randomize {list} [{bool}]) Rearranges the order of elements in {list} into a random order. > (randomize '(a b c d e f g)) ;→ (b a c g d e f) (randomize (sequence 1 5)) ;→ (3 5 4 1 2) < |nl-randomize| will always return a sequence different from the previous one without the optional {bool} flag. This may require the function to calculate several sets of reordered elements, which in turn may lead to different processing times with different invocations of the function on the same input list length. To allow for the output to be equal to the input, {true} or any expression evaluating to not {nil} must be specified in {bool}. |nl-randomize| uses an internal {pseudo random sequence} generator that returns the same series of results each time newLISP is started. Use the |nl-seed| function to change this sequence. *newlisp-function-read* *nl-read* FUNCTION: read~ |nl-destructive| {syntax:} (read {int-file} {sym-buffer} {int-size} [{str-wait}]) Reads a maximum of {int-size} bytes from a file specified in {int-file} into a buffer in {sym-buffer}. Any data referenced by the symbol {sym-buffer} prior to the reading is deleted. The handle in {int-file} is obtained from a previous |nl-open| statement. The symbol {sym-buffer} contains data of type string after the read operation. {sym-buffer} can also be a default functor specified by a context symbol for reference passing in and out of user-defined functions. |nl-read| is a shorter writing of {read-buffer}. The longer form still works but is deprecated and should be avoided in new code. Optionally, a string to be waited for can be specified in {str-wait}. |nl-read| will read a maximum amount of bytes specified in {int-size} or return earlier if {str-wait} was found in the data. The wait-string is part of the returned data and must not contain binary {0} (zero) characters. Returns the number of bytes read or {nil} when the wait-string was not found. In any case, the bytes read are put into the buffer pointed to by {sym-buffer}, and the file pointer of the file read is moved forward. If no new bytes have been read, {sym-buffer} will contain {nil}. > (set 'handle (open "aFile.ext" "read")) (read handle buff 200) < Reads 200 bytes into the symbol {buff} from the file {aFile.ext}. > (read handle buff 1000 "password:") < Reads 1000 bytes or until the string {password:} is encountered. The string {password:} will be part of the data returned. See also the |nl-write| function. *newlisp-function-read-char* *nl-read-char* FUNCTION: read-char~ {syntax:} (read-char [{int-file}]) Reads a byte from a file specified by the file handle in {int-file} or from the current I/O device - e.g. {stdin} - when no file handle is specified. The file handle is obtained from a previous |nl-open| operation. Each |nl-read-char| advances the file pointer by one byte. Once the end of the file is reached, {nil} is returned. > (define (slow-file-copy from-file to-file) (set 'in-file (open from-file "read")) (set 'out-file (open to-file "write")) (while (set 'chr (read-char in-file)) (write-char out-file chr)) (close in-file) (close out-file) "finished") < Use |nl-read-line| and |nl-device| to read whole text lines at a time. Note that newLISP supplies a fast built-in function called |nl-copy-file| for copying files. See also the |nl-write-char| function. *newlisp-function-read-expr* *nl-read-expr* FUNCTION: read-expr~ {syntax:} (read-expr {str-source} [{sym-context} [{exp-error} [{int-offset}]]]) |nl-read-expr| parses the first expressions it finds in {str-source} and returns the translated expression without evaluating it. An optional context in {sym-context} specifies a namespace for the translated expression. After a call to |nl-read-expr| the system variable {$0} contains the number of characters scanned. If an error occurs when translating {str-source} the expression in {exp-error} is evaluated and the result returned. {int-offset} specifies an optional offset into {str-source} where processing should start. When calling |nl-read-expr| repeatedly this number can be updated using {$0}. > (set 'code "; a statement\n(define (double x) (+ x x))") (read-expr code) ;→ (define (double x) (+ x x)) $0 ;→ 41 < |nl-read-expr| behaves similar to |nl-eval-string| but without the evaluation step: > (read-expr "(+ 3 4)") ;→ (+ 3 4) (eval-string "(+ 3 4)") ;→ 7 < Using |nl-read-expr| a customized code reader can be programmed preprocessing expressions before evaluation. See also |nl-reader-event| for preprocessing expressions event-driven. *newlisp-function-read-file* *nl-read-file* FUNCTION: read-file~ {syntax:} (read-file {str-file-name}) Reads a file in {str-file-name} in one swoop and returns a string buffer containing the data. On failure the function returns {nil}. For error information, use |nl-sys-error| when used on files. When used on URLs |nl-net-error| gives more error information. > (write-file "myfile.enc" (encrypt (read-file "/home/lisp/myFile") "secret")) < The file {myfile} is read, then encrypted using the password {"secret"} before being written back into a new file titled {"myfile.enc"} in the current directory. |nl-read-file| can take an {http://} or {file://} URL in {str-file-name}. When the prefix is {http://}, |nl-read-file| works exactly like |nl-get-url| and can take the same additional parameters. > (read-file "http://asite.com/somefile.tgz" 10000) < The file {somefile.tgz} is retrieved from the remote location {http://asite.com}. The file transfer will time out after 10 seconds if it is not finished. In this mode, |nl-read-file| can also be used to transfer files from remote newLISP server nodes. See also the |nl-write-file| and |nl-append-file| functions. *newlisp-function-read-key* *nl-read-key* FUNCTION: read-key~ {syntax:} (read-key) Reads a key from the keyboard and returns an integer value. For navigation keys, more than one |nl-read-key| call must be made. For keys representing ASCII characters, the return value is the same on all OSes, except for navigation keys and other control sequences like function keys, in which case the return values may vary on different OSes and configurations. > (read-key) ;→ 97 ; after hitting the A key (read-key) ;→ 65 ; after hitting the shifted A key (read-key) ;→ 10 ; after hitting [enter] on Linux (read-key) ;→ 13 ; after hitting [enter] on Win32 (while (!= (set 'c (read-key)) 1) (println c)) < The last example can be used to check return sequences from navigation and function keys. To break out of the loop, press {Ctrl-A}. Note that |nl-read-key| will only work when newLISP is running in a Unix shell or Win32 command shell. It will not work in the Java based newLISP-GS or Tcl/Tk based newLISP-Tk frontend. It will also not work when executed by newLISP Unix shared library or newLISP Win32 DLL (Dynamic Link Library). *newlisp-function-read-line* *nl-read-line* FUNCTION: read-line~ {syntax:} (read-line [{int-file}]) Reads from the current I/O device a string delimited by a line-feed character (ASCII 10). There is no limit to the length of the string that can be read. The line-feed character is not part of the returned string. The line always breaks on a line-feed, which is then swallowed. A line breaks on a carriage return (ASCII 13) only if followed by a line-feed, in which case both characters are discarded. A carriage return alone only breaks and is swallowed if it is the last character in the stream. By default, the current |nl-device| is the keyboard (|nl-device| {0}). Use the built-in function |nl-device| to specify a different I/O device (e.g., a file). Optionally, a file handle can be specified in the {int-file} obtained from a previous |nl-open| statement. The last buffer contents from a read-line operation can be retrieved using |nl-current-line|. When |nl-read-line| is reading from a file or from {stdin} in a CGI program or pipe, it will return {nil} when input is exhausted. When using |nl-read-line| on {stdin}, line length is limited to 2048 characters and performance is much faster. > (print "Enter a num:") (set 'num (int (read-line))) (set 'in-file (open "afile.dat" "read")) (while (read-line in-file) (write-line)) (close in-file) < The first example reads input from the keyboard and converts it to a number. In the second example, a file is read line-by-line and displayed on the screen. The |nl-write-line| statement takes advantage of the fact that the result from the last |nl-read-line| operation is stored in a system internal buffer. When |nl-write-line| is used without argument, it writes the contents of the last |nl-read-line| buffer to the screen. See also the |nl-current-line| function for retrieving this buffer. *newlisp-function-read-utf8* *nl-read-utf8* FUNCTION: read-utf8~ {syntax:} (read-utf8 {int-file}) Reads an UTF-8 character from a file specified by the file handle in {int-file}. The file handle is obtained from a previous |nl-open| operation. Each |nl-read-utf8| advances the file pointer by the number of bytes contained in the UTF-8 character. Once the end of the file is reached, {nil} is returned. The function returns an integer value which can be converted to a displayable UTF-8 character string using the |nl-char| function. > (set 'fle (open "utf8text.txt" "read")) (while (setq chr (read-utf8 fle)) (print (char chr))) < The example reads a file containing UTF-8 encoded text and displays it to the terminal screen. *newlisp-function-reader-event* *nl-reader-event* FUNCTION: reader-event~ {syntax:} (reader-event [{sym-event-handler | func-event-handler}]) + {syntax:} (reader-event 'nil) An event handler can be specified to hook between newLISP's reader, translation and evaluation process. The function specified in {sym-event-handler} or {func-event-handler} gets called after newLISP translates an expression and before evaluating it. The event handler can do transformation on the expression before it gets evaluated. Specifying a quoted {nil} for the event will disable it. The following one-liner |nl-reader-event| could be used to enhance the interactive shell with a tracer: > >(reader-event (lambda (ex) (print " => " ex))) $reader-event > (+ 1 2 3) => (+ 1 2 3) 6 > < The expression intercepted passes through unchanged, but output is enhanced. The following example shows the core of a simple macro rewrite pre-processor. A full version is installed in the standard location as module file {macro.lsp}. > (context 'macro) ; initialize macro list (setf macro-list '()) ; registers a macro (define-macro (macro:macro callp body) (push (list (first callp) '*) macro-list -1) (eval (expand '(define-macro callp (expand 'body)) 'callp 'body)) ) ; the event handler translating expressions (define (rewrite expr) (if (list? expr) (dolist (pattern macro-list) (if (match pattern expr) (setf expr (eval expr)) (set-ref-all pattern expr (eval $it) match)) ) ) expr ) ; register event handler (reader-event rewrite) (context MAIN) < The reader event function will be called after each reading of an s-expression by the |nl-load| or |nl-eval-string| function. Register a function macro for pre-processing: > (macro (square X) (pow X 2)) ; must use uppercase vars ; use the macro (square 3) ;→ 9 < After registering the macro {square} newLISP will expand each occurrence of a {(square ...)} to a {(pow ... 2)} expression. Note, that variables in the macro definition must be upper-case. The macro registering function uses a syntax form of |nl-expand| working only on upper-case variables. For a more detailed description see the documentation for {macro.lsp}. *newlisp-function-real-path* *nl-real-path* FUNCTION: real-path~ {syntax:} (real-path [{str-path}]) Returns the full path from the relative file path given in {str-path}. If a path is not given, {"."} (the current directory) is assumed. > (real-path) ;→ "/usr/home/fred" ; current directory (real-path "./somefile.txt") ;→ "/usr/home/fred/somefile.txt" < The output length is limited by the OS's maximum allowed path length. If |nl-real-path| fails (e.g., because of a nonexistent path), {nil} is returned. *newlisp-function-receive* *nl-receive* FUNCTION: receive~ |nl-destructive| {syntax:} (receive {int-pid} {sym-message}) + {syntax:} (receive) In the first syntax, the function is used for message exchange between child processes launched with |nl-spawn| and their parent process. The message received replaces the contents in {sym-message.} The function reads one message from the receiver queue of {int-pid} for each invocation. When the queue is empty, {nil} is returned. > ; sending process (send spid "hello") ;→ true ; receiving process (receive pid msg) ;→ true msg ;→ "hello" < To make |nl-receive| blocking and wait for arriving messages, use the following form: > ; wait until a message can be read (until (receive pid msg)) < The function will loop until a message can be read from the queue. In the second syntax, the function returns a list of all child processes with pending messages for the parent process: > ; read pending messages from child processes (dolist (pid (receive)) (receive pid msg) (println "received message: " msg " from:" pid) ) < The list of child process IDs returned by {(receive)} only contains PIDs of processes which have unread messages in their send queues. The {(receive pid msg)} statement now can be issued non-blocking, because it always is guarenteed to find a pending message in a child's message queue. The |nl-receive| function is not available on Win32. For a more detailed discussion of this function and examples, see the |nl-send| function. *newlisp-function-ref* *nl-ref* FUNCTION: ref~ {syntax:} (ref {exp-key} {list} [{func-compare} [true]]) |nl-ref| searches for the key expression {exp-key} in {list} and returns a list of integer indices or an empty list if {exp-key} cannot be found. |nl-ref| can work together with |nl-push| and link:pop[pop], both of which can also take lists of indices. By default, |nl-ref| checks if expressions are equal. With {func-compare}, more complex comparison functions can be used. The comparison function can be a previously defined function. Note that this function always takes two arguments, even if only the second argument is used inside the function. When the optional {true} parameter is present, the element found is returned instead of the index vector. > ; get index vectors for list elements (set 'pList '(a b (c d (x) e))) (ref 'x pList) ;→ (2 2 0) (ref '(x) pList) ;→ (2 2) ; the key expression is in a variable (set 'p '(c d (x) e)) (ref p pList p) ;→ (2) ; indexing using the vector returned from ref (set 'v (ref '(x) pList)) ;→ (2 2) (pList v) ;→ (x) ; if nothing is found, nil is returned (ref 'foo plist) ;→ nil ; not specifying a comparison functor assumes = (set 'L '(a b (c d (e) f))) (ref 'e L) ;→ (2 2 0) (ref 'e L =) ;→ (2 2 0) ; a is the first symbol where e is greater (ref 'e L >) ;→ (0) ; return the element instead of the index (ref 'e L > true) ;→ a ; use an anonymous comparison function (ref 'e L (fn (x y) (or (= x y) (= y 'd)))) ;→ (2 1) (ref 'e L (fn (x y) (or (= x y) (= y 'd))) true) ;→ d < The following example shows the use of |nl-match| and |nl-unify| to formulate searches that are as powerful as regular expressions are for strings: > (set 'L '((l 3) (a 12) (k 5) (a 10) (z 22))) ; use match as a comparison function (ref '(a ?) L match) ;→ (1) ; use unify as a comparison function (set 'L '( ((a b) (c d)) ((e e) (f g)) )) (ref '(X X) L unify) ;→ (1 0) (ref '(X g) L unify) ;→ (1 1) (ref '(X g) L unify true) ;→ (f g) < The {'(X X)} pattern with |nl-unify| searches for a list pair where the two elements are equal. The |nl-unify| pattern {'(X g)} searches for a list pair with the symbol {g} as the second member. The patterns are quoted to protect them from evaluation. Pass the list as a default functor: > (set 'C:C '(a b (c d) e f)) (ref 'd C) ;→ (2 1) < This is suitable when passing lists by reference using a context. See also the chapter |nl-Passing data by reference|. See also the |nl-ref-all| function, which searches for all occurrences of a key expression in a nested list. *newlisp-function-ref-all* *nl-ref-all* FUNCTION: ref-all~ {syntax:} (ref-all {exp-key} {list} [{func-compare} [true]]) Works similarly to |nl-ref|, but returns a list of all index vectors found for {exp-key} in {list}. When the optional {true} parameter is present, the elements found is returned of the index vectors. By default, |nl-ref-all| checks if expressions are equal. With {func-compare}, more complex comparison functions can be used. > (set 'L '(a b c (d a f (a h a)) (k a (m n a) (x)))) (ref-all 'a L) ;→ ((0) (3 1) (3 3 0) (3 3 2) (4 1) (4 2 2)) ; the index vector returned by ref-all can be used to index the list (L '(3 1)) ;→ a ; mapped implicit indexing of L (map 'L (ref-all 'a L)) ;→ (a a a a a a) ; with comparison operator (set 'L '(a b c (d f (h l a)) (k a (m n) (x)))) ; not specifying a comparison functor assumes = (ref-all 'c L) ;→ ((2)) (ref-all 'c L =) ;→ ((2)) ; look for all elements where c is greater (ref-all 'c L >) ;→ ((0) (1) (3 2 2) (4 1)) (ref-all 'c L > true) ;→ (a b a a) ; use an anonymous function to compare (ref-all 'a L (fn (x y) (or (= x y) (= y 'k)))) ;→ ((0) (3 2 2) (4 0) (4 1)) ; the key is nil because the comparison function only looks at the second argument (ref-all nil L (fn (x y) (> (length y) 2))) ;→ ((3) (3 2) (4)) ; define the comparison functions first (define (is-long? x y) (> (length y) 2)) ; the x gets occupied by 'nil (ref-all nil L is-long?) ;→ ((3) (3 2) (4)) (define (is-it-or-d x y) (or (= x y) (= y 'd))) (set 'L '(a b (c d (e) f)) ) (ref-all 'e L is-it-or-d) ;→ ((2 1) (2 2 0)) < The comparison function can be a previously defined function. Note that the comparison function always takes two arguments, even if only the second argument is used inside the function (as in the example using {is-long?}). Using the |nl-match| and |nl-unify| functions, list searches can be formulated that are as powerful as regular expression searches are for strings. > (set 'L '((l 3) (a 12) (k 5) (a 10) (z 22)) ) ; look for all pairs staring with the symbol a (ref-all '(a ?) L match) ;→ ((1) (3)) (ref-all '(a ?) L match true) ;→ ((a 12) (a 10)) ; look for all pairs where elements are equal (set 'L '( ((a b) (c d)) ((e e) (f g)) ((z) (z)))) (ref-all '(X X) L unify) ;→ ((1 0) (2)) (ref-all '(X X) L unify true) ;→ ((e e) ((z) (z))) ; look for all pairs where the second element is the symbol g (set 'L '( ((x y z) g) ((a b) (c d)) ((e e) (f g)) )) (ref-all '(X g) L unify) ;→ ((0) (2 1)) (ref-all '(X g) L unify true) ;→ (((x y z) g) (f g)) < See also the |nl-ref| function. *newlisp-function-regex* *nl-regex* FUNCTION: regex~ {syntax:} (regex {str-pattern} {str-text} [{int-option} [{int-offset}]]) Performs a Perl Compatible Regular Expression (PCRE) search on {str-text} with the pattern specified in {str-pattern}. The same regular expression pattern matching is also supported in the functions |nl-directory|, |nl-find|, |nl-find-all|, |nl-parse|, |nl-replace|, and |nl-search| when using these functions on strings. |nl-regex| returns a list with the matched strings and substrings and the beginning and length of each string inside the text. If no match is found, it returns {nil}. The offset numbers can be used for subsequent processing. Additionally an {int-option} can be specified to control certain regular expression options explained later. The additional {int-offset} parameter tells |nl-regex| to start searching for a match not at the beginning of the string but at an offset. The offset and length numbers in the |nl-regex| results are given based on single bytes even when running the UTF-8 enabled version of newLISP. |nl-regex| also sets the variables {$0, $1,} and {$2—} to the expression and subexpressions found. Just like any other symbol in newLISP, these variables or their equivalent expressions {($ 0), ($ 1),} and {($ 2)—} can be used in other newLISP expressions for further processing. Functions using regular expressions will not reset the {$0, $1 ... $15} variables to {nil} when no match is found. > (regex "b+" "aaaabbbaaaa") ;→ ("bbb" 4 3) ; case-insensitive search option 1 (regex "b+" "AAAABBBAAAA" 1) ;→ ("BBB" 4 3) (regex "[bB]+" "AAAABbBAAAA" ) ;→ ("BbB" 4 3) (regex "http://(.*):(.*)" "http://nuevatec.com:80") ;→ ("http://nuevatec.com:80" 0 22 "nuevatec.com" 7 12 "80" 20 2) $0 ;→ "http://nuevatec.com:80" $1 ;→ "nuevatec.com" $2 ;→ "80" (dotimes (i 3) (println ($ i))) http://nuevatec.com:80 nuevatec.com 80 ;→ "80" < The second example shows the usage of extra options, while the third example demonstrates more complex parsing of two subexpressions that were marked by parentheses in the search pattern. In the last example, the expression and subexpressions are retrieved using the system variables {$0} to {$2} or their equivalent expression {($ 0)} to {($ 2)}. When {""} (quotes) are used to delimit strings that include literal backslashes, the backslash must be doubled in the regular expression pattern. As an alternative, {{ }} (curly brackets) or {[text]} and {[/text]} (text tags) can be used to delimit text strings. In these cases, no extra backslashes are required. Characters escaped by a backslash in newLISP (e.g., the quote {\"} or {\n}) need not to be doubled in a regular expression pattern, which itself is delimited by quotes. > ;; double backslash for parentheses (special char in regex) (regex "\\(abc\\)" "xyz(abc)xyz") ;→ ("(abc)" 3 5) ;; one backslash for quotes (special char in newLISP) (regex "\"" "abc\"def") ;→ ("\"" 3 1) ;; brackets as delimiters (regex {\(abc\)} "xyz(abc)xyz") ;→ ("(abc)" 3 5) ;; brackets as delimiters and quote in pattern (regex {"} "abc\"def") ;→ ("\"" 3 1) ;; text tags as delimiters, good for multiline text in CGI (regex [text]\(abc\)[/text] "xyz(abc)xyz") ;→ ("(abc)" 3 5) (regex [text]"[/text] "abc\"def") ;→ ("\"" 3 1) < When curly brackets or text tags are used to delimit the pattern string instead of quotes, a simple backslash is sufficient. The pattern and string are then passed in raw form to the regular expression routines. When curly brackets are used inside a pattern itself delimited by curly brackets, the inner brackets must be balanced, as follows: > ;; brackets inside brackets are balanced (regex {\d{1,3}} "qwerty567asdfg") ;→ ("567" 6 3) < The following constants can be used for {int-option}. Several options can be combined using a binary or {|} (pipe) operator. E.g. {(| 1 4)} would combine options {1} and {4}. The uppercase names are used in the PCRE regex documentation and could be predefined in {init.lsp}. The last option is a newLISP custom option only to be used in |nl-replace|; it can be combined with PCRE options. [cols="3<,1<,5<",width="75%",options="header",] |======================================================================= |PCRE name |no |description |PCRE_CASELESS |1 |treat uppercase like lowercase |PCRE_MULTILINE |2 |limit search at a newline like Perl's /m |PCRE_DOTALL |4 |. (dot) also matches newline |PCRE_EXTENDED |8 |ignore whitespace except inside char class |PCRE_ANCHORED |16 |anchor at the start |PCRE{DOLLAR}ENDONLY |32 |$ matches at end of string, not before newline |PCRE_EXTRA |64 |additional functionality currently not used |PCRE_NOTBOL |128 |first ch, not start of line; ^ shouldn't match |PCRE_NOTEOL |256 |last char, not end of line; $ shouldn't match |PCRE_UNGREEDY |512 |invert greediness of quantifiers |PCRE_NOTEMPTY |1024 |empty string considered invalid |PCRE_UTF8 |2048 |pattern and strings as UTF-8 characters |REPLACE_ONCE |0x8000 |replace only one occurrence only for use in |nl-replace| |PRECOMPILED |0x10000 |pattern is pre-compiled, can only be combined with RREPLACE_ONCE 0x8000 |======================================================================= The settings of the PCRE{CASELESS, PCRE}MULTILINE, PCRE_DOTALL, and PCRE_EXTENDED options can be changed from within the pattern by a sequence of option letters enclosed between "(?" and ")". The option letters are: [cols="1<,4<",width="15%"] |===================== |i |for PCRE_CASELESS |m |for PCRE_MULTILINE |s |for PCRE_DOTALL |x |for PCRE_EXTENDED |===================== Note that regular expression syntax is very complex and feature-rich with many special characters and forms. Please consult a book or the PCRE manual pages for more detail. Most PERL books or introductions to Linux or Unix also contain chapters about regular expressions. See also http://www.pcre.org[http://www.pcre.org] for further references and manual pages. Regular expression patterns can be precompiled for higher speed when using changing repetitive patterns with |nl-regex-comp|. *newlisp-function-regex-comp* *nl-regex-comp* FUNCTION: regex-comp~ {syntax:} (regex-comp {str-pattern} [{int-option}]) newLISP automatically compiles regular expression patterns and caches the last compilation to speed up repetitive pattern searches. If patterns change from one to the next, but are repeated over and over again, then the caching of the last pattern is not sufficient. |nl-regex-comp| can be used to pre-compile repetitive patterns to speed up regular expression searches: > ; slower without pre-compilation (dolist (line page) (replace pattern-str1 line repl1 0) (replace pattern-str2 line repl2 512) ) ; fast with pre-compilation and option 0x10000 (set 'p1 (regex-comp pattern-str1)) (set 'p2 (regex-comp pattern-str2 512)) (dolist (line page) (replace p1 line repl1 0x10000) (replace p2 line repl2 0x10000) ) < When using pre-compiled patterns in any of the functions using regular expressions, the option number is set to {0x10000} to signal that pre-compiled patterns are used. Normal pattern options are specified during pre-compilation with |nl-regex-comp| . The {0x10000} option can only be combined with {0x8000}, the option used to specify that only one replacement should be made when using |nl-replace|. *newlisp-function-remove-dir* *nl-remove-dir* FUNCTION: remove-dir~ {syntax:} (remove-dir {str-path}) Removes the directory whose path name is specified in {str-path}. The directory must be empty for |nl-remove-dir| to succeed. Returns {nil} on failure. > (remove-dir "temp") < Removes the directory {temp} in the current directory. *newlisp-function-rename-file* *nl-rename-file* FUNCTION: rename-file~ {syntax:} (rename-file {str-path-old} {str-path-new}) Renames a file or directory entry given in the path name {str-path-old} to the name given in {str-path-new}. Returns {nil} or {true} depending on the operation's success. > (rename-file "data.lisp" "data.backup") < *newlisp-function-replace* *nl-replace* FUNCTION: replace~ |nl-destructive| {syntax:} (replace {exp-key} {list} {exp-replacement} [{func-compare}]) + {syntax:} (replace {exp} {list}) + {syntax:} (replace {str-key} {str-data} {exp-replacement}) + {syntax:} (replace {str-pattern} {str-data} {exp-replacement} {int-regex-option}) List replacement ^^^^^^^^^^^^^^^^ If the second argument is a list, |nl-replace| replaces all elements in the list {list} that are equal to the expression in {exp-key}. The element is replaced with {exp-replacement}. Note that |nl-replace| is destructive. It changes the list passed to it and returns the changed list. The number of replacements made is contained in the system variable {$0} when the function returns. During executions of the replacement expression, the system variable {$0} and the anaphoric system variable {$it} are set to the expression to be replaced. Optionally, {func-compare} can specify a comparison operator or user-defined function. By default, {func-compare} is the |nl-=| (equals sign). > ;; list replacement (set 'aList '(a b c d e a b c d)) (replace 'b aList 'B) ;→ (a B c d e a B c d) aList ;→ (a B c d e a B c d) $0 ;→ 2 ; number of replacements ;; list replacement with special compare functor/function ; replace all numbers where 10 < number (set 'L '(1 4 22 5 6 89 2 3 24)) (replace 10 L 10 <) ;→ (1 4 10 5 6 10 2 3 10) ; same as: (replace 10 L 10 (fn (x y) (< x y))) ;→ (1 4 10 5 6 10 2 3 10) ; change name-string to symbol, x is ignored as nil (set 'AL '((john 5 6 4) ("mary" 3 4 7) (bob 4 2 7 9) ("jane" 3))) (replace nil AL (cons (sym ($it 0)) (rest $it)) (fn (x y) (string? (y 0)))) ;→ ((john 5 6 4) (mary 3 4 7) (bob 4 2 7 9) (jane 3)) < Using the |nl-match| and |nl-unify| functions, list searches can be formulated that are as powerful as regular expression string searches: > ; calculate the sum in all associations with 'mary (set 'AL '((john 5 6 4) (mary 3 4 7) (bob 4 2 7 9) (jane 3))) (replace '(mary *) AL (list 'mary (apply + (rest $it))) match) ;→ ((john 5 6 4) (mary 14) (bob 4 2 7 9) (jane 3)) ; make sum in all expressions (set 'AL '((john 5 6 4) (mary 3 4 7) (bob 4 2 7 9) (jane 3))) (replace '(*) AL (list ($0 0) (apply + (rest $it))) match) ;→ ((john 15) (mary 14) (bob 22) (jane 3)) ; using unify (replace '(X X) '((3 10) (2 5) (4 4) (6 7) (8 8)) (list ($it 0) 'double ($it 1)) unify) ;→ ((3 10) (2 5) (4 double 4) (6 7) (8 double 8)) < List removal ^^^^^^^^^^^^ The last form of |nl-replace| has only two arguments: the expression {exp} and {list}. This form removes all {exp}s found in {list}. > ;; removing elements from a list (set 'lst '(a b a a c d a f g)) (replace 'a lst) ;→ (b c d f g) lst ;→ (b c d f g) $0 ;→ 4 < String replacement without regular expression ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ If all arguments are strings, |nl-replace| replaces all occurrences of {str-key} in {str-data} with the evaluated {exp-replacement}, returning the changed string. The expression in {exp-replacement} is evaluated for every replacement. The number of replacements made is contained in the system variable {$0}. This form of |nl-replace| can also process binary {0}s (zeros). > ;; string replacement (set 'str "this isa sentence") (replace "isa" str "is a") ;→ "this is a sentence" < Regular expression replacement ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The presence of a fourth parameter indicates that a regular expression search should be performed with a regular expression pattern specified in {str-pattern} and an option number specified in {int-option} (e.g., {1} (one) for case-insensitive searching or {0} (zero) for a standard Perl Compatible Regular Expression (PCRE) search). See |nl-regex| above for details. By default, |nl-replace| replaces all occurrences of a search string even if a beginning-of-line specification is included in the search pattern. After each replace, a new search is started at a new position in {str-data}. Setting the option bit to {0x8000} in {int-option} will force |nl-replace| to replace only the first occurrence. The changed string is returned. |nl-replace| with regular expressions also sets the internal variables {$0, $1,} and {$2—} with the contents of the expressions and subexpressions found. The anaphoric system variable {$it} is set to the same value as {$0}. These can be used to perform replacements that depend on the content found during replacement. The symbols {$it, $0, $1,} and {$2—} can be used in expressions just like any other symbols. If the replacement expression evaluates to something other than a string, no replacement is made. As an alternative, the contents of these variables can also be accessed by using {($ 0), ($ 1), ($ 2),} and so forth. This method allows indexed access (e.g., {($ i)}, where {i} is an integer). After all replacements are made, the number of replacements is contained in the system variable {$0}. > ;; using the option parameter to employ regular expressions (set 'str "ZZZZZxZZZZyy") ;→ "ZZZZZxZZZZyy" (replace "[x|y]" str "PP" 0) ;→ "ZZZZZPPZZZZPPPP" str ;→ "ZZZZZPPZZZZPPPP" ;; using system variables for dynamic replacement (set 'str "---axb---ayb---") (replace "(a)(.)(b)" str (append $3 $2 $1) 0) ;→ "---bxa---bya---" str ;→ "---bxa---bya---" ;; using the 'replace once' option bit 0x8000 (replace "a" "aaa" "X" 0) ;→ "XXX" (replace "a" "aaa" "X" 0x8000) ;→ "Xaa" ;; URL translation of hex codes with dynamic replacement (set 'str "xxx%41xxx%42") (replace "%([0-9A-F][0-9A-F])" str (char (int (append "0x" $1))) 1) str ;→ "xxxAxxxB" $0 ;→ 2 < The |nl-setf| function together with |nl-nth|, |nl-first| or |nl-last| can also be used to change elements in a list. See |nl-directory|, |nl-find|, |nl-find-all|, |nl-parse|, |nl-regex|, and |nl-search| for other functions using regular expressions. *newlisp-function-reset* *nl-reset* FUNCTION: reset~ {syntax:} (reset) + {syntax:} (reset true) In the first syntax, |nl-reset| returns to the top level of evaluation, switches the |nl-trace| mode off, and switches to the MAIN context/namespace. |nl-reset| restores the top-level variable environment using the saved variable environments on the stack. It also fires an error "user reset - no error". This behavior can be used when writing error handlers. |nl-reset| may return memory that was claimed by newLISP to the operating system. |nl-reset| walks through the entire cell space, which may take a few seconds in a heavily loaded system. |nl-reset| occurs automatically after an error condition. In the second syntax, |nl-reset| will stop the current process and start a new clean newLISP process with the same command-line parameters. This mode will only work when newLISP was started using its full path-name, e.g. {/usr/bin/newlisp} instead of only {newlisp}. This mode is not available on Win32. *newlisp-function-rest* *nl-rest* FUNCTION: rest~ |nl-utf8_capable| {syntax:} (rest {list}) + {syntax:} (rest {array}) + {syntax:} (rest {str}) Returns all of the items in a list or a string, except for the first. |nl-rest| is equivalent to {cdr} or {tail} in other Lisp dialects. > (rest '(1 2 3 4)) ;→ (2 3 4) (rest '((a b) c d)) ;→ (c d) (set 'aList '(a b c d e)) ;→ (a b c d e) (rest aList) ;→ (b c d e) (first (rest aList)) ;→ b (rest (rest aList)) ;→ (d e) (rest (first '((a b) c d))) ;→ (b) (set 'A (array 2 3 (sequence 1 6))) ;→ ((1 2) (3 4) (5 6)) (rest A) ;→ ((3 4) (5 6)) (rest '()) ;→ () < In the second version, |nl-rest| returns all but the first character of the string {str} in a string. > (rest "newLISP") ;→ "ewLISP" (first (rest "newLISP")) ;→ "e" < See also the |nl-first| and |nl-last| functions. Note that an {implicit rest} is available for lists. See the chapter |nl-Implicit rest and slice|. Note that |nl-rest| works on character boundaries rather than byte boundaries when the UTF-8–enabled version of newLISP is used. *newlisp-function-reverse* *nl-reverse* FUNCTION: reverse~ |nl-destructive| {syntax:} (reverse {list}) + {syntax:} (reverse {string}) In the first form, |nl-reverse| reverses and returns the {list}. Note that |nl-reverse| is destructive and changes the original list. > (set 'l '(1 2 3 4 5 6 7 8 9)) (reverse l) ;→ (9 8 7 6 5 4 3 2 1) l ;→ (9 8 7 6 5 4 3 2 1) < In the second form, |nl-reverse| is used to reverse the order of characters in a string. > (set 'str "newLISP") (reverse str) ;→ "PSILwen" str ;→ "PSILwen" < See also the |nl-sort| function. *newlisp-function-rotate* *nl-rotate* FUNCTION: rotate~ |nl-destructive| {syntax:} (rotate {list} [{int-count}]) + {syntax:} (rotate {str} [{int-count}]) Rotates and returns the {list} or string in {str}. A count can be optionally specified in {int-count} to rotate more than one position. If {int-count} is positive, the rotation is to the right; if {int-count} is negative, the rotation is to the left. If no {int-count} is specified, |nl-rotate| rotates 1 to the right. |nl-rotate| is a destructive function that changes the contents of the original list or string. > (set 'l '(1 2 3 4 5 6 7 8 9)) (rotate l) ;→ (9 1 2 3 4 5 6 7 8) (rotate l 2) ;→ (7 8 9 1 2 3 4 5 6) l ;→ (7 8 9 1 2 3 4 5 6) (rotate l -3) ;→ (1 2 3 4 5 6 7 8 9) (set 'str "newLISP") (rotate str) ;→ "PnewLIS" (rotate str 3) ;→ "LISPnew" (rotate str -4) ;→ "newLISP" < When working on a string, |nl-rotate| works on byte boundaries rather than character boundaries. *newlisp-function-round* *nl-round* FUNCTION: round~ {syntax:} (round {number} [{int-digits}]) Rounds the number in {number} to the number of digits given in {int-digits}. When decimals are being rounded, {int-digits} is negative. It is positive when the integer part of a number is being rounded. If {int-digits} is omitted, the function rounds to {0} decimal digits. > (round 123.49 2) ;→ 100 (round 123.49 1) ;→ 120 (round 123.49 0) ;→ 123 (round 123.49) ;→ 123 (round 123.49 -1) ;→ 123.5 (round 123.49 -2) ;→ 123.49 < Note that rounding for display purposes is better accomplished using |nl-format|. *newlisp-function-save* *nl-save* FUNCTION: save~ {syntax:} (save {str-file}) + {syntax:} (save {str-file} {sym-1} [{sym-2} ... ]) In the first syntax, the |nl-save| function writes the contents of the newLISP workspace (in textual form) to the file {str-file}. |nl-save| is the inverse function of |nl-load|. Using |nl-load| on files created with |nl-save| causes newLISP to return to the same state as when |nl-save| was originally invoked. System symbols starting with the |nl-$| character (e.g., {$0} from regular expressions or {$main-args} from the command-line), symbols of built-in functions and symbols containing {nil} are not saved. In the second syntax, symbols can be supplied as arguments. If {sym-n} is supplied, only the definition of that symbol is saved. If {sym-n} evaluates to a context, all symbols in that context are saved. More than one symbol can be specified, and symbols and context symbols can be mixed. When contexts are saved, system variables and symbols starting with the |nl-$| character are not saved. Specifying system symbols explicitly causes them to be saved. Each symbol is saved by means of a |nl-set| statement or—if the symbol contains a lambda or lambda-macro function—by means of |nl-define| or |nl-define-macro| statements. |nl-save| returns {true} on completion. > (save "save.lsp") (save "/home/myself/myfunc.LSP" 'my-func) (save "file:///home/myself/myfunc.LSP" 'my-func) (save "http://asite.com:8080//home/myself/myfunc.LSP" 'my-func) (save "mycontext.lsp" 'mycontext) ;; multiple args (save "stuff.lsp" 'aContext 'myFunc '$main-args 'Acontext) < Because all context symbols are part of the context {MAIN}, saving {MAIN} saves all contexts. Saving to a URL will cause an HTTP PUT request to be sent to the URL. In this mode, |nl-save| can also be used to push program source to remote newLISP server nodes. Note that a double backslash is required when path names are specified relative to the root directory. |nl-save| in {HTTP} mode will observe a 60-second timeout. Symbols made using |nl-sym| that are incompatible with the normal syntax rules for symbols are serialized using a |nl-sym| statement instead of a |nl-set| statement. |nl-save| serializes contexts and symbols as if the current context is {MAIN}. Regardless of the current context, |nl-save| will always generate the same output. See also the functions |nl-load| (the inverse operation of |nl-save|) and |nl-source|, which saves symbols and contexts to a string instead of a file. *newlisp-function-search* *nl-search* FUNCTION: search~ {syntax:} (search {int-file} {str-search} [{bool-flag} [{int-options}]]) Searches a file specified by its handle in {int-file} for a string in {str-search}. {int-file} can be obtained from a previous |nl-open| file. After the search, the file pointer is positioned at the beginning or the end of the searched string or at the end of the file if nothing is found. By default, the file pointer is positioned at the beginning of the searched string. If {bool-flag} evaluates to {true}, then the file pointer is positioned at the end of the searched string. In {int-options}, the options flags can be specified to perform a PCRE regular expression search. See the function |nl-regex| for details. If {int-options} is not specified a faster, plain string search is performed. |nl-search| returns the new file position or {nil} if nothing is found. When using the regular expression options flag, patterns found are stored in the system variables {$0} to {$15}. > (set 'file (open "init.lsp" "read")) (search file "define") (print (read-line file) "\n") (close file) (set 'file (open "program.c" "r")) (while (search file "#define (.*)" true 0) (println $1)) (close file) < The file {init.lsp} is opened and searched for the string |nl-define| and the line in which the string occurs is printed. The second example looks for all lines in the file {program.c} which start with the string {#define} and prints the rest of the line after the string "#define ". For other functions using regular expressions, see |nl-directory|, |nl-find|, |nl-find-all|, |nl-parse|, |nl-regex|, and |nl-replace|. *newlisp-function-seed* *nl-seed* FUNCTION: seed~ {syntax:} (seed {int-seed}) Seeds the internal random generator that generates numbers for |nl-amb|, |nl-normal|, |nl-rand|, and |nl-random| with the number specified in {int-seed}. Note that the random generator used in newLISP is the C-library function {rand()}. All randomizing functions in newLISP are based on this function. Note that the maximum value for {int-seed} is limited to 16 or 32 bits, depending on the operating system used. Internally, only the 32 least significant bits are passed to the random seed function of the OS. > (seed 12345) (seed (time-of-day)) < After using |nl-seed| with the same number, the random generator starts the same sequence of numbers. This facilitates debugging when randomized data are involved. Using |nl-seed|, the same random sequences can be generated over and over again. The second example is useful for guaranteeing a different seed any time the program starts. *newlisp-function-self* *nl-self* FUNCTION: self~ {syntax:} (self [{int-index} ... ]) The function |nl-self| accesses the target object of a FOOP method. One or more {int-index} are used to access the object members. Objects referenced with |nl-self| are mutable: > (new Class 'Circle) (define (Circle:move dx dy) (inc (self 1) dx) (inc (self 2) dy)) (set 'aCircle (Circle 1 2 3)) (:move aCircle 10 20) aCircle ;→ (Circle 11 22 3) ; objects can be anonymous (set 'circles '((Circle 1 2 3) (Circle 4 5 6))) (:move (circles 0) 10 20) (:move (circles 1) 10 20) circles ;→ ((Circle 11 22 3) (Circle 14 25 6)) < See also the chapter about programming with FOOP: link:#foop[Functional object-oriented programming in newLISP] *newlisp-function-seek* *nl-seek* FUNCTION: seek~ {syntax:} (seek {int-file} [{int-position}]) Sets the file pointer to the new position {int-position} in the file specified by {int-file}.The new position is expressed as an offset from the beginning of the file, {0} (zero) meaning the beginning of the file. If no {int-position} is specified, |nl-seek| returns the current position in the file. If {int-file} is {0} (zero), on BSD, |nl-seek| will return the number of characters printed to STDOUT, and on Linux and Win32, it will return {-1}. On failure, |nl-seek| returns {nil}. When {int-position} is set to {-1}, |nl-seek| sets the file pointer to the end of the file. |nl-seek| can set the file position past the current end of the file. Subsequent writing to this position will extend the file and fill unused positions with zero's. The blocks of zeros are not actually allocated on disk, so the file takes up less space and is called a {sparse file}. > (set 'file (open "myfile" "read")) ;→ 5 (seek file 100) ;→ 100 (seek file) ;→ 100 (open "newlisp_manual.html" "read") (seek file -1) ; seek to EOF ;→ 593816 (set 'fle (open "large-file" "read") (seek file 30000000000) ;→ 30000000000 < newLISP supports file position numbers up to 9,223,372,036,854,775,807. *newlisp-function-select* *nl-select* FUNCTION: select~ |nl-utf8_capable| {syntax:} (select {list} {list-selection}) + {syntax:} (select {list} [{int-index}i_ ... ]) + {syntax:} (select {string} {list-selection}) + {syntax:} (select {string} [{int-index}i_ ... ]) In the first two forms, |nl-select| picks one or more elements from {list} using one or more indices specified in {list-selection} or the {int-index}i_. > (set 'lst '(a b c d e f g)) (select lst '(0 3 2 5 3)) ;→ (a d c f d) (select lst '(-2 -1 0)) ;→ (f g a) (select lst -2 -1 0) ;→ (f g a) < In the second two forms, |nl-select| picks one or more characters from {string} using one or more indices specified in {list-selection} or the {int-index}i_. > (set 'str "abcdefg") (select str '(0 3 2 5 3)) ;→ "adcfd" (select str '(-2 -1 0)) ;→ "fga" (select str -2 -1 0) ;→ "fga" < Selected elements can be repeated and do not have to appear in order, although this speeds up processing. The order in {list-selection} or {int-index}i_ can be changed to rearrange elements. *newlisp-function-semaphore* *nl-semaphore* FUNCTION: semaphore~ {syntax:} (semaphore) + {syntax:} (semaphore {int-id}) + {syntax:} (semaphore {int-id} {int-wait}) + {syntax:} (semaphore {int-id} {int-signal}) + {syntax:} (semaphore {int-id} {0}) A semaphore is an interprocess synchronization object that maintains a count between {0} (zero) and some maximum value. Useful in controlling access to a shared resource, a semaphore is set to signaled when its count is greater than zero and to non-signaled when its count is zero. A semaphore is created using the first syntax. This returns the semaphore ID, an integer used subsequently as {int-id} when the {semaphore} function is called. Initially, the semaphore has a value of zero, which represents the non-signaled state. If calling |nl-semaphore| with a negative value in {int-wait} causes it to be decremented below zero, the function call will block until another process signals the semaphore with a positive value in {int-signal}. Calls to the semaphore with {int-wait} or {int-signal} effectively try to increment or decrement the semaphore value by a positive or negative value specified in {int-signal} or {int-wait}. Because the value of a semaphore must never fall below zero, the function call will block when this is attempted (i.e., a semaphore with a value of zero will block until another process increases the value with a positive {int-signal}). The second syntax is used to inquire about the value of a semaphore by calling |nl-semaphore| with the {int-id} only. This form is not available on Win32. Supplying {0} (zero) as the last argument will release system resources for the semaphore, which then becomes unavailable. Any pending waits on this semaphore in other child processes will be released. On Win32, only parent and child processes can share a semaphore. On Linux/Unix, independent processes can share a semaphore. On failure the |nl-semaphore| function returns {nil}. |nl-sys-error| can be used to retrieve the error number and text from the underlying operating system. The following code examples summarize the different syntax forms: > ;; init semaphores (semaphore) ;; assign a semaphore to sid (set 'sid (semaphore)) ;; inquire the state of a semaphore (not on Win32) (semaphore sid) ;; put sid semaphore in wait state (-1) (semaphore sid -1) ;; run sid semaphore previously put in wait (always 1) (semaphore sid 1) ;; run sid semaphore with X times a skip (backward or forward) on the function (semaphore sid X) ;; release sid semaphore system-wide (always 0) (semaphore sid 0) < The following example shows semaphores controlling a child process: > ;; counter process output in bold (define (counter n) (println "counter started") (dotimes (x n) (semaphore sid -1) (println x))) ;; hit extra to make the prompt come back ;; after output to the console from the counter process > (set 'sid (semaphore)) > (semaphore sid) 0 > (fork (counter 100)) counter started > (semaphore sid 1) 0 > (semaphore sid 3) 1 2 3 > (semaphore sid 2) 4 5 > _ < After the semaphore is acquired in {sid}, it has a value of {0} (the non-signaled state). When starting the process {counter}, the semaphore will block after the initial start message and will wait in the semaphore call. The {-1} is trying to decrement the semaphore, which is not possible because its value is already zero. In the interactive, main parent process, the semaphore is signaled by raising its value by {1}. This unblocks the semaphore call in the {counter} process, which can now decrement the semaphore from {1} to {0} and execute the |nl-print| statement. When the semaphore call is reached again, it will block because the semaphore is already in the wait ({0}) state. Subsequent calls to |nl-semaphore| with numbers greater than {1} give the {counter} process an opportunity to decrement the semaphore several times before blocking. More than one process can participate in controlling the semaphore, just as more than one semaphore can be created. The maximum number of semaphores is controlled by a system-wide kernel setting on Unix-like operating systems. Use the |nl-fork| function to start a new process and the |nl-share| function to share information between processes. For a more comprehensive example of using |nl-semaphore| to synchronize processes, see the file {prodcons.lsp} example in the {examples} directory in the source distribution, as well as the examples and modules distributed with newLISP. *newlisp-function-send* *nl-send* FUNCTION: send~ {syntax:} (send {int-pid} {exp}) + {syntax:} (send) The |nl-send| function enables communication between parent and child processes started with |nl-spawn|. Parent processes can send and receive messages to and from their child processes and child processes can send and receive messages to and from their parent process. A proxy technique – shown further down – is employed to communicate between child process peers. |nl-send| and |nl-receive| do not require locks or semaphores. They work on dual send and receive message queues. Processes started using |nl-fork| or |nl-process| can not use |nl-send| and |nl-receive| message functions. Instead they should use either |nl-share| with |nl-semaphore| or |nl-pipe| to communicate. The |nl-send| function is not available on Win32. In the first syntax |nl-send| is used to send a message from a parent to a child process or a child to a parent process. The second syntax is only used by parent processes to get a list of all child processes ready to accept message from the parent in their receive queues. If a child's receive queue is full, it will not be part of the list returned by the {(send)} statement. The content of a message may be any newLISP expression either atomic or list expressions: boolean constants {nil} and {true}, integers, floating point numbers or strings, or any list expression in valid newLISP syntax. The size of a message is unlimited. The {exp} parameter specifies the data to be sent to the recipient in {int-pid}. The recipient can be either a spawned child process of the current process or the parent process. If a message queue is full, it can be read from the receiving end, but a |nl-send| issued on the other side of the queue will fail and return {nil}. > ; child process dispatching message to parent (set 'ppid (sys-info -4)) ; get parent pid (send ppid "hello") ; send message < The targeted recipient of the message is the parent process: > ; parent process receiving message from child (receive child-pid msg) ;→ true msg ;→ "hello" < When the |nl-send| queue is full, |nl-send| will return {nil} until enough message content is read on the receiving side of the queue and the queue is ready to accept new messages from |nl-send| statements. Using the |nl-until| looping function, the message statements can be repeated until they return a value not {nil}. This way, non-blocking |nl-send| and |nl-receive| can be made blocking until they succeed: > ; blocking sender (until (send pid msg)) ; true after message is queued up ; blocking receiver (until (receive pid msg)) ; true after message could be read < The sender statement blocks until the message could be deposited in the recipients queue. The |nl-receive| statement blocks until a new message can be fetched from the queue. As the |nl-until| statements in this example lack body expressions, the last value of the evaluated conditional expression is the return value of the |nl-until| loop. Blocking message exchange ^^^^^^^^^^^^^^^^^^^^^^^^^ The following code shows how a recipient can listen for incoming messages, and in turn how a sender can retry to deposit a message into a queue. The example shows 5 child processes constantly delivering status data to a parent process which will display the data. After three data sets have been read, the parent will abort all child processes and exit: > #!/usr/bin/newlisp ; child process transmits random numbers (define (child-process) (set 'ppid (sys-info -4)) ; get parent pid (while true (until (send ppid (rand 100)))) ) ; parent starts 5 child processes, listens and displays ; the true flag is specified to enable send/receive (dotimes (i 5) (spawn 'result (child-process) true)) (for (i 1 3) (dolist (cpid (sync)) ; iterate thru pending child PIDs (until (receive cpid msg)) (print "pid:" cpid "->" (format "%-2d " msg))) (println) ) (abort) ; cancel child-processes (exit) < Running above example produces the following output: ------------------------------------------------------------------------- pid:53181->47 pid:53180->61 pid:53179->75 pid:53178->39 pid:53177->3 pid:53181->59 pid:53180->12 pid:53179->20 pid:53178->77 pid:53177->47 pid:53181->6 pid:53180->56 pid:53179->96 pid:53178->78 pid:53177->18 ------------------------------------------------------------------------- The {(sync)} expression returns a list of all child PIDs, and {(until (receive cpid msg))} is used to force a wait until status messages are recived for each of the child processes. A timeout mechanism could be part of an |nl-until| or |nl-while| loop to stop waiting after certain time has expired. The examples show messages flowing from a child processes to a parent process, in the same fashion messages could flow into the other direction from parent to child processes. In that case the parent process would use {(send)} to obtain a list of child processes with place in their message queues. Messages containing code for evaluation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The most powerful feature of the message functions is the ability to send any newLISP expression, which then can be evaluated by the recipient. The recipient uses |nl-eval| to evaluate the received expression. Symbols contained in the expression are evaluated in the receivers environment. The following example shows how a parent process acts like a message proxy. The parent receives messages from a child process A and routes them to a second child process with ID B. In effect this implements messages between child process peers. The implementation relies on the fact that the recipient can evaluate expressions contained in messages received. These expressions can be any valid newLISP statements: > #!/usr/bin/newlisp ; sender child process of the message (set 'A (spawn 'result (begin (dotimes (i 3) (set 'ppid (sys-info -4)) /* the statement in msg will be evaluated in the proxy */ (set 'msg '(until (send B (string "greetings from " A)))) (until (send ppid msg))) (until (send ppid '(begin (sleep 100) ; make sure all else is printed (println "parent exiting ...\n") (set 'finished true))))) true)) ; receiver child process of the message (set 'B (spawn 'result (begin (set 'ppid (sys-info -4)) (while true (until (receive ppid msg)) (println msg) (unless (= msg (string "greetings from " A)) (println "ERROR in proxy message: " msg)))) true)) (until finished (if (receive A msg) (eval msg))) ; proxy loop (abort) (exit) < Child process {A} sends three messages to {B}. As this cannot be done directly {A} sends |nl-send| statements to the parent for evaluation. The statement: > (until (send pidB (string "greetings from " A))) < will be evaluated in the environment of the parent process. Even so the variables {A} and {B} are bound to {nil} in the sender process {A}, in the parent process they will be bound to the correct process ID numbers. After sending the three messages, the statement: > (set 'finished true) < is sent to the parent process. Once evaluated, it will cause the |nl-until| loop to finish. For more details on |nl-send| and |nl-receive| and more examples see the http://www.newlisp.org/CodePatterns.html[Code Patterns] document. *newlisp-function-sequence* *nl-sequence* FUNCTION: sequence~ {syntax:} (sequence {num-start} {num-end} [{num-step}]) Generates a sequence of numbers from {num-start} to {num-end} with an optional step size of {num-step}. When {num-step} is omitted, the value {1} (one) is assumed. The generated numbers are of type integer (when no optional step size is specified) or floating point (when the optional step size is present). > (sequence 10 5) ;→ (10 9 8 7 6 5) (sequence 0 1 0.2) ;→ (0 0.2 0.4 0.6 0.8 1) (sequence 2 0 0.3) ;→ (2 1.7 1.4 1.1 0.8 0.5 0.2) < Note that the step size must be a positive number, even if sequencing from a higher to a lower number. Use the |nl-series| function to generate geometric sequences. *newlisp-function-series* *nl-series* FUNCTION: series~ {syntax:} (series {num-start} {num-factor} {num-count}) + {syntax:} (series {exp-start} {func} {num-count}) In the first syntax, |nl-series| creates a geometric sequence with {num-count} elements starting with the element in {num-start}. Each subsequent element is multiplied by {num-factor}. The generated numbers are always floating point numbers. When {num-count} is less than {1}, then |nl-series| returns an empty list. > (series 2 2 5) ;→ (2 4 8 16 32) (series 1 1.2 6) ;→ (1 1.2 1.44 1.728 2.0736 2.48832) (series 10 0.9 4) ;→ (10 9 8.1 7.29) (series 0 0 10) ;→ (0 0 0 0 0 0 0 0 0 0) (series 99 1 5) ;→ (99 99 99 99 99) < In the second syntax, |nl-series| uses a function specified in {func} to transform the previous expression in to the next expression: > ; embed the function Phi: f(x) = 1 / (1 + x) ; see also http://en.wikipedia.org/wiki/Golden_ratio (series 1 (fn (x) (div (add 1 x))) 20) ;→ (1 0.5 0.6666666 0.6 0.625 0.6153846 0.619047 0.6176470 0.6181818 0.6179775 0.6180555 0.6180257 0.6180371 0.6180327 0.6180344 0.6180338 0.6180340 0.6180339 0.6180339 0.6180339) ; pre-define the function (define (oscillate x) (if (< x) (+ (- x) 1) (- (+ x 1))) ) (series 1 oscillate 20) ;→ (1 -2 3 -4 5 -6 7 -8 9 -10 11 -12 13 -14 15 -16 17 -18 19 -20) ; any data type is accepted as a start expression (series "a" (fn (c) (char (inc (char c)))) 5) ;→ ("a" "b" "c" "d" "e") ; dependency of the two previous values in this fibonacci generator (let (x 1) (series x (fn (y) (+ x (swap y x))) 10)) ;→ (1 2 3 5 8 13 21 34 55 89) < The first example shows a series converging to the {golden ratio, φ} (for any starting value). The second example shows how {func} can be defined previously for better readability of the |nl-series| statement. The |nl-series| function also updates the internal list {$idx} index value, which can be used inside {func}. Use the |nl-sequence| function to generate arithmetic sequences. *newlisp-function-set* *nl-set* FUNCTION: set~ |nl-destructive| {syntax:} (set {sym-1} {exp-1} [{sym-2} {exp-2} ... ]) Evaluates both arguments and then assigns the result of {exp} to the symbol found in {sym}. The |nl-set| expression returns the result of the assignment. The assignment is performed by copying the contents of the right side into the symbol. The old contents of the symbol are deleted. An error message results when trying to change the contents of the symbols {nil}, {true}, or a context symbol. |nl-set| can take multiple argument pairs. > (set 'x 123) ;→ 123 (set 'x 'y) ;→ y (set x "hello") ;→ "hello" y ;→ "hello" (set 'alist '(1 2 3)) ;→ (1 2 3) (set 'x 1 'y "hello") ;→ "hello" ; multiple arguments x ;→ 1 y ;→ "hello" < The symbol for assignment could be the result from another newLISP expression: > (set 'lst '(x y z)) ;→ (x y z) (set (first lst) 123) ;→ 123 x ;→ 123 < Symbols can be set to lambda or lambda-macro expressions. This operation is equivalent to using |nl-define| or |nl-define-macro|. > (set 'double (lambda (x) (+ x x))) ;→ (lambda (x) (+ x x)) < is equivalent to: > (define (double x) (+ x x)) ;→ (lambda (x) (+ x x)) < is equivalent to: > (define double (lambda (x) (+ x x))) ;→ (lambda (x) (+ x x)) < Use the |nl-constant| function (which works like |nl-set|) to protect the symbol from subsequent alteration. Using the |nl-setq| or |nl-setf| function eliminates the need to quote the variable symbol. *newlisp-function-set-locale* *nl-set-locale* FUNCTION: set-locale~ {syntax:} (set-locale [{str-locale} [{int-category}]]) Reports or switches to a different locale on your operating system or platform. When used without arguments, {set-locale} reports the current locale being used. When {str-locale} is specified, {set-locale} switches to the locale with all category options turned on ({LC_ALL}). Placing an empty string in {str-locale} switches to the default locale used on the current platform. |nl-set-locale| returns either the current locale string and decimal point string in a list or {nil} if the requested change could not be performed. > ; report current locale (set-locale) ; set default locale of your platform and country ; return value shown when executing on German MS-Windows (set-locale "") ;→ ("German_Germany.1252" ",") (add 1,234 1,234) ;→ 2,468 < By default, newLISP – if not enabled for UTF-8 – starts up with the POSIX C default locale. This guarantees that newLISP's behavior will be identical on any platform locale. On UTF-8 enabled versions of newLISP the locale of the current platform is chosen. > ; after non-UTF-8 newLISP start up (set-locale) ;→ ("C" ".") < In {int-category}, integer numbers may be specified as _category options_ for fine-tuning certain aspects of the locale, such as number display, date display, and so forth. The numbers used vary from system-to-system. The options valid on your platform can be found in the C include file {locale.h}. This file defines constants like {LC{ALL, LC}NUMERIC,} and {LC_MONETARY}. When |nl-set-locale| is used without the option number, it assumes the {LC_ALL} option, which turns on all options for that locale. Note that the locale also controls the decimal separator in numbers. The default C locale uses the decimal dot, but most others use a decimal comma. Note that using |nl-set-locale| does not change the behavior of regular expressions in newLISP. To localize the behavior of PCRE (Perl Compatible Regular Expressions), newLISP must be compiled with different character tables. See the file, LOCALIZATION, in the newLISP source distribution for details. See also the chapter |nl-Switching the locale|. *newlisp-function-set-ref* *nl-set-ref* FUNCTION: set-ref~ |nl-destructive| {syntax:} (set-ref {exp-key} {list} {exp-replacement} [{func-compare}]) Searches for {exp-key} in {list} and replaces the found element with {exp-replacement}. The {list} can be nested. The system variables {$it} contains the expression found and can be used in {exp-replacement}. The function returns the new modified {list}. > (set 'data '(fruits (apples 123 44) (oranges 1 5 3))) (set-ref 'apples data 'Apples) ;→ (fruits (Apples 123 44) (oranges 1 5 3)) data ;→ (fruits (Apples 123 44) (oranges 1 5 3))) < {data} could be the context identifier of a default function for passing lists by reference: > (set 'db:db '(fruits (apples 123 44) (oranges 1 5 3))) (define (update ct key value) (set-ref key ct value)) (update db 'apples 'Apples) ;→ (fruits (Apples 123 44) (oranges 1 5 3)) (update db 'oranges 'Oranges) ;→ (fruits (Apples 123 44) (Oranges 1 5 3)) db:db ;→ (fruits (Apples 123 44) (Oranges 1 5 3)) < For examples on how to use {func-compare} see |nl-set-ref-all| For changing all occurrences of an element in a list use |nl-set-ref-all|. *newlisp-function-set-ref-all* *nl-set-ref-all* FUNCTION: set-ref-all~ |nl-destructive| {syntax:} (set-ref-all {exp-key} {list} {exp-replacement} [{func-compare}]) Searches for {exp-key} in {list} and replaces each instance of the found element with {exp-replacement}. The {list} can be nested. The system variable {$it} contains the expression found and can be used in {exp-replacement}. The function returns the new modified {list}. > (set 'data '((monday (apples 20 30) (oranges 2 4 9)) (tuesday (apples 5) (oranges 32 1)))) (set-ref-all 'apples data "Apples") ;→ ((monday ("Apples" 20 30) (oranges 2 4 9)) (tuesday ("Apples" 5) (oranges 32 1))) < Using the default functor in the {(list key)} pattern allows the list to be passed by reference to a user-defined function containing a |nl-set-ref-all| statement. This would result in less memory usage and higher speeds in when doing replacements in large lists: > (set 'db:db '((monday (apples 20 30) (oranges 2 4 9)) (tuesday (apples 5) (oranges 32 1)))) (define (foo ctx) (set-ref-all 'apples ctx "Apples") ) (foo db) ;→ ((monday ("Apples" 20 30) (oranges 2 4 9)) (tuesday ("Apples" 5) (oranges 32 1))) < When evaluating {(foo db)}, the list in {db:db} will be passed by reference and |nl-set-ref-all| will make the changes on the original, not on a copy of {db:db}. Like with |nl-find|, |nl-replace|, |nl-ref| and |nl-ref-all|, complex searches can be expressed using |nl-match| or |nl-unify| in {func-compare}: > (set 'data '((monday (apples 20 30) (oranges 2 4 9)) (tuesday (apples 5) (oranges 32 1)))) (set-ref-all '(oranges *) data (list (first $it) (apply + (rest $it))) match) ;→ ( ... (oranges 15) ... (oranges 33) ... ) < The example sums all numbers found in records starting with the symbol {oranges}. The found items appear in {$it} See also |nl-set-ref| which replaces only the first element found. *newlisp-function-setq* *nl-setq* *newlisp-function-setf* *nl-setf* FUNCTION: setq, setf~ |nl-destructive| {syntax:} (setq {place-1} {exp-1} [{place-2} {exp-2} ... ]) |nl-setq| and {setf} work alike in newLISP and set the contents of a symbol, list, array or string or of a list, array or string place reference. Like |nl-set|, |nl-setq| and {setf} can take multiple argument pairs. Although both |nl-setq| and {setf} point to the same built-in function internally, throughout this manual |nl-setq| is used when setting a symbol reference and {setf} is used when setting list or array references. > (setq x 123) ;→ 123 ; multiple arguments (setq x 1 y 2 z 3) ;→ 3 x ;→ 1 y ;→ 2 z ;→ 3 ; with nth or implicit indices (setq L '(a b (c d) e f g)) (setf (L 1) 'B) ;→ B ; or the same (setf (nth 1 L) 'B) L ;→ (a B (c d) e f g) (setf (L 2 0) 'C) ;→ C L ;→ (a B (C d) e f g) (setf (L 2) 'X) L ;→ (A B X e f g) ; with assoc (setq L '((a 1) (b 2))) (setf (assoc 'b L) '(b 3)) ;→ (b 3) L ;→ ((a 1) (b 3)) ; with lookup (setf (lookup 'b L) 30) ;→ 30 L ;→ ((a 1) (b 30)) ; several list accessors can be nested (setq L '((a 1) (b 2))) (push 'b (setf (assoc 'b l) '(b 4))) 'b) ;→ b L ;→((a 1) (b b 4))) ; on strings (set 's "NewISP") (setf (s 0) "n") ;→ "n" s ;→ "newISP" (setf (s 3) "LI") ;→ "LI" s ;→ "newLISP" < Often the new value set is dependent on the old value. {setf} can use the anaphoric system variable {$it} to refer to the old value inside the {setf} expression: > (setq L '((apples 4) (oranges 1))) (setf (L 1 1) (+ $it 1)) ;→ 2 L ;→ ((apples 4) (oranges 2)) (set 's "NewLISP") (setf (s 0) (lower-case $it)) ;→ "n") s ;→ "newLISP" < *newlisp-function-sgn* *nl-sgn* FUNCTION: sgn~ {syntax:} (sgn {num}) + {syntax:} (sgn {num} {exp-1} [{exp-2} [{exp-3}]]) In the first syntax, the |nl-sgn| function is a logical function that extracts the sign of a real number according to the following rules: *_x > {0} : sgn(x) = 1 + x < {0} : sgn(x) = -1 + x = {0} : sgn(x) = {0}_* > (sgn -3.5) ;→ -1 (sgn 0) ;→ 0 (sgn 123) ;→ 1 < In the second syntax, the result of evaluating one of the optional expressions {exp-1}, {exp-2}, or {exp-3} is returned, instead of {-1}, {0}, or {1}. If {exp-n} is missing for the case triggered, then {nil} is returned. > (sgn x -1 0 1) ; works like (sgn x) (sgn x -1 1 1) ; -1 for negative x all others 1 (sgn x nil true true) ; nil for negative else true (sgn x (abs x) 0) ; (abs x) for x < 0, 0 for x = 0, else nil < Any expression or constant can be used for {exp-1}, {exp-2}, or {exp-3}. *newlisp-function-share* *nl-share* FUNCTION: share~ {syntax:} (share) + {syntax:} (share {int-address-or-handle}) + {syntax:} (share {int-address-or-handle} {exp-value}) + {syntax:} (share {nil} {int-address}) Accesses shared memory for communicating between several newLISP processes. When called without arguments, |nl-share| requests a page of shared memory from the operating system. This returns a memory address on Linux/Unix and a handle on Win32, which can then be assigned to a variable for later reference. This function is not available on OS/2. To set the contents of shared memory, use the third syntax of |nl-share|. Supply a shared memory address on Linux/Unix or a handle on Win32 in {int-address-or-handle}, along with an integer, float, string expression or any other expression (since v.10.1.0) supplied in {exp-value}. Using this syntax, the value supplied in {exp-value} is also the return value. To access the contents of shared memory, use the second syntax of |nl-share|, supplying only the shared memory address or handle. The return value will be any constant or expression (since v.10.1.0) written previously into the memory. If the memory has not been previously set to a value, {nil} will be returned. Only available on Unix-like operating systems, the last syntax unmaps a shared memory address. Note that using a shared address after unmapping it will crash the system. Memory can be shared between parent and child processes, but not between independent processes. Since v.10.1.0 size of share objects can exceed the shared memory pagesize of the operating system. For objects bigger than the pagesize, newLISP internally uses files for sharing. This requires a {/tmp} directory on Unix-like operating system and a {temp} directory in the root of the current disk drive on Win32 systems. On Unix-like systems this directory is present, on Win32 it may have to be created. > (set 'mem (share)) (share mem 123) ;→ 123 (share mem) ;→ 123 (share mem "hello world") ;→ "hello world" (share mem) ;→ "hello world" (share mem true) ;→ true (share mem) ;→ true (share mem '(+ 1 2 3 4)) ;→ (+ 1 2 3 4) (share mem) ;→ (+ 1 2 3 4) ; expressions received can be evaluated (since v.10.1.0) (eval (share mem)) ;→ 10 (share nil mem) ;→ true ; unmap only on Unix < Expression read from shared memory and evaluated, will be evaluated in the recipient's process environment. Note that shared memory access between different processes should be synchronized using a |nl-semaphore|. Simultaneous access to shared memory can crash the running process. For a more comprehensive example of using shared memory in a multi process Linux/Unix application, see the file {example/prodcons.lsp} in the newLISP source distribution. *newlisp-function-signal* *nl-signal* FUNCTION: signal~ {syntax:} (signal {int-signal} {sym-event-handler} | {func-event-handler}) + {syntax:} (signal {int-signal} "ignore" | "default" | "reset") + {syntax:} (signal {int-signal}) Sets a user-defined handler in {sym-event-handler} for a signal specified in {int-signal} or sets to a function expression in {func-event-handler}. A parameter following {int-signal} is not evaluated. If no signal handler is speified any of the string constants {"ignore"}, {"default"} or {"reset"} can be specified in either lower or upper case or simply using the the first letter of the option string. When signal setup with any of these three options has been successfull {true} is returned. Using {"ignore"} will make newLISP ignore the signal. Using {"default"} will set the handler to the default handler of the underlying platform OS. The {"reset"} option will restore the handler to newLISP startup state. On startup, newLISP either specifies an empty newLISP handler or a Ctrl-C handler for {SIGINT} and a {waitpipd(-1, 0, WNOHANG)} C-call for {SIGCHLD}. Different signals are available on different OS platforms and Linux/Unix flavors. The numbers to specify in {int-signal} also differ from platform-to-platform. Valid values can normally be extracted from a file found in {/usr/include/sys/signal.h} or {/usr/include/signal.h}. Some signals make newLISP exit even after a user-defined handler has been specified and executed (e.g., signal SIGKILL). This behavior may also be different on different platforms. > (constant 'SIGINT 2) (define (ctrlC-handler) (println "ctrl-C has been pressed")) (signal SIGINT 'ctrlC-handler) ; now press ctrl-C ; the following line will appear ; this will only work in an interactive terminal window ; and will not work in the newLISP-GS editor ctrl-C has been pressed ; reset tratment of signal 2 to startup conditions (signal SIGINT "reset") < On Win32, the above example would execute the handler before exiting newLISP. On most Linux/Unix systems, newLISP would stay loaded and the prompt would appear after hitting the [enter] key. Instead of specifying a symbol containing the signal handler, a function can be specified directly. The signal number is passed as a parameter: > (signal SIGINT exit) ;→ $signal-2 (signal SIGINT (fn (s) (println "signal " s " occurred"))) < Note that the signal SIGKILL (9 on most platforms) will always terminate the application regardless of an existing signal handler. The signal could have been sent from another shell on the same computer: > kill -s SIGINT 2035 < In this example, {2035} is the process ID of the running newLISP. The signal could also have been sent from another newLISP application using the function |nl-destroy|: > (destroy 2035) ;→ true < If newLISP receives a signal while evaluating another function, it will still accept the signal and the handler function will be executed: > (constant 'SIGINT 2) (define (ctrlC-handler) (println "ctrl-C has been pressed")) (signal SIGINT 'ctrlC-handler) ;; or (signal SIGINT ctrlC-handler) (while true (sleep 300) (println "busy")) ;; generates following output busy busy busy ctrl-C has been pressed busy busy … < Specifying only a signal number will return either the name of the currently defined handler function or {nil}. The user-defined signal handler can pass the signal number as a parameter. > (define (signal-handler sig) (println "received signal: " sig)) ;; set all signals from 1 to 8 to the same handler (for (s 1 8) (signal s 'signal-handler)) < In this example, all signals from 1 to 8 are set to the same handler. *newlisp-function-silent* *nl-silent* FUNCTION: silent~ {syntax:} (silent [{exp-1} [{exp-2} ... ]]) Evaluates one or more expressions in {exp-1}—. |nl-silent| is similar to |nl-begin|, but it suppresses console output of the return value and the following prompt. It is often used when communicating from a remote application with newLISP (e.g., GUI front-ends or other applications controlling newLISP), and the return value is of no interest. Silent mode is reset when returning to a prompt. This way, it can also be used without arguments in a batch of expressions. When in interactive mode, hit [enter] twice after a statement using |nl-silent| to get the prompt back. > (silent (my-func)) ; same as next (silent) (my-func) ; same effect as previous < *newlisp-function-sin* *nl-sin* FUNCTION: sin~ {syntax:} (sin {num-radians}) Calculates the sine function from {num-radians} and returns the result. > (sin 1) ;→ 0.8414709838 (set 'pi (mul 2 (acos 0))) ;→ 3.141592654 (sin (div pi 2)) ;→ 1 < *newlisp-function-sinh* *nl-sinh* FUNCTION: sinh~ {syntax:} (sinh {num-radians}) Calculates the hyperbolic sine of {num-radians}. The hyperbolic sine is defined mathematically as: {(exp (x) - exp (-x)) / 2}. An overflow to {inf} may occur if {num-radians} is too large. > (sinh 1) ;→ 1.175201194 (sinh 10) ;→ 11013.23287 (sinh 1000) ;→ inf (sub (tanh 1) (div (sinh 1) (cosh 1))) ;→ 0 < *newlisp-function-sleep* *nl-sleep* FUNCTION: sleep~ {syntax:} (sleep {num-milliseconds}) Gives up CPU time to other processes for the amount of milliseconds specified in {num-milli-seconds}. > (sleep 1000) ; sleeps 1 second (sleep 0.5) ; sleeps 500 micro seconds < On some platforms, |nl-sleep| is only available with a resolution of one second. In this case, the parameter {int-milli-seconds} will be rounded to the nearest full second. *newlisp-function-slice* *nl-slice* FUNCTION: slice~ {syntax:} (slice {list} {int-index} [{int-length}]) + {syntax:} (slice {array} {int-index} [{int-length}]) + {syntax:} (slice {str} {int-index} [{int-length}]) In the first form, |nl-slice| copies a sublist from a {list}. The original list is left unchanged. The sublist extracted starts at index {int-index} and has a length of {int-length}. If {int-length} is negative, |nl-slice| will take the parameter as offset counting from the end and copy up to that offset. If the parameter is omitted, |nl-slice| copies all of the elements to the end of the list. See also |nl-Indexing elements of strings and lists|. > (slice '(a b c d e f) 3 2) ;→ (d e) (slice '(a b c d e f) 2 -2) ;→ (c d) (slice '(a b c d e f) 2) ;→ (c d e f) (slice '(a b c d e f) -4 3) ;→ (c d e) (set 'A (array 3 2 (sequence 1 6))) ;→ ((1 2) (3 4) (5 6)) (slice A 1 2) ;→ ((3 4) (5 6)) < In the second form, a part of the string in {str} is extracted. {int-index} contains the start index and {int-length} contains the length of the substring. If {int-length} is not specified, everything to the end of the string is extracted. |nl-slice| also works on string buffers containing binary data like {0}'s (zeroes). It operates on byte boundaries rather than character boundaries. See also |nl-Indexing elements of strings and lists|. Note that |nl-slice| always works on single 8-bit byte boundaries for offset and length numbers, even when running the UTF-8 enabled version of newLISP. > (slice "Hello World" 6 2) ;→ "Wo" (slice "Hello World" 0 5) ;→ "Hello" (slice "Hello World" 6) ;→ "World" (slice "newLISP" -4 2) ;→ "LI" < Note that an {implicit slice} is available for lists. See the chapter |nl-Implicit rest and slice|. Be aware that |nl-slice| always works on byte boundaries rather than character boundaries in the UTF-8–enabled version of newLISP. As a result, |nl-slice| can be used to manipulate binary content. *newlisp-function-sort* *nl-sort* FUNCTION: sort~ |nl-destructive| {syntax:} (sort {list} [{func-compare}]) All members in {list} are sorted in ascending order. Anything may be sorted, regardless of the types. When members are themselves lists, each list element is recursively compared. If two expressions of different types are compared, the lower type is sorted before the higher type in the following order: > Atoms: nil, true, integer or float, string, symbol, primitive Lists: quoted expression, list, lambda, lambda-macro < The sort is destructive, changing the order of the elements in the original list. The return value of |nl-sort| is a copy of the sorted list. An optional comparison operator, user-defined function, or anonymous function can be supplied. The functor or operator can be given with or without a preceding quote. > (sort '(v f r t h n m j)) ;→ (f h j m n r t v) (sort '((3 4) (2 1) (1 10))) ;→ ((1 10) (2 1) (3 4)) (sort '((3 4) "hi" 2.8 8 b)) ;→ (2.8 8 "hi" b (3 4)) (set 's '(k a l s)) (sort s) ;→ (a k l s) (sort '(v f r t h n m j) >) ;→ (v t r n m j h f) (sort s <) ;→ (a k l s) (sort s >) ;→ (s l k a) s ;→ (s l k a) ;; define a comparison function (define (comp x y) (> (last x) (last y))) (set 'db '((a 3) (g 2) (c 5))) (sort db comp) ;→ ((c 5) (a 3) (g 2)) ;; use an anonymous function (sort db (fn (x y) (> (last x) (last y)))) < *newlisp-function-source* *nl-source* FUNCTION: source~ {syntax:} (source) + {syntax:} (source {sym-1} [{sym-2} ... ]) Works almost identically to |nl-save|, except symbols and contexts get serialized to a string instead of being written to a file. Multiple variable symbols, definitions, and contexts can be specified. If no argument is given, |nl-source| serializes the entire newLISP workspace. When context symbols are serialized, any symbols contained within that context will be serialized, as well. Symbols containing {nil} are not serialized. System symbols beginning with the |nl-$| (dollar sign) character are only serialized when mentioned explicitly. Symbols not belonging to the current context are written out with their context prefix. > (define (double x) (+ x x)) (source 'double) ;→ "(define (double x)\n (+ x x))\n\n" < As with |nl-save|, the formatting of line breaks and leading spaces or tabs can be controlled using the |nl-pretty-print| function. *newlisp-function-spawn* *nl-spawn* FUNCTION: spawn~ {syntax:} (spawn {sym} {exp} [true]) Launches the evaluation of {exp} as a child process and immediately returns. The symbol in {sym} is quoted and receives the result of the evaluation when the function |nl-sync| is executed. |nl-spawn| is used to start parallel evaluation of expressions in concurrent processes. If newLISP is running on a multi-core CPU, the underlying operating system will distribute spawned processes onto different cores, thereby evaluating expressions in parallel and speeding up overall processing. The optional {true} parameter must be set if |nl-send| or |nl-receive| is used to communicated with the child process spawned. The function |nl-spawn| is not available on Win32. After successfully starting a child process, the |nl-spawn| expression returns the process id of the forked process. The following examples shows how the calculation of a range of prime numbers can be split up in four sub ranges to speed up the calculation of the whole range: > ; calculate primes in a range (define (primes from to) (local (plist) (for (i from to) (if (= 1 (length (factor i))) (push i plist -1))) plist)) ; start child processes (set 'start (time-of-day)) (spawn 'p1 (primes 1 1000000)) (spawn 'p2 (primes 1000001 2000000)) (spawn 'p3 (primes 2000001 3000000)) (spawn 'p4 (primes 3000001 4000000)) ; wait for a maximum of 60 seconds for all tasks to finish (sync 60000) ; returns true if all finished in time ; p1, p2, p3 and p4 now each contain a lists of primes (println "time spawn: " (- (time-of-day) start)) (println "time simple: " (time (primes 1 4000000))) (exit) < On a 1.83 Intel Core 2 Duo processor, the above example will finish after about 13 seconds. Calculating all primes using {(primes 1 4000000)} would take about 20 seconds. The |nl-sync| function will wait for all child processes to finish and receive the evaluation results in the symbols {p1} to {p4}. When all results are collected, |nl-sync| will stop waiting and return {true}. When the time specified was insufficient , |nl-sync| will return {nil} and another |nl-sync| statement could be given to further wait and collect results. A short timeout time can be used to do other processing during waiting: > (spawn 'p1 (primes 1 1000000)) (spawn 'p2 (primes 1000001 2000000)) (spawn 'p3 (primes 2000001 3000000)) (spawn 'p4 (primes 3000001 4000000)) ; print a dot after each 2 seconds of waiting (until (sync 2000) (println ".")) < |nl-sync| when used without any parameters, will not wait but immediately return a list of pending child processes. For the {primes} example, the following |nl-sync| expression could be used to watch the progress: > (spawn 'p1 (primes 1 1000000)) (spawn 'p2 (primes 1000001 2000000)) (spawn 'p3 (primes 2000001 3000000)) (spawn 'p4 (primes 3000001 4000000)) ; show a list of pending process ids after each three-tenths of a second (until (sync 300) (println (sync))) < A parameter of {-1} tells |nl-sync| to wait for a very long time (~ 1193 hours). A better solution would be to wait for a maximum time, then |nl-abort| all pending child processes: > (spawn 'p1 (primes 1 1000000)) (spawn 'p2 (primes 1000001 2000000)) (spawn 'p3 (primes 2000001 3000000)) (spawn 'p4 (primes 3000001 4000000)) ; wait for one minute, then abort and ; report unfinished PIDs (if (not (sync 60000)) (begin (println "aborting unfinished: " (sync)) (abort)) (println "all finished successfully") ) < The three functions |nl-spawn|, |nl-sync| and |nl-abort| are part of the http://supertech.csail.mit.edu/cilk/[Cilk] API. The original implementation also does sophisticated scheduling and allocation of threaded tasks to multiple CPU cores. The newLISP implementation of the Cilk API lets the operating system of the underlying platform handle process management. Internally, the API is implemented using the Unix libc functions {fork()}, {waitpid()} and {kill()}. Intercommunications between processes and child processes is done using the |nl-send| and |nl-receive| functions. |nl-spawn| can be called recursively from spawned subtasks: > (define (fibo n) (local (f1 f2) (if(< n 2) 1 (begin (spawn 'f1 (fibo (- n 1))) (spawn 'f2 (fibo (- n 2))) (sync 10000) (+ f1 f2))))) (fibo 7) ;→ 21 < With {(fibo 7)} 41 processes will be generated. Although the above code shows the working of the Cilk API in a recursive application, it would not be practical, as the overhead required to spawn subtasks is much higher than the time saved through parallelization. Since version 10.1 a |nl-send| and |nl-receive| message functions are available for communications between parent and child processes. Using these functions any data or expression of any size can be transferred. Additionally messaged expressions can be evaluated in the recipient's environment. *newlisp-function-sqrt* *nl-sqrt* FUNCTION: sqrt~ {syntax:} (sqrt {num}) Calculates the square root from the expression in {num} and returns the result. > (sqrt 10) ;→ 3.16227766 (sqrt 25) ;→ 5 < *newlisp-function-starts-with* *nl-starts-with* FUNCTION: starts-with~ {syntax:} (starts-with {str} {str-key} [{num-option}]) + {syntax:} (starts-with {list} [{exp}]) In the first version, |nl-starts-with| checks if the string {str} starts with a key string in {str-key} and returns {true} or {nil} depending on the outcome. If a regular expression number is specified in {num-option}, {str-key} contains a regular expression pattern. See |nl-regex| for valid {option} numbers. > (starts-with "this is useful" "this") ;→ true (starts-with "this is useful" "THIS") ;→ nil ;; use regular expressions (starts-with "this is useful" "THIS" 1) ;→ true (starts-with "this is useful" "this|that" 0) ;→ true < In the second version, |nl-starts-with| checks to see if a list starts with the list element in {exp}. {true} or {nil} is returned depending on outcome. > (starts-with '(1 2 3 4 5) 1) ;→ true (starts-with '(a b c d e) 'b) ;→ nil (starts-with '((+ 3 4) b c d) '(+ 3 4)) ;→ true < See also the |nl-ends-with| function. *newlisp-function-stats* *nl-stats* FUNCTION: stats~ {syntax:} (stats {list-vector}) The functions calculates statistical values of central tendency and dsitribution moments of values in {list-vector}. The following values are returned by |nl-stats| in a list: [cols="1<,4<",width="30%",options="header",] |============================================== |name |description |N |Number of values |mean |Mean of values |avdev |Average deviation from mean value |sdev |Standard deviation (population estimate) |var |Variance (population estimate) |skew |Skew of distribution |kurt |Kurtosis of distribution |============================================== > (set 'data '(90 100 130 150 180 200 220 300 350 400)) (println (format [text] N = %5d mean = %8.2f avdev = %8.2f sdev = %8.2f var = %8.2f skew = %8.2f kurt = %8.2f [/text] (stats data))) ; outputs the following N = 10 mean = 212.00 avdev = 84.40 sdev = 106.12 var = 11262.22 skew = 0.49 kurtosis = -1.34 < *newlisp-function-string* *nl-string* FUNCTION: string~ {syntax:} (string {exp-1} [{exp-2} ... ]) Translates into a string anything that results from evaluating {exp-1}—. If more than one expression is specified, the resulting strings are concatenated. > (string 'hello) ;→ "hello" (string 1234) ;→ "1234" (string '(+ 3 4)) ;→ "(+ 3 4)" (string (+ 3 4) 8) ;→ "78" (string 'hello " " 123) ;→ "hello 123" < If a buffer passed to |nl-string| contains {\000}, only the string up to the first terminating zero will be copied: > (set 'buff "ABC\000\000\000") ;→ "ABC\000\000\000" (length buff) ;→ 6 (string buff) ;→ "ABC" (length (string buff)) ;→ 3 < Use the |nl-append| and |nl-join| (allows the joining string to be specified) functions to concatenate strings containing zero bytes. Use the |nl-source| function to convert a lambda expression into its newLISP source string representation. *newlisp-function-string?* *nl-string?* FUNCTION: string?~ {syntax:} (string? {exp}) Evaluates {exp} and tests to see if it is a string. Returns {true} or {nil} depending on the result. > (set 'var "hello") (string? var) ;→ true < *newlisp-function-struct* *nl-struct* FUNCTION: struct~ {syntax:} (struct {symbol} [{str-data-type} ... ]) The |nl-struct| function can be used to define aggregate data types for usage with the extended syntax of |nl-import|, |nl-pack| and |nl-unpack|. This allows importing functions which take C-language {struct} data types or pointers to these aggregate data types. The following example illustrates the usage of |nl-struct| together with the C data functions {localtime} and {asctime}. The {localtime} functions works similar to the built-in |nl-now| function. The {asctime} function takes the numerical data output by {localtime} and formats these to readable text. > /* The C function prototypes for the functions to import */ struct tm * localtime(const time_t *clock); char * asctime(const struct tm *timeptr); /* the tm struct aggregating different time related values */ struct tm { int tm_sec; /* seconds after the minute [0-60] */ int tm_min; /* minutes after the hour [0-59] */ int tm_hour; /* hours since midnight [0-23] */ int tm_mday; /* day of the month [1-31] */ int tm_mon; /* months since January [0-11] */ int tm_year; /* years since 1900 */ int tm_wday; /* days since Sunday [0-6] */ int tm_yday; /* days since January 1 [0-365] */ int tm_isdst; /* Daylight Savings Time flag */ long tm_gmtoff; /* offset from CUT in seconds */ /*** not on Windows ***/ char *tm_zone; /* timezone abbreviation */ /*** not on Windows ***/ }; < Function import and definition of the structure data type in newLISP: > ;; for pointers to structs always use void* ;; as a library use msvcrt.dll on Windows or libc.so on Unix. ;; The tm struct type is configured for Mac OSX and Linux. ;; On other OS the tm structure may be different (import "libc.dylib" "asctime" "char*" "void*") (import "libc.dylib" "localtime" "void*" "void*") ; definition of the struct (struct 'tm "int" "int" "int" "int" "int" "int" "int" "int" "int" "long" "char*") ;; use import and struct ; todays date number (seconds after 1970 also called Unix epoch time) (set 'today (date-value)) ;→ 1324134913 ;; the time value is passed by it's address ;; localtime retirns a pointer to a tm struct (set 'ptr (localtime (address today))) ;→ 2896219696 ; unpack the the tm struct (7:15:13 on the 17th etc.) (unpack tm ptr) ;→ (13 15 7 17 11 111 6 350 0 -28800 "PST") ; transform to readable form (asctime ptr) ;→ "Sat Dec 17 07:15:13 2011\n" ; all in one statement does actually not use struct, pointers are passed directly (asctime (localtime (address today))) ;→ "Sat Dec 17 07:15:13 2011" ; same as the built-in date function (date today) ;→ "Sat Dec 17 07:15:13 2011" < Care must be taken to pass valid addresses to pointer parameters in imported functions or when passing address pointers to |nl-unpack|. Invalid address pointers can crash newLISP or make it unstable. |nl-struct| defininitions can be nested: > ; the pair aggregate type (struct 'pair "char" "char") ;→ pair ; nested struct type (struct 'comp "pair" "int") ;→ comp ; pack data using the extended pack syntax ; not the insertion of structure alignment bytes after the pair (pack comp (pack pair 1 2) 3) ;→ "\001\002\000\000\003\000\000\000" ; unpack reverses the process (unpack comp "\001\002\000\000\003\000\000\000") ;→ ((1 2) 3) < Nested structures are unpacked recursively. *newlisp-function-sub* *nl-sub* FUNCTION: sub~ {syntax:} (sub {num-1} [{num-2} ... ]) Successively subtracts the expressions in {num-1}, {num-2}—. |nl-sub| performs mixed-type arithmetic and handles integers or floating points, but it will always return a floating point number. If only one argument is supplied, its sign is reversed. Any floating point calculation with {NaN} also returns {NaN}. > (sub 10 8 0.25) ;→ 1.75 (sub 123) ;→ -123 < *newlisp-function-swap* *nl-swap* FUNCTION: swap~ |nl-destructive| {syntax:} (swap {place-1} {place-2}) The contents of the two places {place-1 and place-2} are swapped. A {place} can be the contents of an unquoted symbol or any list or array references expressed with |nl-nth|, |nl-first|, |nl-last| or implicit |nl-indexing| or places referenced by |nl-assoc| or |nl-lookup|. |nl-swap| is a destructive operation that changes the contents of the lists, arrays, or symbols involved. > (set 'lst '(a b c d e f)) (swap (first lst) (last lst)) ;→ a lst ;→ (f b c d e a) (set 'lst-b '(x y z)) (swap (lst 0) (lst-b -1)) ;→ f lst ;→ (z b c d e a) lst-b ;→ (x y f) (set 'A (array 2 3 (sequence 1 6)) ;→ ((1 2 3) (4 5 6)) (swap (A 0) (A 1)) ;→ (1 2 3) A ;→ ((4 5 6) (1 2 3)) (set 'x 1 'y 2) (swap x y) ;→ 1 x ;→ 2 y ;→ 1 (set 'lst '((a 1 2 3) (b 10 20 30))) (swap (lookup 'a lst -1) (lookup 'b lst 1)) lst ;→ ((a 1 2 10) (b 3 20 30)) (swap (assoc 'a lst) (assoc 'b lst)) lst ;→ ((b 3 20 30) (a 1 2 10)) < Any two places can be swept in the same or different objects. *newlisp-function-sym* *nl-sym* FUNCTION: sym~ {syntax:} (sym {string} [{sym-context} {nil-flag}]) + {syntax:} (sym {number} [{sym-context} {nil-flag}]) + {syntax:} (sym {symbol} [{sym-context} {nil-flag}]) Translates the first argument in {string}, {number}, or {symbol} into a symbol and returns it. If the optional context is not specified in {sym-context}, the current context is used when doing symbol lookup or creation. Symbols will be created if they do not already exist. When the context does not exist and the context is specified by a quoted symbol, the symbol also gets created. If the context specification is unquoted, the context is the specified name or the context specification is a variable containing the context. |nl-sym| can create symbols within the symbol table that are not legal symbols in newLISP source code (e.g., numbers or names containing special characters such as parentheses, colons, etc.). This makes |nl-sym| usable as a function for associative memory access, much like _hash table_ access in other scripting languages. As a third optional argument, {nil} can be specified to suppress symbol creation if the symbol is not found. In this case, |nl-sym| returns {nil} if the symbol looked up does not exist. Using this last form, |nl-sym| can be used to check for the existence of a symbol. > (sym "some") ;→ some (set (sym "var") 345) ;→ 345 var ;→ 345 (sym "aSym" 'MyCTX) ;→ MyCTX:aSym (sym "aSym" MyCTX) ;→ MyCTX:aSym ; unquoted context (sym "foo" MyCTX nil) ;→ nil ; 'foo does not exist (sym "foo" MyCTX) ;→ foo ; 'foo is created (sym "foo" MyCTX nil) ;→ foo ; foo now exists < Because the function |nl-sym| returns the symbol looked up or created, expressions with |nl-sym| can be embedded directly in other expressions that use symbols as arguments. The following example shows the use of |nl-sym| as a hash-like function for associative memory access, as well as symbol configurations that are not legal newLISP symbols: > ;; using sym for simulating hash tables (set (sym "John Doe" 'MyDB) 1.234) (set (sym "(" 'MyDB) "parenthesis open") (set (sym 12 'MyDB) "twelve") (eval (sym "John Doe" 'MyDB)) ;→ 1.234 (eval (sym "(" 'MyDB)) ;→ "parenthesis open" (eval (sym 12 'MyDB)) ;→ "twelve" ;; delete a symbol from a symbol table or hash (delete (sym "John Doe" 'MyDB)) ;→ true < The last statement shows how a symbol can be eliminated using |nl-delete|. The third syntax allows symbols to be used instead of strings for the symbol name in the target context. In this case, |nl-sym| will extract the name from the symbol and use it as the name string for the symbol in the target context: > (sym 'myVar 'FOO) ;→ FOO:myVar (define-macro (def-context) (dolist (s (rest (args))) (sym s (first (args))))) (def-context foo x y z) (symbols foo) ;→ (foo:x foo:y foo:z) < The {def-context} macro shows how this could be used to create a macro that creates contexts and their variables in a dynamic fashion. A syntax of the |nl-context| function can also be used to create, set and evaluate symbols. *newlisp-function-symbol?* *nl-symbol?* FUNCTION: symbol?~ {syntax:} (symbol? {exp}) Evaluates the {exp} expression and returns {true} if the value is a symbol; otherwise, it returns {nil}. > (set 'x 'y) ;→ y (symbol? x) ;→ true (symbol? 123) ;→ nil (symbol? (first '(var x y z))) ;→ true < The first statement sets the contents of {x} to the symbol {y}. The second statement then checks the contents of {x}. The last example checks the first element of a list. *newlisp-function-symbols* *nl-symbols* FUNCTION: symbols~ {syntax:} (symbols [{context}]) Returns a sorted list of all symbols in the current context when called without an argument. If a context symbol is specified, symbols defined in that context are returned. > (symbols) ; list of all symbols in current context (symbols 'CTX) ; list of symbols in context CTX (symbols CTX) ; omitting the quote (set 'ct CTX) ; assigning context to a variable (symbols ct) ; list of symbols in context CTX < The quote can be omitted because contexts evaluate to themselves. *newlisp-function-sync* *nl-sync* FUNCTION: sync~ {syntax:} (sync {int-timeout} [{func-inlet}]) + {syntax:} (sync) When {int-timeout} in milliseconds is specified, |nl-sync| waits for child processes launched with |nl-spawn| to finish. Whenever a child process finishes, |nl-sync| assigns the evaluation result of the spawned subtask to the symbol specified in the spawn statement. The |nl-sync| returns {true} if all child processes have been processed or {nil} if the timeout value has been reached and more child processes are pending. If |nl-sync| additionally is given with an optional user-defined {inlet} function in {func-inlet}, this function will be called with the child process-id as argument whenever a spawned child process returns. {func-inlet} can contain either a lambda expression or a symbol which defines a function. Without any parameter, |nl-sync| returns a list of pending child process PIDs (process identifiers), for which results have not been processed yet. The function |nl-sync| is not available on Win32. > ; wait for 10 seconds and process finished child processes (sync 10000) ; wait for the maximum time (~ 1193 hours) (sync -1) (define (report pid) (println "process: " pid " has returned")) ; call the report function, when a child returns (sync 10000 report) ; wait for 10 seconds max ; return a list of pending child processes (sync) ;→ (245 246 247 248) ; wait and do something else (until (true? (sync 10 report) ) (println (time-of-day))) < When |nl-sync| is given with a timeout parameter, it will block until timeout or until all child processes have returned, whichever comes earlier. When no parameter is specified or a function is specified, |nl-sync| returns immediately. The function |nl-sync| is part of the Cilk API for synchronizing child processes and process parallelization. See the reference for the function |nl-spawn| for a full discussion of the Cilk API. *newlisp-function-sys-error* *nl-sys-error* FUNCTION: sys-error~ {syntax:} (sys-error) + {syntax:} (sys-error {int-error}) + {syntax:} (sys-error {0}) Reports the last error generated by the underlying OS which newLISP is running on. The error reported may differ on the platforms newLISP has been compiled for. Consult the platform's C library information. The error is reported as a list of error number and error text. If no error has occurred or the system error number has been reset, {nil} is returned. When {int-error} is greater {0} (zero) a list of the number and the error text is returned. To reset the error specify {0} as the error number. Whenever a function in newLISP within the system resources area returns {nil}, |nl-sys-error| can be checked for the underlying reason. For file operations, |nl-sys-error| may be set for nonexistent files or wrong permissions when accessing the resource. Another cause of error could be the exhaustion of certain system resources like file handles or semaphores. > ;; trying to open a nonexistent file (open "xyz" "r") ;→ nil (sys-error) ;→ (2 "No such file or directory") ;; reset errno (sys-error 0) ;→ (0 "Unknown error: 0") (sys-error) ;→ nil < See also |nl-last-error| and |nl-net-error|. *newlisp-function-sys-info* *nl-sys-info* FUNCTION: sys-info~ {syntax:} (sys-info [{int-idx}]) Calling |nl-sys-info| without {int-idx} returns a list of internal resource statistics. Ten integers report the following status: [cols="1<,9<",width="50%",options="header",] |======================================================================= |offset |description |0 |Number of Lisp cells |1 |Maximum number of Lisp cells constant |2 |Number of symbols |3 |Evaluation/recursion level |4 |Environment stack level |5 |Maximum call stack constant |6 |Pid of the parent process or 0 |7 |Pid of running newLISP process |8 |Version number as an integer constant |9 |Operating system constant: + linux=1, bsd=2, osx=3, solaris=4, win32=6, os/2=7, cygwin=8, tru64unix=9, aix=10 + bit 11 will be set for ffilib (extended import/callback API) versions (add 1024) + bit 10 will be set for IPv6 versions (add 512) + bit 9 will be set for 64-bit (changeable at runtime) versions (add 256) + bit 8 will be set for UTF-8 versions (add 128) + bit 7 will be added for library versions (add 64) |======================================================================= The numbers from {0} to {9} indicate the optional offset in the returned list. It is recommended to use offsets 0 to 5 to address up and including "Maximum call stack constant" and to use negative offsets -1 to -4 to access the last four entries in the system info list. Future new entries will be inserted after offset 5. This way older source code does not need to change. When using {int-idx}, one element of the list will be returned. > (sys-info) ;→ (401 268435456 376 1 0 2048 39220 10002 131) (sys-info 3) ;→ 1 (sys-info -2) ;→ 10002 < The number for the maximum of Lisp cells can be changed via the {-m} command-line switch. For each megabyte of Lisp cell memory, 64k memory cells can be allocated. The maximum call stack depth can be changed using the {-s} command-line switch. *newlisp-function-t-test* *nl-t-test* FUNCTION: t-test~ {syntax:} (t-test {list-vector-A} {list-vecor-B} [{true}]) The functions performs a t-test using the {Student's t} statistic for comparing the means values in {list-vector-A} and {list-vecor-B}. If the {true} flag is not used, both vectors in A and B can be of different length and groups represented by A and B are not related. When the optional flag is set to {true}, measurements were taken from the same group twice, e.g. before and after a procedure. The following results are returned in a list: [cols="1<,4<",width="35%",options="header",] |============================================================== |name |description |mean-a |Mean of group A |mean-b |Mean of group B |sdev-a |Standard deviation in group A |sdev-b |Standard deviation in group B |t |t between mean values |df |Degress of freedom |p |Two tailed probablity of t under the null hypothesis |============================================================== The first example studies the effect of different sleep length before a test on the SCAT (Sam's Cognitive Ability Test): > ; SCAT (Sam's Cognitive Ability Test) (set 'hours-sleep-8 '(5 7 5 3 5 3 3 9)) (set 'hours-sleep-4 '(8 1 4 6 6 4 1 2)) (t-test hours-sleep-8 hours-sleep-4) ;→ (5 4 2.138 2.563 0.847 14 0.411) < The duration of sleeps before the SCAT does not have a significant impact with a probability value of {0.411}. In the second example, the same group of people get tested twice, before and after a treatment with Prosac depression medication: > ; Effect of Prozac on a group of depressed people (set 'mood-pre '(3 0 6 7 4 3 2 1 4)) (set 'mood-post '(5 1 5 7 10 9 7 11 8)) (t-test mood-pre mood-post true) ;→ (3.333 7 2.236 3.041 -3.143 8 0.0137) < The effect of the Prosac treatment is moderately significant with a {p} of {0.0137}. *newlisp-function-tan* *nl-tan* FUNCTION: tan~ {syntax:} (tan {num-radians}) Calculates the tangent function from {num-radians} and returns the result. > (tan 1) ;→ 1.557407725 (set 'pi (mul 2 (asin 1))) ;→ 3.141592654 (tan (div pi 4)) ;→ 1 < *newlisp-function-tanh* *nl-tanh* FUNCTION: tanh~ {syntax:} (tanh {num-radians}) Calculates the hyperbolic tangent of {num-radians}. The hyperbolic tangent is defined mathematically as: {sinh (x) / cosh (x)}. > (tanh 1) ;→ 0.761594156 (tanh 10) ;→ 0.9999999959 (tanh 1000) ;→ 1 (= (tanh 1) (div (sinh 1) (cosh 1))) ;→ true < *newlisp-function-term* *nl-term* FUNCTION: term~ {syntax:} (term {symbol}) Returns as a string, the term part of a {symbol} without the context prefix. > (set 'ACTX:var 123) (set 'sm 'ACTX:var) (string sm) ;→ "ACTX:var" (term sm) ;→ "var" (set 's 'foo:bar) (= s (sym (term s) (prefix s))) < See also |nl-prefix| to extract the namespace or context prefix from a symbol. *newlisp-function-throw* *nl-throw* FUNCTION: throw~ {syntax:} (throw {exp}) Works together with the |nl-catch| function. |nl-throw| forces the return of a previous |nl-catch| statement and puts the {exp} into the result symbol of |nl-catch|. > (define (throw-test) (dotimes (x 1000) (if (= x 500) (throw "interrupted")))) (catch (throw-test) 'result) ;→ true result ;→ "interrupted" (catch (throw-test)) ;→ "interrupted" < The last example shows a shorter form of |nl-catch|, which returns the |nl-throw| result directly. |nl-throw| is useful for breaking out of a loop or for early return from user-defined functions or expression blocks. In the following example, the |nl-begin| block will return {X} if {(foo X)} is {true}; else {Y} will be returned: > (catch (begin … (if (foo X) (throw X) Y) … )) < |nl-throw| will {not} cause an error exception. Use |nl-throw-error| to throw user error exceptions. *newlisp-function-throw-error* *nl-throw-error* FUNCTION: throw-error~ {syntax:} (throw-error {exp}) Causes a user-defined error exception with text provided by evaluating {exp}. > (define (foo x y) (if (= x 0) (throw-error "first argument cannot be 0")) (+ x y)) (foo 1 2) ;→ 3 (foo 0 2) ; causes a user error exception ERR: user error : first argument cannot be 0 called from user-defined function foo < The user error can be handled like any other error exception using user-defined error handlers and the |nl-error-event| function, or the form of |nl-catch| that can capture error exceptions. *newlisp-function-time* *nl-time* FUNCTION: time~ {syntax:} (time {exp} [{int-count}) Evaluates the expression in {exp} and returns the time spent on evaluation in floating point milliseconds. Depending on the platform decimals of milliseconds are shown or not shown. > (time (myprog x y z)) ;→ 450.340 (time (myprog x y z) 10) ;→ 4420.021 < In first the example, 450 milliseconds elapsed while evaluating {(myprog x y z)}. The second example returns the time for ten evaluations of {(myprog x y z)}. See also |nl-date|, |nl-date-value|, |nl-time-of-day|, and |nl-now|. *newlisp-function-time-of-day* *nl-time-of-day* FUNCTION: time-of-day~ {syntax:} (time-of-day) Returns the time in milliseconds since the start of the current day. See also the |nl-date|, |nl-date-value|, |nl-time|, and |nl-now| functions. *newlisp-function-timer* *nl-timer* FUNCTION: timer~ {syntax:} (timer {sym-event-handler | func-event-handler} {num-seconds} [{int-option}]) + {syntax:} (timer {sym-event-handler | func-event-handler}) + {syntax:} (timer) Starts a one-shot timer firing off the Unix signal {SIGALRM}, {SIGVTALRM}, or {SIGPROF} after the time in seconds (specified in {num-seconds}) has elapsed. When the timer fires, it calls the user-defined function in {sym-} or {func-event-handler}. On Linux/Unix, an optional {0}, {1}, or {2} can be specified to control how the timer counts. With default option {0}, real time is measured. Option {1} measures the time the CPU spends processing in the process owning the timer. Option {2} is a combination of both called _profiling time_. See the Unix man page {setitimer()} for details. The event handler can start the timer again to achieve a continuous flow of events. Starting with version 8.5.9, seconds can be defined as floating point numbers with a fractional part (e.g., {0.25} for 250 milliseconds). Defining {0} (zero) as time shuts the running timer down and prevents it from firing. When called with {sym-} or {func-event-handler}, |nl-timer| returns the elapsed time of the timer in progress. This can be used to program time lines or schedules. |nl-timer| called without arguments returns the symbol of the current event handler. > (define (ticker) (println (date)) (timer 'ticker 1.0)) > (ticker) Tue Apr 12 20:44:48 2005 ; first execution of ticker ;→ ticker ; return value from ticker > Tue Apr 12 20:44:49 2005 ; first timer event Tue Apr 12 20:44:50 2005 ; second timer event ... Tue Apr 12 20:44:51 2005 Tue Apr 12 20:44:52 2005 < The example shows an event handler, {ticker}, which starts the timer again after each event. Note that a timer cannot interrupt an ongoing built-in function. The timer interrupt gets registered by newLISP, but a timer handler cannot run until one expression is evaluated and the next one starts. To interrupt an ongoing I/O operation with |nl-timer|, use the following pattern, which calls |nl-net-select| to test if a socket is ready for reading: > define (interrupt) (set 'timeout true)) (set 'listen (net-listen 30001)) (set 'socket (net-accept listen)) (timer 'interrupt 10) ;; or specifying the function directly (timer (fn () (set 'timeout true)) 10) (until (or timeout done) (if (net-select socket "read" 100000) (begin (net-receive socket buffer 1024) (set 'done true))) ) (if timeout (println "timeout") (println buffer)) (exit) < In this example, the |nl-until| loop will run until something can be read from {socket}, or until ten seconds have passed and the {timeout} variable is set. *newlisp-function-title-case* *nl-title-case* FUNCTION: title-case~ |nl-utf8_capable| {syntax:} (title-case {str} {[bool]}) Returns a copy of the string in {str} with the first character converted to uppercase. When the optional {bool} parameter evaluates to any value other than {nil}, the rest of the string is converted to lowercase. > (title-case "hello") ;→ "Hello" (title-case "hELLO" true) ;→ "Hello" (title-case "hELLO") ;→ "HELLO" < See also the |nl-lower-case| and |nl-upper-case| functions. *newlisp-function-trace* *nl-trace* FUNCTION: trace~ {syntax:} (trace [{bool}]) Tracing is switched on when {bool} evaluates to anything other than {nil}. When no argument is supplied, |nl-trace| evaluates to {true} or {nil} depending on the current trace mode. If trace mode is switched on, newLISP goes into debugging mode after entering the next user defined function, displaying the function and highlighting the current expression upon entry and exit. Highlighting is done by bracketing the expression between two # (number sign) characters. This can be changed to a different character using |nl-trace-highlight|. Upon exit from the expression, the result of its evaluation is also reported. If an expression occurs more than once in a function, the first occurrence of the executing function will always be highlighted (bracketed). newLISP execution stops with a prompt line at each entry and exit of an expression. > [-> 2] s|tep n|ext c|ont q|uit > < At the prompt, an {s}, {n}, {c}, or {q} can be entered to step into or merely execute the next expression. Any expression can be entered at the prompt for evaluation. Entering the name of a variable, for example, would evaluate to its contents. In this way, a variable's contents can be checked during debugging or set to different values. > ;; switches newLISP into debugging mode (trace true) ;→ true ;; the debugger will show each step (my-func a b c) ;; switched newLISP out of debugging mode (trace nil) ;→ nil < To set break points where newLISP should interrupt normal execution and go into debugging mode, put {(trace true)} statements into the newLISP code where execution should switch on the debugger. Use the |nl-debug| function as a shortcut for the above example. *newlisp-function-trace-highlight* *nl-trace-highlight* FUNCTION: trace-highlight~ {syntax:} (trace-highlight {str-pre} {str-post} [{str-header} {str-footer}]) Sets the characters or string of characters used to enclose expressions during |nl-trace|. By default, the # (number sign) is used to enclose the expression highlighted in |nl-trace| mode. This can be changed to different characters or strings of up to seven characters. If the console window accepts terminal control characters, this can be used to display the expression in a different color, bold, reverse, and so forth. Two more strings can optionally be specified for _str-header and str-footer_, which control the separator and prompt. A maximum of 15 characters is allowed for the header and 31 for the footer. > ;; active expressions are enclosed in >> and << (trace-highlight ">>" "<<") ;; 'bright' color on a VT100 or similar terminal window (trace-highlight "\027[1m" "\027[0m") < The first example replaces the default {#} (number sign) with a |nl->>| and |nl-<<|. The second example works on most Linux shells. It may not, however, work in console windows under Win32 or CYGWIN, depending on the configuration of the terminal. *newlisp-function-transpose* *nl-transpose* FUNCTION: transpose~ {syntax:} (transpose {matrix}) Transposes a {matrix} by reversing the rows and columns. Any kind of list-matrix can be transposed. Matrices are made rectangular by filling in {nil} for missing elements, omitting elements where appropriate, or expanding atoms in rows into lists. Matrix dimensions are calculated using the number of rows in the original matrix for columns and the number of elements in the first row as number of rows for the transposed matrix. The matrix to transpose can contain any data-type. The dimensions of a matrix are defined by the number of rows and the number of elements in the first row. A matrix can either be a nested list or an |nl-array|. > (set 'A '((1 2 3) (4 5 6))) (transpose A) ;→ ((1 4) (2 5) (3 6)) (transpose (list (sequence 1 5))) ;→ ((1) (2) (3) (4) (5)) ; any data type is allowed in the matrix (transpose '((a b) (c d) (e f))) ;→ ((a c e) (b d f)) ; arrays can be transposed too (set 'A (array 2 3 (sequence 1 6))) (set 'M (transpose A)) M ;→ ((1 4) (2 5) (3 6)) < The number of columns in a matrix is defined by the number of elements in the first row of the matrix. If other rows have fewer elements, |nl-transpose| will assume {nil} for those missing elements. Superfluous elements in a row will be ignored. > (set 'A '((1 2 3) (4 5) (7 8 9))) (transpose A) ;→ ((1 4 7) (2 5 8) (3 nil 9)) < If a row is any other data type besides a list, the transposition treats it like an entire row of elements of that data type: > (set 'A '((1 2 3) X (7 8 9))) (transpose A) ;→ ((1 X 7) (2 X 8) (3 X 9)) < All operations shown here on lists can also be performed on arrays. See also the matrix operations |nl-det|, |nl-invert|, |nl-mat| and |nl-multiply|. *newlisp-function-trim* *nl-trim* FUNCTION: trim~ |nl-utf8_capable| {syntax:} (trim {str} [{str-char}]) + {syntax:} (trim {str} {str-left-char} {str-right-char}) The first syntax trims the string {str} from both sides, stripping the leading and trailing characters as given in {str-char}. If {str-char} contains no character, the space character is assumed. |nl-trim| returns the new string. The second syntax can either trim different characters from both sides or trim only one side if an empty string is specified for the other. > (trim " hello ") ;→ "hello" (trim "----hello-----" "-") ;→ "hello" (trim "00012340" "0" "") ;→ "12340" (trim "1234000" "" "0") ;→ "1234" (trim "----hello=====" "-" "=") ;→ "hello" < *newlisp-function-true?* *nl-true?* FUNCTION: true?~ {syntax:} (true? {exp}) If the expression in {exp} evaluates to anything other than {nil} or the empty list {()}, |nl-true?| returns {true}; otherwise, it returns {nil}. > (map true? '(x 1 "hi" (a b c) nil ())) ;→ (true true true true nil nil) (true? nil) ;→ nil (true? '()) ;→ nil < |nl-true?| behaves like |nl-if| and rejects the empty list {()}. *newlisp-function-unicode* *nl-unicode* FUNCTION: unicode~ {syntax:} (unicode {str-utf8}) Converts ASCII/UTF-8 character strings in {str} to UCS-4–encoded Unicode of 4-byte integers per character. The string is terminated with a 4-byte integer {0}. This function is only available on UTF-8–enabled versions of newLISP. > (unicode "new") ;→ "n\000\000\000e\000\000\000w\000\000\000\000\000\000\000" (utf8 (unicode "new")) ;→ "new" < On {big endian} CPU architectures, the byte order will be reversed from high to low. The |nl-unicode| and |nl-utf8| functions are the inverse of each other. These functions are only necessary if UCS-4 Unicode is in use. Most systems use UTF-8 encoding only. *newlisp-function-unify* *nl-unify* FUNCTION: unify~ {syntax:} (unify {exp-1} {exp-2} [{list-env}]) Evaluates and matches {exp-1} and {exp-2}. Expressions match if they are equal or if one of the expressions is an unbound variable (which would then be bound to the other expression). If expressions are lists, they are matched by comparing subexpressions. Unbound variables start with an uppercase character to distinguish them from symbols. |nl-unify| returns {nil} when the unification process fails, or it returns a list of variable associations on success. When no variables were bound, but the match is still successful, |nl-unify| returns an empty list. newLISP uses a modified {J. Alan Robinson} unification algorithm with correctly applied {occurs check}. See also {Peter Norvig}'s paper about a common http://norvig.com/unify-bug.pdf[unifcation algorithm bug], which is not present in this implementation. Since version 10.4.0 the underscore symbol {_} (ASCII 95) matches any atom, list or unbound variable and never binds. Like |nl-match|, |nl-unify| is frequently employed as a parameter functor in |nl-find|, |nl-ref|, |nl-ref-all| and |nl-replace|. > (unify 'A 'A) ;→ () ; tautology (unify 'A 123) ;→ ((A 123)) ; A bound to 123 (unify '(A B) '(x y)) ;→ ((A x) (B y)) ; A bound to x, B bound to y (unify '(A B) '(B abc)) ;→ ((A abc) (B abc)) ; B is alias for A (unify 'abc 'xyz) ;→ nil ; fails because symbols are different (unify '(A A) '(123 456)) ;→ nil ; fails because A cannot be bound to different values (unify '(f A) '(f B)) ;→ ((A B)) ; A and B are aliases (unify '(f A) '(g B)) ;→ nil ; fails because heads of terms are different (unify '(f A) '(f A B)) ;→ nil ; fails because terms are of different arity (unify '(f (g A)) '(f B)) ;→ ((B (g A))) ; B bound to (g A) (unify '(f (g A) A) '(f B xyz)) ;→ ((B (g xyz)) (A xyz)) ; B bound to (g xyz) A to xyz (unify '(f A) 'A) ;→ nil ; fails because of infinite unification (f(f(f …))) (unify '(A xyz A) '(abc X X)) ;→ nil ; indirect alias A to X doesn't match bound terms (unify '(p X Y a) '(p Y X X)) ;→ '((Y a) (X a))) ; X alias Y and binding to 'a (unify '(q (p X Y) (p Y X)) '(q Z Z)) ;→ ((Y X) (Z (p X X))) ; indirect alias (unify '(A b _) '(x G z)) ;→ ((A x) (G b)) ; _ matches atom z (unify '(A b c _) '(x G _ z)) ;→ ((A x) (G b)) ; _ never binds, matches c and z (unify '(A b _) '(x G (x y z))) ;→ ((A x) (G b)) ; _ matches list (x y z) ;; some examples taken from http://en.wikipedia.org/wiki/Unification < |nl-unify| can take an optional binding or association list in {list-env}. This is useful when chaining |nl-unify| expressions and the results of previous |nl-unify| bindings must be included: > (unify '(f X) '(f 123)) ;→ ((X 123)) (unify '(A B) '(X A) '((X 123))) ;→ ((X 123) (A 123) (B 123)) < In the previous example, {X} was bound to {123} earlier and is included in the second statement to pre-bind {X}. Use |nl-unify| with |nl-expand| ^^^^^^^^^^^^^^^^^^^^^^^^^ Note that variables are not actually bound as a newLISP assignment. Rather, an association list is returned showing the logical binding. A special syntax of |nl-expand| can be used to actually replace bound variables with their terms: > (set 'bindings (unify '(f (g A) A) '(f B xyz))) ;→ ((B (g xyz)) (A xyz)) (expand '(f (g A) A) bindings) ;→ (f (g xyz) xyz) ; or in one statement (expand '(f (g A) A) (unify '(f (g A) A) '(f B xyz))) ;→ (f (g xyz) xyz) < Use |nl-unify| with |nl-bind| for de-structuring ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The function |nl-bind| can be used to set unified variables: > (bind (unify '(f (g A) A) '(f B xyz))) A ;→ xyz B ;→ (g xyz) < This can be used for de-structuring: > (set 'structure '((one "two") 3 (four (x y z)))) (set 'pattern '((A B) C (D E))) (bind (unify pattern structure)) A ;→ one B ;→ "two" C ;→ 3 D ;→ four E ;→ (x y z) < |nl-unify| returns an association list and |nl-bind| binds the associations. Model propositional logic with |nl-unify| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The following example shows how propositional logic can be modeled using |nl-unify| and |nl-expand|: > ; if somebody is human, he is mortal -> (X human) :- (X mortal) ; socrates is human -> (socrates human) ; is socrates mortal? -> ? (socrates mortal) (expand '(X mortal) (unify '(X human) '(socrates human))) ;→ (socrates mortal) < The following is a more complex example showing a small, working PROLOG (Programming in Logic) implementation. > ;; a small PROLOG implementation (set 'facts '( (socrates philosopher) (socrates greek) (socrates human) (einstein german) (einstein (studied physics)) (einstein human) )) (set 'rules '( ((X mortal) <- (X human)) ((X (knows physics)) <- (X physicist)) ((X physicist) <- (X (studied physics))) )) (define (query trm) (or (if (find trm facts) true) (catch (prove-rule trm)))) (define (prove-rule trm) (dolist (r rules) (if (list? (set 'e (unify trm (first r)))) (if (query (expand (last r) e)) (throw true)))) nil ) ; try it > (query '(socrates human)) true > (query '(socrates (knows physics))) nil > (query '(einstein (knows physics))) true < The program handles a database of {facts} and a database of simple _A is a fact if B is a fact_ {rules}. A fact is proven true if it either can be found in the {facts} database or if it can be proven using a rule. Rules can be nested: for example, to prove that somebody {(knows physics)}, it must be proved true that somebody is a {physicist}. But somebody is only a physicist if that person {studied physics}. The {<-} symbol separating the left and right terms of the rules is not required and is only added to make the rules database more readable. This implementation does not handle multiple terms in the right premise part of the rules, but it does handle backtracking of the {rules} database to try out different matches. It does not handle backtracking in multiple premises of the rule. For example, if in the following rule {A if B and C and D}, the premises {B} and {C} succeed and {D} fails, a backtracking mechanism might need to go back and reunify the {B} or {A} terms with different facts or rules to make {D} succeed. The above algorithm could be written differently by omitting |nl-expand| from the definition of {prove-rule} and by passing the environment, {e}, as an argument to the |nl-unify| and {query} functions. A {learning} of proven facts can be implemented by appending them to the {facts} database once they are proven. This would speed up subsequent queries. Larger PROLOG implementations also allow the evaluation of terms in rules. This makes it possible to implement functions for doing other work while processing rule terms. {prove-rule} could accomplish this testing for the symbol |nl-eval| in each rule term. *newlisp-function-union* *nl-union* FUNCTION: union~ {syntax:} (union {list-1} {list-2} [{list-3} ... ]) |nl-union| returns a unique collection list of distinct elements found in two or more lists. > (union '(1 3 1 4 4 3) '(2 1 5 6 4)) ;→ (1 3 4 2 5 6) < Like the other set functions |nl-difference|, |nl-intersect| and |nl-unique|, |nl-union| maintains the order of elements as found in the original lists. *newlisp-function-unique* *nl-unique* FUNCTION: unique~ {syntax:} (unique {list}) Returns a unique version of {list} with all duplicates removed. > (unique '(2 3 4 4 6 7 8 7)) ;→ (2 3 4 6 7 8) < Note that the list does not need to be sorted, but a sorted list makes |nl-unique| perform faster. Other {set} functions are |nl-difference|, |nl-intersect| and |nl-union|. *newlisp-function-unless* *nl-unless* FUNCTION: unless~ {syntax:} (unless {exp-condition} {body}) The statements in {body} are only evaluated if {exp-condition} evaluates to {nil} or the empty list {()}. The result of the last expression in {body} is returned or {nil} or the empty list {()} if {body} was not executed. Because |nl-unless| does not have an {else} condition as in |nl-if|, the statements in {body} need not to be grouped with |nl-begin|: > (unless (starts-with (read-line) "quit") (process (current-line)) ... (finish) ) < See also the function |nl-when|. *newlisp-function-unpack* *nl-unpack* FUNCTION: unpack~ {syntax:} (unpack {str-format} {str-addr-packed}) + {syntax:} (unpack {str-format} {num-addr-packed}) + {syntax:} (unpack {struct} {num-addr-packed}) + {syntax:} (unpack {struct} {str-addr-packed}) When the first parameter is a string, |nl-unpack| unpacks a binary structure in {str-addr-packed} or pointed to by {num-addr-packed} into newLISP variables using the format in {str-format}. |nl-unpack| is the reverse operation of |nl-pack|. Using {num-addr-packed} facilitates the unpacking of structures returned from imported, shared library functions. If the number specified in {num-addr-packed} is not a valid memory address, a system bus error or segfault can occur and crash newLISP or leave it in an unstable state. When the first parameter is the symbol of a |nl-struct| definition, |nl-unpack| uses the format as specified in {struct}. While |nl-unpack| with {str-format} literally unpacks as specified, |nl-unpack| with {struct} will skip structure aligning pad-bytes depending on data type, order of elements and CPU architecture. Refer to the description of the |nl-struct| function for more detail. The following characters may define a format: [cols="1<,4<",width="25%",options="header",] |================================================== |format |description |{c } |a signed 8-bit number |{b } |an unsigned 8-bit number |{d } |a signed 16-bit short number |{u } |an unsigned 16-bit short number |{ld} |a signed 32-bit long number |{lu} |an unsigned 32-bit long number |{Ld} |a signed 64-bit long number |{Lu} |an unsigned 64-bit long number |{f } |a float in 32-bit representation |{lf} |a double float in 64-bit representation |{sn} |a string of {n} null padded ASCII characters |{nn} |{n} null characters ||nl->| |switches to big endian byte order ||nl-<| |switches to little endian byte order |================================================== > (pack "c c c" 65 66 67) ;→ "ABC" (unpack "c c c" "ABC") ;→ (65 66 67) (set 's (pack "c d u" 10 12345 56789)) (unpack "c d u" s) ;→ (10 12345 56789) (set 's (pack "s10 f" "result" 1.23)) (unpack "s10 f" s) ;→ ("result\000\000\000\000" 1.230000019) (set 's (pack "s3 lf" "result" 1.23)) (unpack "s3 f" s) ;→ ("res" 1.23) (set 's (pack "c n7 c" 11 22)) (unpack "c n7 c" s) ;→ (11 22)) < The |nl->| and |nl-<| specifiers can be used to switch between {little endian} and {big endian} byte order when packing or unpacking: > ;; on a little endian system (e.g., Intel CPUs) (set 'buff (pack "d" 1)) ;→ "\001\000" (unpack "d" buff) ;→ (1) (unpack ">d" buff) ;→ (256) < Switching the byte order will affect all number formats with 16-, 32-, or 64-bit sizes. The |nl-pack| and |nl-unpack| format need not be the same, as in the following example: > (set 's (pack "s3" "ABC")) (unpack "c c c" s) ;→ (65 66 67) < The examples show spaces between the format specifiers. Although not required, they can improve readability. If the buffer's size at a memory address is smaller than the formatting string specifies, some formatting characters may be left unused. See also the |nl-address|, |nl-get-int|, |nl-get-long|, |nl-get-char|, |nl-get-string|, and |nl-pack| functions. *newlisp-function-until* *nl-until* FUNCTION: until~ {syntax:} (until {exp-condition} [{body}]) Evaluates the condition in {exp-condition}. If the result is {nil} or the empty list {()}, the expressions in {body} are evaluated. Evaluation is repeated until the exp-condition results in a value other than {nil} or the empty list. The result of the last expression evaluated in {body} is the return value of the |nl-until| expression. If {body} is empty, the result of last {exp-condition} is returned. |nl-until| works like (|nl-while| (|nl-not| …)). |nl-until| also updates the system iterator symbol {$idx}. > (device (open "somefile.txt" "read")) (set 'line-count 0) (until (not (read-line)) (inc line-count)) (close (device)) (print "the file has " line-count " lines\n") < Use the |nl-do-until| function to test the condition {after} evaluation of the body expressions. *newlisp-function-upper-case* *nl-upper-case* FUNCTION: upper-case~ |nl-utf8_capable| {syntax:} (upper-case {str}) Returns a copy of the string in {str} converted to uppercase. International characters are converted correctly. > (upper-case "hello world") ;→ "HELLO WORLD" < See also the |nl-lower-case| and |nl-title-case| functions. *newlisp-function-utf8* *nl-utf8* FUNCTION: utf8~ {syntax:} (utf8 {str-unicode}) Converts a UCS-4, 4-byte, Unicode-encoded string ({str}) into UTF-8. This function is only available on UTF-8–enabled versions of newLISP. > (unicode "new") ;→ "n\000\000\000e\000\000\000w\000\000\000\000\000\000\000" (utf8 (unicode "new")) ;→ "new" < The |nl-utf8| function can also be used to test for the presence of UTF-8–enabled newLISP: > (if utf8 (do-utf8-version-of-code) (do-ascii-version-of-code)) < On {big endian} CPU architectures, the byte order will be reversed from highest to lowest. The |nl-utf8| and |nl-unicode| functions are the inverse of each other. These functions are only necessary if UCS-4 Unicode is in use. Most systems use UTF-8 Unicode encoding only. *newlisp-function-utf8len* *nl-utf8len* FUNCTION: utf8len~ {syntax:} (utf8len {str}) Returns the number of characters in a UTF-8–encoded string. UTF-8 characters can be encoded in more than one 8-bit byte. |nl-utf8len| returns the number of UTF-8 characters in a string. This function is only available on UTF-8–enabled versions of newLISP. > (utf8len "我能吞下玻璃而不伤身体。") ;→ 12 (length "我能吞下玻璃而不伤身体。") ;→ 36 < See also the |nl-unicode| and |nl-utf8| functions. Above Chinese text from http://www.columbia.edu/kermit/utf8.html[UTF-8 Sampler]. *newlisp-function-uuid* *nl-uuid* FUNCTION: uuid~ {syntax:} (uuid [{str-node}]) Constructs and returns a UUID (Universally Unique IDentifier). Without a node spec in {str-node}, a type 4 UUID random generated byte number is returned. When the optional {str-node} parameter is used, a type 1 UUID is returned. The string in {str-node} specifies a valid MAC (Media Access Code) from a network adapter installed on the node or a random node ID. When a random node ID is specified, the least significant bit of the first node byte should be set to 1 to avoid clashes with real MAC identifiers. UUIDs of type 1 with node ID are generated from a timestamp and other data. See http://www.ietf.org/rfc/rfc4122.txt[RFC 4122] for details on UUID generation. > ;; type 4 UUID for any system (uuid) ;→ "493AAD61-266F-48A9-B99A-33941BEE3607" ;; type 1 UUID preferred for distributed systems ;; configure node ID for ether 00:14:51:0a:e0:bc (set 'id (pack "cccccc" 0x00 0x14 0x51 0x0a 0xe0 0xbc)) (uuid id) ;→ "0749161C-2EC2-11DB-BBB2-0014510AE0BC" < Each invocation of the |nl-uuid| function will yield a new unique UUID. The UUIDs are generated without system-wide shared stable store (see RFC 4122). If the system generating the UUIDs is distributed over several nodes, then type 1 generation should be used with a different node ID on each node. For several processes on the same node, valid UUIDs are guaranteed even if requested at the same time. This is because the process ID of the generating newLISP process is part of the seed for the random number generator. When type 4 IDs are used on a distributed system, two identical UUID's are still highly unlikely and impossible for type 1 IDs if real MAC addresses are used. *newlisp-function-wait-pid* *nl-wait-pid* FUNCTION: wait-pid~ {syntax:} (wait-pid {int-pid} [{int-options} | {nil}]) Waits for a child process specified in {int-pid} to end. The child process was previously started with |nl-process| or |nl-fork|. When the child process specified in {int-pid} ends, a list of pid and status value is returned. The status value describes the reason for termination of the child process. The interpretation of the returned status value differs between Linux and other flavors of Unix. Consult the Linux/Unix man pages for the {waitpid} command (without the hyphen used in newLISP) for further information. When {-1} is specified for {int-pid}, pid and status information of any child process started by the parent are returned. When {0} is specified, |nl-wait-pid| only watches child processes in the same process group as the calling process. Any other negative value for {int-pid} reports child processes in the same process group as specified with a negative sign in {int-pid}. An option can be specified in {int-option}. See Linux/Unix documentation for details on integer values for {int-options}. As an alternative, {nil} can be specified. This option causes |nl-wait-pid| to be non-blocking, returning right away with a {0} in the pid of the list returned. This option used together with an {int-pid} parameter of {-1} can be used to continuously loop and act on returned child processes. This function is only available on Mac OS X, Linux and other Unix-like operating systems. > (set 'pid (fork (my-process))) ;→ 8596 (set 'ret (wait-pid pid)) ;→ (8596 0) ; child has exited (println "process: " pid " has finished with status: " (last ret)) < The process {my-process} is started, then the main program blocks in the |nl-wait-pid| call until {my-process} has finished. *newlisp-function-when* *nl-when* FUNCTION: when~ {syntax:} (when {exp-condition} {body}) The statements in {body} are only evaluated if {exp-condition} evaluates to anything not {nil} and not the empty list {()}. The result of the last expression in {body} is returned or {nil} or the empty list {()} if {body} was not executed. Because |nl-when| does not have an {else} condition as in |nl-if|, the statements in {body} need not to be grouped with |nl-begin|: > (when (read-line) (set 'result (analyze (current-line))) (report result) (finish) ) < See also the function |nl-unless| working like {(when (not ...) ...)}. *newlisp-function-while* *nl-while* FUNCTION: while~ {syntax:} (while {exp-condition} {body}) Evaluates the condition in {exp-condition}. If the result is not {nil} or the empty list {()}, the expressions in {body} are evaluated. Evaluation is repeated until an {exp-condition} results in {nil} or the empty list {()}. The result of the body's last evaluated expression is the return value of the |nl-while| expression. |nl-while| also updates the system iterator symbol {$idx}. > (device (open "somefile.txt" "read")) (set 'line-count 0) (while (read-line) (inc line-count)) (close (device)) (print "the file has " line-count " lines\n") < Use the |nl-do-while| function to evaluate the condition {after} evaluating the body of expressions. *newlisp-function-write* *nl-write* FUNCTION: write~ |nl-destructive| {syntax:} (write {int-file} {str-buffer} [{int-size}]) + {syntax:} (write {str} {str-buffer} [{int-size}]) The function |nl-write| writes {int-size} bytes from a buffer in {str-buffer} to a file specified in {int-file}, previously obtained from a file |nl-open| operation. If {int-size} is not specified, all data in {sym-buffer} or {str-buffer} is written. |nl-write| returns the number of bytes written or {nil} on failure. |nl-write| is a shorter writing of {write-buffer}. The longer form still works but is deprecated and should be avoided in new code. > (set 'handle (open "myfile.ext" "write")) (write handle data 100) (write handle "a quick message\n") < The code in the example writes 100 bytes to the file {myfile.ext} from the contents in {data}. In the second syntax, |nl-write| can be used for destructive string appending: > (set 'str "") (write str "hello world") str ;→ "hello world" < See also the |nl-read| function. *newlisp-function-write-char* *nl-write-char* FUNCTION: write-char~ {syntax:} (write-char {int-file} {int-byte1} [{int-byte2} ... ]) Writes a byte specified in {int-byte} to a file specified by the file handle in {int-file}. The file handle is obtained from a previous |nl-open| operation. Each |nl-write-char| advances the file pointer by one 8-bit byte. |nl-write-char| returns the number of bytes written. > (define (slow-file-copy from-file to-file) (set 'in-file (open from-file "read")) (set 'out-file (open to-file "write")) (while (set 'chr (read-char in-file)) (write-char out-file chr)) (close in-file) (close out-file) "finished") < Use the |nl-print| and |nl-device| functions to write larger portions of data at a time. Note that newLISP already supplies a faster built-in function called |nl-copy-file|. See also the |nl-read-char| function. *newlisp-function-write-file* *nl-write-file* FUNCTION: write-file~ {syntax:} (write-file {str-file-name} {str-buffer}) Writes a file in {str-file-name} with contents in {str-buffer} in one swoop and returns the number of bytes written. On failure the function returns {nil}. For error information, use |nl-sys-error| when used on files. When used on URLs |nl-net-error| gives more error information. > (write-file "myfile.enc" (encrypt (read-file "/home/lisp/myFile") "secret")) < The file {myfile} is read, |nl-encrypted| using the password {secret}, and written back into the new file {myfile.enc} in the current directory. |nl-write-file| can take an {http://} or {file://} URL in {str-file-name}. When the prefix {http://} is used, |nl-write-file| works exactly like |nl-put-url| and can take the same additional parameters: > (write-file "http://asite.com/message.txt" "This is a message" ) < The file {message.txt} is created and written at a remote location, {http://asite.com}, with the contents of {str-buffer}. In this mode, |nl-write-file| can also be used to transfer files to remote newLISP server nodes. See also the |nl-append-file| and |nl-read-file| functions. *newlisp-function-write-line* *nl-write-line* FUNCTION: write-line~ |nl-destructive| {syntax:} (write-line [{int-file} [{str}]]) + {syntax:} (write-line {str-out} [{str}]]) The string in {str} and the line termination character(s) are written to the device specified in {int-file}. When the string argument is omitted |nl-write-line| writes the contents of the last |nl-read-line| to {int-file} If the first argument is omitted too then it writes to to standard out (STDOUT) or to whatever device is set by |nl-device|. In the second syntax lines are appended to a string in {str-out}. |nl-write-line| returns the number of bytes written. > (set 'out-file (open "myfile" "write")) (write-line out-file "hello there") (close out-file) (set 'myFile (open "init.lsp" "read") (while (read-line myFile) (write-line)) (set 'str "") (write-line str "hello") (write-line str "world") str ;→ "hello\nworld\n" < The first example opens/creates a file, writes a line to it, and closes the file. The second example shows the usage of |nl-write-line| without arguments. The contents of {init.lsp} are written to the console screen. See also the function |nl-write| for writing to a device without the line-terminating character. *newlisp-function-xfer-event* *nl-xfer-event* FUNCTION: xfer-event~ {syntax:} (xfer-event {sym-event-handler} | {func-event-handler}) Registers a function in symbol {sym-event-handler} or in lambda function {func-event-handler} to monitor HTTP byte transfers initiated by |nl-get-url|, |nl-post-url| or |nl-put-url| or initiated by file functions which can take URLs like |nl-load|, |nl-save|, |nl-read-file|, |nl-write-file| and |nl-append-file|. E.g. whenever a block of data requested with |nl-get-url| arrives the function in {sym} or {func} will be called with the number of bytes transferred. Likewise when sending data with |nl-post-url| or any of the other data sending functions, {sym} or {func} will be called with the number of bytes transferred for each block of data transferred. > (xfer-event (fn (n) (println "->" n))) (length (get-url "http://newlisp.org")) ->73 ->799 ->1452 ->351 ->1093 ->352 ->211 ->885 ->564 ->884 ->561 ->75 ->812 ->638 ->1452 ->801 ->5 ->927 11935 < The computer output is shown in bold. Whenever a block of data is received its byte size is printed. Instead of defining the handler function directory with a lambda function in {func}, a symbol containing a function definition could have been used: > (define (report n) (println "->" n)) (xfer-event 'report) < This can be used to monitor the progress of longer lasting byte transfers in HTTP uploads or downloads. *newlisp-function-xml-error* *nl-xml-error* FUNCTION: xml-error~ {syntax:} (xml-error) Returns a list of error information from the last |nl-xml-parse| operation; otherwise, returns {nil} if no error occurred. The first element contains text describing the error, and the second element is a number indicating the last scan position in the source XML text, starting at {0} (zero). > (xml-parse "hello" 18) < *newlisp-function-xml-parse* *nl-xml-parse* FUNCTION: xml-parse~ {syntax:} (xml-parse {string-xml} [{int-options} [{sym-context} [{func-callback}]]]) Parses a string containing XML 1.0 compliant, {well-formed} XML. |nl-xml-parse| does not perform DTD validation. It skips DTDs (Document Type Declarations) and processing instructions. Nodes of type ELEMENT, TEXT, CDATA, and COMMENT are parsed, and a newLISP list structure is returned. When an element node does not have attributes or child nodes, it instead contains an empty list. Attributes are returned as association lists, which can be accessed using |nl-assoc|. When |nl-xml-parse| fails due to malformed XML, {nil} is returned and |nl-xml-error| can be used to access error information. > (set 'xml "nice guy") (xml-parse xml) ;→ (("ELEMENT" "person" (("name" "John Doe") ("tel" "555-1212")) (("TEXT" "nice guy")))) < Modifying the translation process ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Optionally, the {int-options} parameter can be specified to suppress whitespace, empty attribute lists, and comments. It can also be used to transform tags from strings into symbols. Another function, |nl-xml-type-tags|, serves for translating the XML tags. The following option numbers can be used: [cols="1<,4<",width="30%",options="header",] |============================================== |option |description |1 |suppress whitespace text tags |2 |suppress empty attribute lists |4 |suppress comment tags |8 |translate string tags into symbols |16 |add SXML (S-expression XML) attribute tags |============================================== Options can be combined by adding the numbers (e.g., {3} would combine the options for suppressing whitespace text tags/info and empty attribute lists). The following examples show how the different options can be used: .XML source: > apple red 0.80 orange orange 1.00 banana yellow 0.60 < .Parsing without any options: > (xml-parse (read-file "example.xml")) ;→ (("ELEMENT" "DATABASE" (("name" "example.xml")) (("TEXT" "\r\n\t") ("COMMENT" "This is a database of fruits") ("TEXT" "\r\n\t") ("ELEMENT" "FRUIT" () (("TEXT" "\r\n\t\t") ("ELEMENT" "NAME" () (("TEXT" "apple"))) ("TEXT" "\r\n\t\t") ("ELEMENT" "COLOR" () (("TEXT" "red"))) ("TEXT" "\r\n\t\t") ("ELEMENT" "PRICE" () (("TEXT" "0.80"))) ("TEXT" "\r\n\t"))) ("TEXT" "\r\n\r\n\t") ("ELEMENT" "FRUIT" () (("TEXT" "\r\n\t\t") ("ELEMENT" "NAME" () (("TEXT" "orange"))) ("TEXT" "\r\n\t\t") ("ELEMENT" "COLOR" () (("TEXT" "orange"))) ("TEXT" "\r\n\t\t") ("ELEMENT" "PRICE" () (("TEXT" "1.00"))) ("TEXT" "\r\n\t"))) ("TEXT" "\r\n\r\n\t") ("ELEMENT" "FRUIT" () (("TEXT" "\r\n\t\t") ("ELEMENT" "NAME" () (("TEXT" "banana"))) ("TEXT" "\r\n\t\t") ("ELEMENT" "COLOR" () (("TEXT" "yellow"))) ("TEXT" "\r\n\t\t") ("ELEMENT" "PRICE" () (("TEXT" "0.60"))) ("TEXT" "\r\n\t"))) ("TEXT" "\r\n")))) < The {TEXT} elements containing only whitespace make the output very confusing. As the database in {example.xml} only contains data, we can suppress whitespace, empty attribute lists and comments with option {(+ 1 2 4)}: .Filtering whitespace TEXT, COMMENT tags, and empty attribute lists: > (xml-parse (read-file "example.xml") (+ 1 2 4)) ;→ (("ELEMENT" "DATABASE" (("name" "example.xml")) ( ("ELEMENT" "FRUIT" ( ("ELEMENT" "NAME" (("TEXT" "apple"))) ("ELEMENT" "COLOR" (("TEXT" "red"))) ("ELEMENT" "PRICE" (("TEXT" "0.80"))))) ("ELEMENT" "FRUIT" ( ("ELEMENT" "NAME" (("TEXT" "orange"))) ("ELEMENT" "COLOR" (("TEXT" "orange"))) ("ELEMENT" "PRICE" (("TEXT" "1.00"))))) ("ELEMENT" "FRUIT" ( ("ELEMENT" "NAME" (("TEXT" "banana"))) ("ELEMENT" "COLOR" (("TEXT" "yellow"))) ("ELEMENT" "PRICE" (("TEXT" "0.60")))))))) < The resulting output looks much more readable, but it can still be improved by using symbols instead of strings for the tags "FRUIT", "NAME", "COLOR", and "PRICE", as well as by suppressing the XML type tags "ELEMENT" and "TEXT" completely using the |nl-xml-type-tags| directive. .Suppressing XML type tags with |nl-xml-type-tags| and translating string tags into symbol tags: > ;; suppress all XML type tags for TEXT and ELEMENT ;; instead of "CDATA", use cdata and instead of "COMMENT", use !-- (xml-type-tags nil 'cdata '!-- nil) ;; turn on all options for suppressing whitespace and empty ;; attributes, translate tags to symbols (xml-parse (read-file "example.xml") (+ 1 2 8)) ;→ ((DATABASE (("name" "example.xml")) (!-- "This is a database of fruits") (FRUIT (NAME "apple") (COLOR "red") (PRICE "0.80")) (FRUIT (NAME "orange") (COLOR "orange") (PRICE "1.00")) (FRUIT (NAME "banana") (COLOR "yellow") (PRICE "0.60")))) < When tags are translated into symbols by using option {8}, a context can be specified in {sym-context}. If no context is specified, all symbols will be created inside the current context. > (xml-type-tags nil nil nil nil) (xml-parse "Hello World" (+ 1 2 4 8 16) 'CTX) ;→ ((CTX:msg "Hello World")) < Specifying {nil} for the XML type tags TEXT and ELEMENT makes them disappear. At the same time, parentheses of the child node list are removed so that child nodes now appear as members of the list, starting with the tag symbol translated from the string tags "FRUIT", "NAME", etcetera. .Parsing into SXML (S-expressions XML) format: Using |nl-xml-type-tags| to suppress all XML-type tags—along with the option numbers {1}, {2}, {4}, {8}, and {16}—SXML formatted output can be generated: > (xml-type-tags nil nil nil nil) (xml-parse (read-file "example.xml") (+ 1 2 4 8 16)) ;→ ((DATABASE (@ (name "example.xml")) (FRUIT (NAME "apple") (COLOR "red") (PRICE "0.80")) (FRUIT (NAME "orange") (COLOR "orange") (PRICE "1.00")) (FRUIT (NAME "banana") (COLOR "yellow") (PRICE "0.60")))) < Note that using option number {16} causes an {@} (at symbol) to be added to attribute lists. See also the |nl-xml-type-tags| function for further information on XML parsing. .Parsing into a specified context: When parsing XML expressions, XML tags are translated into newLISP symbols. The {sym-context} option specifies the target context for the symbol creation: > (xml-type-tags nil nil nil nil) (xml-parse (read-file "example.xml") (+ 1 2 4 8 16) 'CTX) ;→((CTX:DATABASE (@ (CTX:name "example.xml")) (CTX:FRUIT (CTX:NAME "apple") (CTX:COLOR "red") (CTX:PRICE "0.80")) (CTX:FRUIT (CTX:NAME "orange") (CTX:COLOR "orange") (CTX:PRICE "1.00")) (CTX:FRUIT (CTX:NAME "banana") (CTX:COLOR "yellow") (CTX:PRICE "0.60")))) < If the context does not exist, it will be created. If it exists, the quote can be omitted or the context can be referred to by a variable. .Using a call back function: Normally, |nl-xml-parse| will not return until all parsing has finished. Using the {func-callback} option, |nl-xml-parse| will call back after each tag closing with the generated S-expression and a start position and length in the source XML: > ;; demo callback feature (define (xml-callback s-expr start size) (if (or (= (s-expr 0) 'NAME) (= (s-expr 0) 'COLOR) (= (s-expr 0) 'PRICE)) (begin (print "parsed expression:" s-expr) (println ", source:" (start size example-xml)) ) ) ) (xml-type-tags nil 'cdata '!-- nil) (xml-parse (read-file "example.xml") (+ 1 2 8) MAIN xml-callback) < The following output will be generated by the callback function {xml-callback}: > parsed expression:(NAME "apple"), source:apple parsed expression:(COLOR "red"), source:red parsed expression:(PRICE "0.80"), source:0.80 parsed expression:(NAME "orange"), source:orange parsed expression:(COLOR "orange"), source:orange parsed expression:(PRICE "1.00"), source:1.00 parsed expression:(NAME "banana"), source:banana parsed expression:(COLOR "yellow"), source:yellow parsed expression:(PRICE "0.60"), source:0.60 < The example callback handler function filters the tags of interest and processes them as they occur. *newlisp-function-xml-type-tags* *nl-xml-type-tags* FUNCTION: xml-type-tags~ {syntax:} (xml-type-tags [{exp-text-tag} {exp-cdata-tag} {exp-comment-tag} {exp-element-tags}]) Can suppress completely or replace the XML type tags "TEXT", "CDATA", "COMMENT", and "ELEMENT" with something else specified in the parameters. Note that |nl-xml-type-tags| only suppresses or translates the tags themselves but does not suppress or modify the tagged information. The latter would be done using option numbers in |nl-xml-parse|. Using |nl-xml-type-tags| without arguments returns the current type tags: > (xml-type-tags) ;→ ("TEXT" "CDATA" "COMMENT" "ELEMENT") (xml-type-tags nil 'cdata '!-- nil) < The first example just shows the currently used type tags. The second example specifies suppression of the "TEXT" and "ELEMENT" tags and shows {cdata} and {!--} instead of "CDATA" and "COMMENT". *newlisp-function-zero?* *nl-zero?* FUNCTION: zero?~ {syntax:} (zero? {exp}) Checks the evaluation of {exp} to see if it equals {0} (zero). > (set 'value 1.2) (set 'var 0) (zero? value) ;→ nil (zero? var) ;→ true (map zero? '(0 0.0 3.4 4)) ;→ (true true nil nil) < |nl-zero?| will return {nil} on data types other than numbers. // vim: set tw=72 cms=//%s :