!
+-*/%
Ab
Ap
As
Ba
Ca
Cl
Co
Cu
De
Di
Do
En
Ex
Fi
Fl
Ga
Gl
In
La
Li
Ma
Mu
Net
New
Nt
Pa
Pr
Ra
Rea
Reg
Sea
Seq
Sl
St
Sy
Ti
Tr
Ut
Wr
newLISP focuses on the core components of Lisp: lists, symbols, and lambda expressions. To these, newLISP adds arrays, implicit indexing on lists and arrays, and dynamic and lexical scoping. Lexical scoping is implemented using separate namespaces called contexts.
The result is an easier-to-learn Lisp that is even smaller than most Scheme implementations, but which still has about 350 built-in functions. Approximately 200k in size, newLISP is built for high portability using only the most common Unix system C-libraries. It loads quickly and has a small memory footprint. newLISP is as fast or faster than other popular scripting languages and uses very few resources.
newLISP is dynamically scoped inside lexically separated contexts (namespaces). Contexts can be used to create isolated protected expansion packages, functions with memory and to write object-oriented programs.
Both built-in and user-defined functions, along with variables, share the same namespace and are manipulated by the same functions. Lambda expressions and user-defined functions can be handled like any other list expression.
Contexts (namespaces) in newLISP facilitate the development of larger applications comprising independently developed modules with their own separate namespaces. They can be copied, dynamically assigned to variables, and passed by reference to functions as arguments. In this way, contexts can serve as dynamically created objects that package symbols and methods. Lexical separation of namespaces also enables the definition of statically scoped functions.
newLISP's efficient red-black tree implementation can handle millions of symbols without degrading performance. Contexts can hold symbol-value pairs, allowing them to be used as hash-tables. Functions are also available to iteratively access symbols inside contexts.
newLISP allocates and reclaims memory automatically, without using traditional asynchronous garbage collection (except under error conditions). All objects — except for contexts, built-in primitives, and symbols — are passed by value and are referenced only once. When objects are no longer referenced, their memory is automatically deallocated. This results in predictable processing times without the pauses found in traditional garbage collection. newLISP's unique automatic memory management makes it the fastest interactive Lisp available.
Many of newLISP's built-in functions are polymorphic and accept a variety of data types and optional parameters. This greatly reduces the number of functions and syntactic forms it is necessary to learn and implement. High-level functions are available for distributed computing, parallel processing, financial math, statistics, and AI.
newLISP has functions to modify, insert, or delete elements inside complex nested lists or multi-dimensional array structures.
Because strings can contain null characters in newLISP, they can be used to process binary data.
newLISP can also be extended with a shared library interface to import functions that access data in foreign binary data structures. The distribution contains a module for importing popular database APIs.
newLISP's HTTP, TCP/IP, and UDP socket interfaces make it easy to write distributed networked applications. Its built-in XML interface, along with its text-processing features — Perl Compatible Regular Expressions (PCRE) and text-parsing functions — make newLISP a useful tool for CGI processing. The source distribution includes examples of HTML forms processing. newLISP can be run a as a CGI capable web server using its built-in http mode option.
newLISP has built-in support for distributed processing on networks and parallel processing on the same CPU with one or more processing cores.
The source distribution can be compiled for Linux, BSDs, Mac OS X/Darwin, Solaris, and Win32. On 64-bit Linux, Mac OS X, and True64Unix, newLISP can be compiled as a 64-bit LP64 application for full 64-bit memory addressing.
newLISP-GS comprises a graphical user interface (GUI) and library server. The GUI front-end is written in newLISP, whereas the library server is Java based and uses the standard Java runtime environment installed on all Windows and Mac OS X platforms. Applications built with newLISP-GS can have the host operating system's native look and feel. Interfaces to GTK, Tcl/Tk and OpenGL graphics libraries are also available.
newLISP and Java are available for most operating systems. This makes newLISP-GS a platform-independent solution for writing GUI applications.
For more information on newLISP-GS, see newLISP-GS.
newLISP and newLISP-GS are licensed under version 3 of the GPL (General Public License). The newLISP documentation as well as other documentation packaged with newLISP are licensed under the GNU Free Documentation License.
The function swap has a new syntax since 10.0.3. Any two places referenced by a symbol, an indexed expression or an association reference using assoc or lookup can be swapped. Before this was possible only with symbols. The old syntax using three parameters has been removed in version 10.0.5.
The functions error-number and error-text have been replaced by the function last-error which returns the error number and text together in a list. This is consisten with the behavior of the other two error reporting functions net-error and sys-error.
When starting newLISP from the command-line several switches and options and source files can be specified. Executing:
newlisp -h
in a command shell will produce the following summary of options and switches:
-h this help -n no init (must be first) -s <stacksize> -m <max-mem-megabyte> -e <quoted lisp expression> -l <path-file> log connections -L <path-file> log all -w <working-directory> -c no prompts, HTTP -C force prompts -t <microsec-timeout> -p <port-number> -d <port-number> -http HTTP only
Before or after the command-line switches, files to load and execute can be specified. If a newLISP executable program is followed by parameters the program must finish with and (exit) statement, else newLISP will take command-line parameters as additional newLISP scripts to be loaded and executed.
On Linux and other Unix systems, a newlisp man page can be found:
man newlisp
This will display a man page in the Linux/Unix shell.
newLISP will load and execute files specified on the command-line. Files are specified with either their pathname or a file:// URL on the local file system or with a http:// URL on remote file systems running an HTTP server. That HTTP server can be newLISP running in HTTP server mode.
newlisp aprog.lsp bprog.lsp prog.lsp newlisp http://newlisp.org/example.lsp newlisp file:///usr/home/newlisp/demo.lsp
This option suppresses loading of any present initialization file init.lsp or .init.lsp. In order to work, this must be the first option specified:
newlisp -n
More about initialization files.
newlisp -s 4000 newlisp -s 100000 aprog bprog newlisp -s 6000 myprog newlisp -s 6000 http://asite.com/example.lsp
The above examples show starting newLISP with different stack sizes using the -s option, as well as loading one or more newLISP source files and loading files specified by an URL. When no stack size is specified, the stack defaults to 2048. Per stack position about 80 bytes of memory are preallocated.
newlisp -m 128
This example limits newLISP cell memory to 128 megabytes. In 32-bit newLISP, each Lisp cell consumes 16 bytes, so the argument 128 would represent a maximum of 8,388,608 newLISP cells. This information is returned by sys-info as the list's second element. Although Lisp cell memory is not the only memory consumed by newLISP, it is a good estimate of overall dynamic memory usage.
Small pieces of newLISP code can be executed directly from the command-line:
newlisp -e "(+ 3 4)" → 7 ; On Win32 and Unix newlisp -e '(append "abc" "def")' → "abcdef" ; On Unix
The expression enclosed in quotation marks is evaluated, and the result is printed to standard out (STDOUT). In most Unix system shells, single quotes can also be used as command string delimiters. Note that there is a space between -e and the quoted command string.
In any mode, newLISP can write a log when started with the -l or -L option. Depending on the mode newLISP is running, different output is written to the log file. Both options always must specify the path of a log-file. The path may be a relative path and can be either attached or detached to the -l or -L option. The file must exist.
newlisp -l./logfile.txt -c newlisp -L /usr/home/www/log.txt -http -w /usr/home/www/htpdocs
The following table shows the items logged in different situations:
logging mode | command-line and net-eval with -c | HTTP server with -http |
---|---|---|
newlisp -l | log only input and network connections | log only network connections |
newlisp -L | log also newLISP output (w/o prompts) | log also HTTP requests |
All logging output is written to the file specified after the -l or -L option.
The -w option specifies the initial working directory for newLISP after startup:
newlisp -w /usr/home/newlisp
All file requests without a directory path will now be directed to the path specified with the -w option.
The command-line prompt and initial copyright banner can be suppressed:
newlisp -c
Listen and connection messages are suppressed if logging is not enabled. The -c option is useful when controlling newLISP from other programs; it is mandatory when setting it up as a net-eval server.
The -c option also enables newLISP server nodes to answer HTTP GET, PUT, POST and DELETE requests, as well as perform CGI processing. Using the -c option, together with the -w and -d options, newLISP can serve as a standalone httpd webserver:
newlisp -c -d 8080 -w /usr/home/www
When running newLISP as a inetd or xinetd enabled server on Unix machines, use:
newlisp -c -w /usr/home/www
In -c mode, newLISP processes command-line requests as well as HTTP and net-eval requests. Running newLISP in this mode is only recommended on a machine behind a firewall. This mode should not be run on machines open and accessible through the Internet. To suppress the processing of net-eval and command-line–like requests, use the safer -http option.
A capital C forces prompts when running newLISP in pipe I/O mode inside the Emacs editor:
newlisp -C
To suppress console output from return values from evaluations, use silent.
newlisp some.lsp -p 9090
This example shows how newLISP can listen for commands on a TCP/IP socket connection. In this case, standard I/O is redirected to the port specified with the -p option. some.lsp is an optional file loaded during startup, before listening for a connection begins.
The -p option is mainly used to control newLISP from another application, such as a newLISP GUI front-end or a program written in another language. As soon as the controlling client closes the connection, newLISP will exit.
A telnet application can be used to test running newLISP as a server. First enter:
newlisp -p 4711 &
The & indicates to a Unix shell to run the process in the background. On Windows, start the server process without the & in the foreground and open a second command window for the telnet application. Now connect with a telnet:
telnet localhost 4711
If connected, the newLISP sign-on banner and prompt appear. Instead of 4711, any other port number could be used.
When the client application closes the connection, newLISP will exit, too.
When the connection to the client is closed in -p mode, newLISP exits. To avoid this, use the -d option instead of the -p option:
newlisp -d 4711 &
This works like the -p option, but newLISP does not exit after a connection closes. Instead, it stays in memory, listening for a new connection and preserving its state. An exit issued from a client application closes the network connection, and the newLISP daemon remains resident, waiting for a new connection. Any port number could be used in place of 4711.
When running in -p or -d mode, the opening and closing tags [cmd] and [/cmd] must be used to enclose multiline statements. They must each appear on separate lines. This makes it possible to transfer larger portions of code from controlling applications.
The following variant of the -d mode is frequently used in a distributed computing environment, together with net-eval on the client side:
newlisp -c -d 4711 &
The -c spec suppresses prompts, making this mode suitable for receiving requests from the net-eval function.
newLISP server nodes running will also answer HTTP GET, PUT and DELETE requests. This can be used to retrieve and store files with get-url, put-url, delete-url, read-file, write-file and append-file, or to load and save programs using load and save from and to remote server nodes. See the chapters for the -c and -http options for more details.
newLISP can be limited to HTTP processing using the -http option. With this mode, a secure httpd web server daemon can be configured:
newlisp -http -d 8080 -w /usr/home/www
When running newLISP as an inetd or xinetd-enabled server on Unix machines, use:
newlisp -http -w /usr/home/www
To further enhance security and HTTP processing, load a program during startup when using this mode:
newlisp httpd-conf.lsp -http -w /usr/home/www
The file httpd-conf.lsp contains a command-event function configuring a user-defined function to analyze, filter and translate requests. See the reference for this function for a working example.
In the HTTP modes enabled by either -c or -http, the following file types are recognized, and a correctly formatted Content-Type: header is sent back:
file extension | media type |
---|---|
.html | text/html |
.htm | text/htm |
.css | text/css |
.gif | image/gif |
.png | image/png |
.mp3 | audio/mpeg |
.wav | audio/x-wav |
.mpg | video/mpeg |
.mov | video/quicktime |
.avi | video/x-msvideo |
application/pdf | |
.js | application/javascript |
.zip | application/zip |
any other | text/plain |
To serve CGI, HTTP server mode needs a /tmp directory on Unix-like platforms or a C:\tmp directory on Win32. newLISP can process GET, PUT, POST and DELETE requests and create custom response headers. CGI files must have the extension .cgi and have executable permission on UNIX. More information about CGI processing for newLISP server modes can be found in the document Code Patterns in newLISP
Instead of a port, a local domain Unix socket path can be specified in the -d or -p server modes.
newlisp -c -d /tmp/mysocket &
Test the server using another newLISP process:
newlisp -e '(net-eval "/tmp/mysocket" 0 "(symbols)")'
A list of all built-in symbols will be printed to the terminal
This mode will work together with local domain socket modes of net-connect, net-listen, and net-eval. Local domain sockets opened with net-connect and net-listen can be served using net-accept, net-receive, and net-send. Local domain socket connections can be monitored using net-peek and net-select.
Local domain socket connections are much faster than normal TCP/IP network connections and preferred for communications between processes on the same local file system in distributed applications. This mode is not available on Win32.
Specifies a connection timeout when running in -p or
The example specifies a timeout of three seconds.
The inetd server running on virtually all Linux/Unix OSes can function
as a proxy for newLISP. The server accepts TCP/IP or UDP connections and passes
on requests via standard I/O to newLISP. inetd starts a newLISP process
for each client connection. When a client disconnects, the connection is closed
and the newLISP process exits.
inetd and newLISP together can handle multiple connections efficiently
because of newLISP's small memory footprint, fast executable, and short program load
times. When working with net-eval, this mode is preferred
for efficiently handling multiple requests in a distributed computing environment.
Two files must be configured: services and inetd.conf.
Both are ASCII-editable and can usually be found at /etc/services and
/etc/inetd.conf.
Put one of the following lines into inetd.conf:
Instead of root, another user and optional group can be specified.
For details, see the Unix man page for inetd.
The following line is put into the services file:
On Mac OS X and some Unix systems, xinetd can be used instead of
inetd. Save the following to a file named net-eval in the
/etc/xinetd.d/ directory:
For security reasons, root should be changed to a different user
and file permissions of the www document directory adjusted accordingly.
The only_from spec can be left out to permit remote access.
See the man pages for xinetd and xinetd.conf
for other configuration options.
After configuring the daemon, inetd or
xinetd must be restarted to
allow the new or changed configuration files to be read:
Replace <pid> with the process ID of the
running xinetd process.
A number or network protocol other than 4711 or TCP can be specified.
newLISP handles everything as if the input were being entered
on a newLISP command-line without a prompt. To test the
inetd setup, the telnet program can be used:
newLISP expressions can now be entered, and inetd will
automatically handle the startup and communications of a newLISP
process. Multiline expressions can be entered by bracketing them
with [cmd] and [/cmd] tags, each on separate lines.
newLISP server nodes answer HTTP GET and PUT requests.
This can be used to retrieve and store files
with get-url, put-url,
read-file, write-file
and append-file,
or to load and save programs using load
and save from and to remote server nodes. During startup, newLISP sets the environment variable NEWLISPDIR, if it is
not set already. On Linux, BSDs, Mac OS X and other Unixes the variable is set to
/usr/local/share/newlisp. On Win32 the variable is set to
%PROGRAMFILES%/newlisp. The environment variable NEWLISPDIR is useful when loading files installed with
newLISP: A predefined function module can be used to shorten
the second statement loading from the modules/
directory: Before loading any files specified on the command-line, and before the banner
and prompt are shown. newLISP tries to load a file .init.lsp from
the home directory of the user starting newLISP. On Mac OS X, Linux and other
Unix the home directory is found in the HOME environment variable.
On Win32 the is directory name is contained in the USERPROFILE or
DOCUMENT_ROOT environment variable. If a .init.lsp cannot be found in the home directory newLISP tries
to load the file init.lsp from the directory found in the
environment variable NEWLISPDIR.
When newLISP is run as a shared libraryi, an initialization file is looked
for in the environment variable NEWLISPLIB_INIT. The full path-name
of the initialization file must be specified. If NEWLISPLIB_INIT is
not defined, no initialization file will be loaded by the library module. Although newLISP does not require init.lsp to run, it is convenient for
defining functions and system-wide variables. Note that neither one of the initialization files init.lsp nor
.init.lsp is loaded during startup of linked programs.
The directory /usr/local/share/newlisp/modules contains modules with useful functions
POP3 mail, etc. The directory /usr/local/share/newlisp/guiserver contains sample programs
for writing GUI applications with newLISP-GS.
The directory /usr/share/doc/newlisp/ contains documentation in HTML format.
On Win32 systems, all files are installed in the default directory %PROGRAMFILES%\newlisp.
PROGRAMFILES is a Win32 environment variable that resolves to
C:\Program files\newlisp\ in English language installations. The subdirectories
%PROGRAMFILES%\newlisp\modules and %PROGRAMFILES%\newlisp\guiserver
contain modules for interfacing to external libraries and sample programs written for
newLISP-GS. newLISP can be compiled as a Unix shared library called newlisp.so on Linux
and BSDs. A newLISP shared library can be used like any other Unix shared library. To use newlisp.so or newlisp.dylib,
import the function newlispEvalStr. Like
eval-string, this function
takes a string containing a newLISP expression and
stores the result in a string address. The result can
be converted using get-string.
The returned string is formatted like output from a
command-line session. It contains terminating line-feed
characters, but without the prompt strings.
The first example shows how newlisp.so is imported from newLISP itself.
The second example shows how to import newlisp.so into a program written in C: This program will accept quoted newLISP expressions and print the evaluated results. When calling newlisp.so's function newlispEvalStr,
output normally directed to the console (e.g., return values or
print statements) is returned in the form of an
integer string pointer. The output can be accessed by passing this
pointer to the get-string function. To silence the output
from return values, use the silent function. On the Win32 platforms, newLISP can be compiled as a DLL (Dynamic Link Library).
In this way, newLISP functions can be made available to other programs
(e.g., MS Excel, Visual Basic, Borland Delphi, or even newLISP itself). To access the functionality of the DLL, use newlispEvalStr, which takes
a string containing a valid newLISP expression and returns a string of the result:
The above example shows the loading of a DLL using newLISP.
The get-string function is necessary
to access the string being returned. Other applications running
on Win32 allow the returned data type to be declared when importing the function.
When using newLISP as a library module, output normally directed to the
console — like print statements or
return values — will be returned in a string pointed to
by the call to newlispEvalStr. To silence the output
from return values, use the silent directive. The following is a short introduction to newLISP statement evaluation
and the role of integer and floating point arithmetic in newLISP. Top-level expressions are evaluated when using the
load function or when entering
expressions in console mode on the command-line. As
shown in the following snippet from an interactive
session, multiline expressions can be entered by
enclosing them between [cmd] and [/cmd] tags:
Each [cmd] and [/cmd] tag is entered
on a separate line. This mode is useful for pasting
multiline code into the interactive console.
newLISP functions and operators accept integer and
floating point numbers, converting them into the
needed format. For example, a bit-manipulating
operator converts a floating point number into an
integer by omitting the fractional part. In the
same fashion, a trigonometric function will
internally convert an integer into a floating
point number before performing its calculation.
The symbol operators
(+ - * / %
$ ~ | ^ <<
>>) return values of type integer.
Functions and operators named with a word instead of a symbol
(e.g., add rather than +) return floating
point numbers. Integer operators truncate floating point
numbers to integers, discarding the fractional parts. newLISP has two types of basic arithmetic operators:
integer (+ - * /)
and floating point (add sub mul div).
The arithmetic functions convert their arguments into types compatible
with the function's own type: integer function arguments into integers,
floating point function arguments into floating points. To make newLISP
behave more like other scripting languages, the integer operators
+, -, *, and / can be redefined to
perform the floating point operators add, sub,
mul, and div:
Now the common arithmetic operators +, -, *,
and / accept both integer and floating point numbers and return
floating point results. Note that the looping variables in dotimes and
for, as well as the result of
sequence, use floating point numbers for their values.
Care must be taken when importing from libraries that use functions
expecting integers. After redefining +, -, *, and /,
a double floating point number may be unintentionally passed to an
imported function instead of an integer. In this case, floating point
numbers can be converted into integers by using the function
int. Likewise, integers can be transformed into
floating point numbers using the float function: Some of the modules shipping with newLISP are written assuming the
default implementations of +, -, *,
and /. This gives imported library functions maximum
speed when performing address calculations. The newLISP preference is to leave +, -, *,
and / defined as integer operators and use
add, sub, mul, and div
when explicitly required. Since version 8.9.7, integer operations
in newLISP are 64 bit operations, whereas 64 bit double floating
point numbers offer only 52 bits of resolution in the integer part of the number.
Evaluate expressions by entering and editing them on the command-line.
More complicated programs can be entered using editors like Emacs and VI,
which have modes to show matching parentheses while typing. Load a saved
file back into a console session by using the load function.
A line comment begins with a ; (semicolon) or a # (number sign)
and extends to the end of the line. newLISP ignores this line during evaluation.
The # is useful when using newLISP as a scripting language in Linux/Unix
environments, where the # is commonly used as a line comment in scripts and shells.
When evaluation occurs from the command-line, the result is printed to
the console window. The following examples can be entered on the command-line by typing the code to
the left of the → symbol. The result that
appears on the next line should match the code to the right of the
→ symbol. nil and true are Boolean data types that
evaluate to themselves: Integers and floating point numbers evaluate to themselves:
Integers are 64-bit numbers (including the sign bit, 32-bit before version 8.9.7).
Valid integers are numbers between -9,223,372,036,854,775,808 and
+9,223,372,036,854,775,807.
Larger numbers converted from floating point numbers are truncated
to one of the two limits. Integers internal to newLISP, which
are limited to 32-bit numbers, overflow to either +2,147,483,647 or
-2,147,483,648. Floating point numbers are IEEE 754 64-bit doubles.
Unsigned numbers up to 18,446,744,073,709,551,615 can be displayed
using special formatting characters for format.
Strings may contain null characters and can have different
delimiters. They evaluate to themselves. Strings delimited by " (double quotes) will also process
the following characters escaped with a \ (backslash):
Quoted strings cannot exceed 2,048 characters. Longer strings
should use the [text] and [/text] tag delimiters.
newLISP automatically uses these tags for string output longer than 2,048 characters.
The { (left curly bracket), } (right curly bracket),
and [text], [/text] delimiters do not perform escape character processing. Lambda and lambda-macro expressions evaluate to themselves: Symbols evaluate to their contents: Contexts evaluate to themselves: Built-in functions also evaluate to themselves: In the above example, the number between the < > (angle brackets)
is the hexadecimal memory address (machine-dependent) of the
add function. It is displayed when printing a built-in primitive. Quoted expressions lose one ' (single quote) when evaluated:
A single quote is often used to protect an expression
from evaluation (e.g., when referring to the symbol itself instead
of its contents or to a list representing data instead of a function). Lists are evaluated by first evaluating the first list element
before the rest of the expression (as in Scheme). The result of the
evaluation is applied to the remaining elements in the list and must
be one of the following: a lambda expression, lambda-macro
expression, or primitive (built-in) function. or For a user-defined lambda expression, newLISP evaluates the
arguments from left to right and binds the results to the
parameters (also from left to right), before using the
results in the body of the expression. Like Scheme, newLISP evaluates the functor
(function object) part of an expression before applying
the result to its arguments. For example: Depending on the value of X, this expression applies the *
(product) or + (sum) function to X and Y.
Because their arguments are not evaluated, lambda-macro
expressions are useful for extending the syntax of the language. Most
built-in functions evaluate their arguments from left to right (as needed)
when executed. Some exceptions to this rule are indicated in the reference
section of this manual. Lisp functions that do not evaluate all or some of
their arguments are called special forms. Arrays evaluate to themselves: Shell commands: If an ! (exclamation mark)
is entered as the first character on the command-line followed by a shell
command, the command will be executed. For example, !ls on Unix or
!dir on Win32 will display a listing of the present working directory.
No spaces are permitted between the ! and the shell command. Symbols
beginning with an ! are still allowed inside expressions or on the
command-line when preceded by a space. Note: This mode only works when running
in the shell and does not work when controlling newLISP from another
application.
To exit the newLISP shell on Linux/Unix, press Ctrl-D; on Win32,
type (exit) or Ctrl-C, then the x key.
Use the exec function to access shell commands from
other applications or to pass results back to newLISP.
Lambda expressions in newLISP evaluate to themselves and can be treated
just like regular lists: Note: No ' is necessary before the lambda expression because
lambda expressions evaluate to themselves in newLISP.
The second line uses the keyword fn, an alternative syntax first suggested
by Paul Graham for his Arc language project.
A lambda expression is a lambda list, a subtype of list, and its
arguments can associate from left to right or right to left. When using
append, for example, the arguments associate from left to right:
cons, on the other hand, associates the arguments from right to left:
Note that the lambda keyword is not a symbol in a list, but a
designator of a special type of list: the lambda list.
Lambda expressions can be mapped or applied onto arguments to work as user-defined, anonymous functions:
A lambda expression can be assigned to a symbol, which in turn can be
used as a function: The define function is just a shorter way of
assigning a lambda expression to a symbol: In the above example, the expressions inside the lambda list are still
accessible within double: A lambda list can be manipulated as a first-class object using any function
that operates on lists: All arguments are optional when applying lambda expressions and default to nil
when not supplied by the user. This makes it possible to write functions with
multiple parameter signatures. In newLISP, nil and true represent both the symbols and the
Boolean values false and true. Depending on their context,
nil and true are treated differently. The following examples use
nil, but they can be applied to true by simply reversing the logic.
Evaluation of nil yields a Boolean false and is treated as such inside
flow control expressions such as if, unless, while,
until, and not. Likewise, evaluating true yields true. In the above example, nil represents a symbol. In the following example,
nil and true are evaluated and represent Boolean values: In newLISP, nil and the empty list () are not the same as in
some other Lisps. Only in conditional expressions are they treated as a Boolean
false, as in and, or, if, while,
unless, until, and cond. Evaluation of (cons 'x '()) yields (x), but (cons 'x nil)
yields (x nil) because nil is treated as a Boolean value when
evaluated not as an empty list. The cons of two atoms in newLISP
does not yield a dotted pair, but rather a two-element list. The predicate
atom? is true for nil, but false for the empty list. The empty
list in newLISP is only an empty list and not equal to nil. A list in newLISP is a newLISP cell of type list. It acts like a container for the
linked list of elements making up the list cell's contents. There is no
dotted pair in newLISP because the cdr (tail) part of a Lisp
cell always points to another Lisp cell and never to a basic data type, such as a
number or a symbol. Only the car (head) part may contain a basic data type.
Early Lisp implementations used car and cdr for the names
head and tail. newLISP's arrays enable fast element access within large lists. New arrays
can be constructed and initialized with the contents of an existing list
using the function array. Lists can be converted into
arrays, and vice versa. Most of the same functions used for modifying and
accessing lists can be applied to arrays, as well. Arrays can hold any type
of data or combination thereof. In particular, the following functions can be used for creating, accessing,
and modifying arrays:
newLISP represents multidimensional arrays with an array of arrays
(i.e., the elements of the array are themselves arrays).
When used interactively, newLISP prints and displays arrays as lists,
with no way of distinguishing between them. Use the source or save
functions to serialize arrays (or the variables containing them).
The array statement is included as part of
the definition when serializing arrays. Like lists, negative indices can be used to enumerate the elements
of an array, starting from the last element. An out-of-bounds index will cause an error message on an array or list. Arrays can be non-rectangular, but they are made rectangular
during serialization when using source or save.
The array function always constructs arrays in rectangular form. The matrix functions det, transpose,
multiply, and invert can be used on
matrices built with nested lists or arrays built with array. For more details, see array, array?,
and array-list in the reference section of this manual. Some functions take array, list, or string elements (characters)
specified by one or more int-index (integer index). The positive
indices run 0, 1, …, N-2, N-1, where N is the
number of elements in the list. If int-index is negative, the sequence
is -N, -N+1, …, -2, -1. Adding N to the negative
index of an element yields the positive index. Unless a function does
otherwise, an index greater than N-1 or less then -N causes an
out-of-bounds error in lists and arrays. Implicit indexing can be used instead of nth to
retrieve the elements of a list or array or the characters of a string: Indices may also be supplied from a list. In this way, implicit
indexing works together with functions that take or produce index
vectors, such as push, pop,
ref and ref-all. Note that implicit indexing is not breaking newLISP
syntax rules but is merely an expansion of existing rules to
other data types in the functor position of an s-expression.
In original Lisp, the first element in an s-expression list
is applied as a function to the rest elements as arguments. In newLISP, a list
in the functor position of an s-expression assumes self-indexing functionality
using the index arguments following it. Implicit indexing is faster than the explicit forms, but the explicit forms
may be more readable depending on context. Note that in the UTF-8–enabled version of newLISP, implicit indexing
of strings or using the nth function work on character rather
than single-byte boundaries. The default functor is a functor inside a context with the same
name as the context itself. See The context
default function chapter. A default functor can be used together with
implicit indexing to serve as a mechanism for referencing lists: In this example, aList references MyList:MyList,
not a copy of it. For more information about contexts, see
Programming with contexts. The indexed default functor can also be used with setf as shown
in the following example: Implicit forms of rest and slice
can be created by prepending a list with one or two numbers for offset and length.
If the length is negative it counts from the end of the list or string: The functions rest, first
and last work on multi-byte character boundaries
in UTF-8 enabled versions of newLISP. But the implicit indexing forms for
slicing and resting will always work on single-byte boundaries and can be used for
binary content. Ofset and length results from the regular expression functions
find and regex are also in single-byte
counts and can be further processed with slice or it's
implicit form. Parts in lists, arrays and strings referenced by indices can be modified using
setf: Note that only full elements or nested lists or arrays can be changed this way.
Slices or rest parts of lists or arrays as used in implicit resting or slicing cannot
be substituted at once using setf, but would have to be substituted
element by element. In strings only one character can be replaced at a time, but
that character can be replaced by a multi-chracacter string. Most of the primitives in newLISP are nondestructive (no side effects)
and leave existing objects untouched, although they may create new ones. There
are a few destructive functions, however, that do change the contents of a
variable, list, array, or string. Note that the last two functions, write-buffer
and write-line, are destructive in diffferent ways.
Depending on the syntactic form used, either a string buffer or a disk file
is modified. Some destructive functions can be made non-destructive by wrapping the target
object into the copy function. The list in aList is left unchanged. newLISP uses dynamic scoping inside contexts. A context is a lexically
closed namespace. In this way, parts of a newLISP program can live in different
namespaces taking advantage of lexical scoping.
When the parameter symbols of a lambda expression are bound to its arguments,
the old bindings are pushed onto a stack. newLISP automatically restores the
original variable bindings when leaving the lambda function.
The following example illustrates the dynamic scoping mechanism.
The text in bold is the output from newLISP: The variable x is first set to 1. But when (g 0)
is called, x is bound to 0 and x is reported
by (f) as 0 during execution of (g 0). After
execution of (g 0), the call to (f) will report x as 1 again. This is different from the lexical scoping mechanisms found in
languages like C or Java, where the binding of local parameters occurs inside
the function only. In lexically scoped languages like C, (f) would
always print the global bindings of the symbol x with 1.
Be aware that passing quoted symbols to a user-defined function causes a
name clash if the same variable name is used as a function parameter:
Because the global y shares the same symbol as the function's second parameter,
inc-symbol returns 246 (123 + 123), leaving the global y unaffected.
Dynamic scoping's variable capture can be a disadvantage when passing symbol
references to user-defined functions. newLISP offers several methods to avoid variable
capture.
Contexts should be used to group related functions when creating interfaces
or function libraries. This surrounds the functions with a lexical "fence",
thus avoiding variable name clashes with the calling functions.
newLISP uses contexts for different forms of lexical scoping. See the
chapters Contexts and
Programming with contexts, as well as
the section default functors for more information.
What follows are methods of interrupting the control flow inside both
loops and the begin expression. The looping functions dolist and
dotimes can take optional conditional expressions to leave the loop
early. catch and throw are a more
general form to break out of a loop body and are also applicable to other
forms or statement blocks. Because newLISP is a functional language, it uses no break or
return statements to exit functions or iterations. Instead, a
block or function can be exited at any point using the functions
catch and throw: Breaking out of loops works in a similar way: The example shows how an iteration can be exited before executing N times. Multiple points of return can be coded using throw: If condition-A is true, x will be returned from
the catch expression; if condition-B is true, the
value returned is y. Otherwise, the result from foo5
will be used as the return value. As an alternative to catch, the throw-error
function can be used to catch errors caused by faulty code or user-initiated exceptions. Using the logical functions and and
or, blocks of statements can be built
that are exited depending on the Boolean result of the enclosed functions: The and expression will return as soon as one of the
block's functions returns nil or an () (empty list).
If none of the preceding functions causes an exit from the block, the
result of the last function is returned. or can be used in a similar fashion:
The result of the or expression will be the first function
that returns a value which is not nil or ().
In newLISP, symbols can be separated into namespaces called contexts.
Each context has a private symbol table separate from all other contexts. Symbols
known in one context are unknown in others, so the same name may be used
in different contexts without conflict. Contexts are used to build modules of isolated variable and function definitions.
They can also be copied and dynamically assigned to variables or passed as arguments.
Because contexts in newLISP have lexically separated namespaces, they allow programming
with lexical scoping and software object styles of programming. Contexts are identified by symbols that are part of the root or MAIN
context. Although context symbols are uppercased in this chapter, lowercase symbols
may also be used. In addition to context names, MAIN contains the symbols for built-in
functions and special symbols such as true and nil. The MAIN
context is created automatically each time newLISP is run. To see all the symbols
in MAIN, enter the following expression after starting newLISP: The following rules should simplify the process of understanding contexts by
identifying to which context the created symbols are being assigned. newLISP first parses and translates each top level expression. The symbols
are created during this phase. After the expression is translated, it gets
evaluated. A symbol is created when newLISP first sees it, when calling the
load, sym,
or eval-string functions. When newLISP reads
a source file, symbols are created before evaluation occurs. When an unknown symbol is encountered during code translation,
a search for its definition begins inside the current context.
Failing that, the search continues inside MAIN for a
built-in function, context, or global symbol. If no definition
is found, the symbol is created locally inside the current context. Once a symbol is created and assigned to a specific context,
it will belong to that context permanently. When a user-defined function is evaluated, the context is switched to the parent
context of the symbol it is called with. Contexts can be created either by using the context
function or via implicit creation. The first method is used when writing larger
portions of code belonging the same context: If the context does not exist yet, the context symbol must be quoted.
If the symbol is not quoted, newLISP assumes the symbol is a variable
holding the symbol of the context to create. Because a context evaluates
to itself, existing contexts like MAIN do not require quoting. When newLISP reads the above code, it will read, then evaluate the first
statement: (context 'FOO). This causes newLISP to switch the namespace
to FOO and the following symbols var, x, y and z
will all be created in the FOO context when reading and evaluating the remaining
expressions. To refer to var or func from anywhere else outside the
FOO namespace they need to be prefixed with the context name: The symbols function is used to show all symbols
belonging to a context" A context is implicitly created when referring to one that does not yet exist.
Unlike the context function, the context is not switched. The following
statements are all executed inside the MAIN context: Note that only the symbols prefixed with their context name will be part
of the context: When above code is loaded in MAIN only foo will be part of
ACTX. The symbols x and y will still be part
of MAIN. When loading source files on the command-line with load,
or when executing the functions eval-string or
sym, the context function tells newLISP where to
put all of the symbols and definitions: The draw-triangle and draw-circle functions — along
with their x, y, and z parameters — are now
part of the GRAPH context. These symbols are known only to GRAPH.
To call these functions from another context, prefix them with GRAPH: The last statement shows how the runtime context has changed to
GRAPH (function foo's context). A symbol's name and context are used when comparing symbols from different
contexts. The name function can be used to extract the name
part from a fully qualified symbol. Note: The symbols are quoted with a ' (single quote) because we are interested in
the symbol itself, not in the contents of the symbol. By default, only built-in functions and symbols like nil and
true are visible inside contexts other than MAIN. To make a symbol
visible to every context, use the global function: Without the global statement, the second aVar would have
returned nil instead of 123. If FOO had a previously
defined symbol (aVar in this example) that symbol's value
— and not the global's — would be returned instead. Note that only
symbols from the MAIN context can be made global. Once it is made visible to contexts through the global function,
a symbol cannot be hidden from them again. By using the constant function, symbols can be both set
and protected from change at the same time:
A symbol needing to be both a constant and a global can be defined simultaneously:
In the current context, symbols protected by constant can be overwritten
by using the constant function again. This protects the symbols from
being overwritten by code in other contexts. Global and built-in function symbols can be overwritten inside a
context by prefixing them with their own context symbol: In this example, the built-in function new is overwritten by
Account:new, a different function that is private to the Account context.
Variables can be used to refer to contexts:
Context variables ate useful when writing functions, which need to switch
contexts or use contexts which do not exist yet:
The following shows a terminal session using above definitions. The program
output is shown in bold-face: The same one function update can display different behavior depending
on the context passed as first parameter. The sequence in which contexts are created or loaded can lead to unexpected
results. Enter the following code into a file called demo: Now load the file into the newlisp shell: Loading the file causes an error message for FOO, but not
for ABC. When the first context FOO is loaded, the
context ABC does not exist yet, so a local variable FOO:ABC
gets created. When ABC loads, FOO already exists as a global
protected symbol and will be correctly flagged as protected. FOO could still be used as a local variable in the ABC
context by explicitly prefixing it, as in ABC:FOO. The following pattern can be applied to avoid unexpected behavior when
loading contexts being used as modules to build larger applications: Always load the modules required by a context before
the module's context statement. Always finish by switching
back to the MAIN context, where the module's functions and
values can be safely accessed. Contexts in newLISP are mainly used for partitioning source into
modules. Because each module lives in a different namespace, modules
are lexically separated and the names of symbols cannot clash with
identical names in other modules. The modules, which are
part of the newLISP distribution, are a good example of how to put related
functions into a module file, and how to document modules using
the newLISPdoc utility. For best programming practice, a file should only contain one module and
the filename should be similar if not identical to the context name used: The example shows a good practice of predefining variables, which are global
inside the namespace, and defining as constants the variables that will not change. If a file contains more than one context, then the end of the context
should be marked with a switch back to MAIN: Contexts are frequently uses as data containers, e.g. for hash-like dictionaries
and configuration data: Loading the Config namespace will now load a whole variable set into
memory at once: In a similar fashion a whole data set can be saved: Read more about this in the section Serializing contexts. Module files are loaded using the load function.
If a programming project contains numerous modules that refer
to each other, they should be pre-declared to avoid problems due to context forward
references that can occur before the loading of that context. When pre-declaring and loading modules as shown in the example, the sequence
of declaration or loading can be neglected. All forward references to variables
and definitions in modules not loaded yet will be translated correctly. Modules not starting with a context switch are always loaded into MAIN
except when the load statement specifies a target context
as the last parameter. The load function can take URLs
to load modules from remote locations, via HTTP. The current context after the load statement will always be
the same as before the load. Serialization makes a software object persistent
by converting it into a character stream,
which is then saved to a file or string in memory.
In newLISP, anything referenced by a symbol can be serialized to a file
by using the save function.
Like other symbols, contexts are saved just by using their names:
For details, see the functions save (mentioned above)
and source (for serializing to a newLISP string).
A default functor or default function
is a symbol or user-defined function or macro
with the same name as its namespace. When the context is used
as the name of a function or in the functor position of an s-expression,
newLISP executes the default function. If a default function is called from a context other than MAIN,
the context must already exist or be declared with a forward declaration,
which creates the context and the function symbol: Default functions work like global functions,
but they are lexically separate from the context in which they are called. Like a lambda or lambda-macro function, default functions can be used
with map or apply.
A default function can update the lexically isolated static variables
contained inside its namespace: The first time the Gen function is called,
its accumulator is set to the value of the argument.
Each successive call increments Gen's accumulator
by the argument's value. The definition of Gen:Gen shows, how a function is put in its own namespace
without using the surrounding (context 'Gen) and (context MAIN)
statements. In that case only symbols qualified by the namespace prefix will
end up in the Gen context. In the above example the variable
x is still part of MAIN. There are several functions that can be used to place symbols into namespace contexts.
When using dictionaries as simple hash-like collections of variable → value pairs, use the
uninitialized default functor: Either method can be used to make the MyHash dictionary space and default
functor. Creating key-value pairs and retrieving a value is easy: Note that the default functor should not be initialized to any
value other than nil. The default functor works like a dictionary
hash function creating the symbols in the string following it and setting it
to the value if specified. Symbol variables created this way can contain spaces or other characters
normally not allowed in newLISP symbol names: An entry which doesn't exist will return nil: Setting an entry to nil will effectively delete it from
the namespace. An association list can be generated from the contents of the namespace: Entries in the dictionary can also be created from a list: The list can also be used to iterate through the sorted key -> value pairs: Like many built-in functions hash expressions return a reference to their content which
can be modified directly: When setting hash values the anaphoric system variable $it
can be used to refer to the old value when setting the new: Hash values also can be modified using setf: But supplying the value as a second parameter to the hash functions
is shorter to write and faster. Dictionaries can easily be saved to a file and reloaded later: Internally the key strings are created and stored as symbols in the
hash context. All key strings are prepended with an _
underscore character. This protects against overwriting the default symbol and
symbols like set and sym, which are needed when loading
a hash namespace from disk or over HTTP. Note the following
difference: In the first line hash symbols are shown as strings without without the preceding
underscore characters. The second line shows the internal form of the symbols with
prepended underscore characters. For a more detailed introduction to namespaces, see the chapter on
Contexts.
A default functor can also be used to hold data.
If this data contains a list or string, the context name can be used as a reference to
the data: Most of the time, newLISP passes parameters by value copy.
This poses a potential problem when passing large lists or strings
to user-defined functions or macros. Strings and lists, which are packed
in a namespace using default functors, are passed automatically by reference:
Any argument of a built-in function calling for either a list or a string
— but no other data type — can receive data passed by reference.
Any user-defined function can take either normal variables, or can take a context
name for passing a reference to the default functor containing a list or string. Note that on lists with less than about 100 elements or strings of less than
about 50000 characters, the speed difference between reference and value passing is
negligible. But on bigger data objects, differences in both speed and memory usage
between reference and value passing can be significant. Built-in and user-defined functions are suitable for both types of arguments,
but when passing context names, data will be passed by reference. Quoted symbols can also be used to pass data by reference, but this method
has disadvantages: Although this method is simple to understand and use, it poses the potential
problem of variable capture when passing the same symbol as used
as a function parameter: At the beginning of the chapter it was shown how to package data
in a name-space using a default functor. Not only the default
functor but any symbol in context can be used to hold data. The
disadvantage is that the calling function must have knowledge about
the symbol being used:
The function receives the namespace in the variable obj,
but it must have the knowledge that the list to access is contained
in the data symbol of that namespace (context). Any object-oriented programming (OOP) system built in newLISP is based on the following
four principles: Class attributes and methods are stored in the namespace of the object class. The namespace default functor is used to hold the object constructor method. An object is constructed using a list, the first element of which is the
context symbol describing the class of the object. Polymorphism is implemented using the : (colon) operator, which selects the appropriate
class from the object. The following paragraphs are a short introduction to FOOP: Functional Object-Oriented Programming
as designed by Michael Michaels. This description covers only very basic elements.
For more details see the Michael Michaels's FOOP training videos on
newlisp.org or neglook.com.
Class attributes and methods are stored in the namespace of the object class.
No object instance data is stored in this namespace/context. Data variables in
the class namespace only describe the class of objects as a whole but don't contain
any object specific information. A generic FOOP object constructor can be used
as a template for specific object constructors when creating new object classes
with new: The generic FOOP constructor is already built-in, and FOOP
code can start with (new Class ...) statements right away. New classes can only be created in the MAIN context. If creating a
new class while in a different namespace, the new class name should be
prefixed with MAIN: Creating the namespace classes using new reserves the class
name as a context in newLISP and facilitates forward references. At the same time,
a simple constructor is defined for the new class for instantiating new objects.
As a convention, it is recommended to start class names in upper-case to signal that
the name stands for a namespace. In some cases, it may be useful to overwrite the simple constructor, that was
created during class creation, with new: A constructor can also specify defaults: In many cases the constructor as created when using new is sufficient and overwriting
it is not necessary. FOOP represents objects as lists. The first element of the list indicates the
object's kind or class, while the remaining elements contain the data. The following
statements define two objects using any of the constructors defined previously: An object created is identical to the function necessary to create it. Nested objects can be
created in a similar manner: Objects in FOOP not only resemble functions they also resemble associations. The
assoc function can be used to access object data by name: In a similar manner setf together with assoc
can be used to modify object data: The street number has been changed from 123 to 456. Note that in none of the assoc statements Address and Street
need to carry quotes. The same is true in the set statement:
(set 'JohnDoe (Person ...)) for the data part assigned. In both cases we do not
deal with symbols or lists of symbols but rather with contexts and FOOP objects which
evaluate to themselves. Quoting would not make a difference. In newLISP, the colon character : is primarily used to
connect the context symbol with the symbol it is qualifying.
Secondly, the colon function is used in OOP to resolve a function's
application polymorphously. The following code defines two functions called area,
each belonging to a different namespace. Both functions could
have been defined in different modules, but in this case they are
defined in the same file and without bracketing
context statements. Here, only
the symbols rectangle:area and circle:area belong
to different namespaces. The local parameters p, c,
dx, and dy are all part of MAIN,
but this is of no concern. By prefixing the area or move symbol with the : (colon),
we can call these functions for each class of object. Although there is no space
between the colon and the symbol following it, newLISP parses them as distinct entities.
The colon works as a function that processes parameters: In this example, the correct qualified symbol (rectangle:area or
circle:area) is constructed and applied to the object data based on
the symbol following the colon and the context name (the first element of the object list). Note that moving the shapes is done in a functional manner.
Rather than changing the x and y coordinates directly in
myrect and mycircle, newLISP constructs and then reassigns the moved shapes. To write destructive functions using the colon operator, objects have to passed
in a default functor:
newLISP has high-level APIs to control multiple processes on the same
CPU or distributed onto different computer nodes on a TCP/IP network. newLISP implements a Cilk-
like API to launch and control concurrent processes. The API can take advantage of
multi-core computer architectures. Only three functions, spawn,
sync and abort, are necessary to start
multiple processes and collect the results in a synchronized fashion. The underlying
operating system distributes processes onto different cores inside the CPU or
executes them on the same core in parallel if there are not enough cores present.
Note that newLISP only implements the API; optimized scheduling
of spawned procedures is not performed as in Cilk. Functions are started in the order
they appear in spawn statements and are distributed and scheduled onto
different cores in the CPU by the operating system. When multiple cores are present, this can increase overall processing speed
by evaluating functions in parallel. But even when running on single core CPUs,
the Cilk API makes concurrent processing much easier for the programmer and
may speed up processing if subtasks include waiting for I/O or sleeping. Since version 10.1 send and receive
message functions are available for communications between parent and child
processes. The functions can be used in blocking and non blocking communications
and can transfer any kind of newLISP data or expressions. Transmitted expressions
can be evaluated in the recipients environment. Internally, newLISP uses the lower level fork,
wait-pid, destroy, and
share functionalities to control processes and synchronize
the passing of computed results via a shared memory interface. Only on Mac OS X and other Unixes will the Cilk API parallelize tasks.
On Win32, the API partly simulates the behavior on Unix but executes tasks
sequentially. This way, code can be written that runs on all platforms. With only one function, net-eval, newLISP implements
distributed computing. Using net-eval, different tasks can be mapped
and evaluated on different nodes running on a TCP/IP network or local domain Unix sockets
network when running on the same computer. net-eval does all the housekeeping
required to connect to remote nodes, transfer functions to execute, and
collect the results. net-eval can also use a call-back function to
further structure consolidation of incoming results from remote nodes. newLISP's built-in support for XML-encoded data or documents
comprises three functions:
xml-parse,
xml-type-tags, and xml-error.
Use the xml-parse function
to parse XML-encoded strings.
When xml-parse encounters an error,
nil is returned.
To diagnose syntax errors caused by incorrectly formatted XML,
use the function xml-error.
The xml-type-tags function can be used
to control or suppress the appearance of XML type tags.
These tags classify XML into one of four categories:
text, raw string data, comments, and element data.
S-XML can be generated directly from XML
using xml-type-tags
and the special option parameters
of the xml-parse function:
S-XML is XML
reformatted as newLISP S-expressions.
The @ (at symbol) denotes
an XML attribute specification.
See xml-parse in
the reference section of the manual
for details on parsing and option numbers,
as well as for a longer example.
The remote procedure calling protocol XML-RPC uses
HTTP post requests as a transport and
XML for the encoding of method names, parameters, and parameter types.
XML-RPC client libraries and servers have been implemented
for most popular compiled and scripting languages.
For more information about XML,
visit www.xmlrpc.com.
XML-RPC clients and servers are easy to write
using newLISP's built-in network and XML support.
A stateless XML-RPC server implemented as a CGI service
can be found in the file examples/xmlrpc.cgi. This
script can be used together with a web server, like Apache.
This XML-RPC service script implements
the following methods:
The first three methods are discovery methods implemented by most XML-RPC servers.
The last one is specific to the newLISP XML-RPC server script and
implements remote evaluation of a Base64-encoded string of newLISP source code.
newLISP's base64-enc and base64-dec functions
can be used to encode and decode Base64-encoded information.
In the modules directory of the source distribution,
the file xmlrpc-client.lsp implements a specific client interface for
all of the above methods.
In a similar fashion,
standard system.xxx calls can be issued.
All functions return either a result if successful, or nil if a request fails.
In case of failure, the expression (XMLRPC:error) can be evaluated
to return an error message.
For more information, please consult the header of the file modules/xmlrpc-client.lsp.
All built-in primitives in newLISP can be easily renamed:
Now, plus is functionally equivalent to +
and runs at the same speed.
As with many scripting languages,
this allows for double precision floating point arithmetic
to be used throughout newLISP.
The constant function,
rather than the set function,
must be used to rename built-in primitive symbols.
By default, all built-in function symbols
are protected against accidental overwriting.
All operations using +, -, *, and /
are now performed as floating point operations. Using the same mechanism, the names of built-in functions
can be translated into languages other than English: The new symbol can be made global at the same time using global. newLISP can switch locales based on the platform and operating system.
On startup, newLISP attempts to set the ISO C standard default POSIX locale,
available for most platforms and locales. Use the
set-locale function to switch to the default locale:
This switches to the default locale used on your platform/operating system
and ensures character handling (e.g., upper-case)
works correctly. Many Unix systems have
a variety of locales available. To find out which ones are available on
a particular Linux/Unix/BSD system, execute the following command
in a system shell:
This command prints a list of all the locales available on your system.
Any of these may be used as arguments to set-locale:
This would switch to a U.S. Spanish locale.
Accents or other characters
used in a U.S. Spanish environment
would be correctly converted.
See the manual description for more details
on the usage of set-locale.
Many countries use a comma instead of a period
as a decimal separator in numbers.
newLISP correctly parses numbers
depending on the locale set: The default POSIX C locale, which is set when newLISP starts up,
uses a period as a decimal separator. The following countries use a period as a decimal separator: The following countries use a comma as a decimal separator: Note that for many European languages,
the set-locale mechanism
is sufficient to display non-ASCII character sets,
as long as each character is presented as one byte internally.
UTF-8 encoding is only necessary for multi-byte character sets as described
in this chapter.
newLISP can be compiled
as a UTF-8–enabled application.
UTF-8 is a multi-byte encoding
of the international Unicode character set.
A UTF-8–enabled newLISP
running on an operating system with UTF-8 enabled
can handle any character of the installed locale.
The following steps
make UTF-8 work with newLISP
on a specific operating system and platform:
(1) Use one of the makefiles
ending in utf8
to compile newLISP as
a UTF-8 application.
If no UTF-8 makefile
is available for your platform,
the normal makefile
for your operating system
contains instructions
on how to change it
for UTF-8.
The Mac OS X binary installer contains
a UTF-8–enabled version by default.
(2) Enable the UTF-8 locale
on your operating system.
Check and set a UTF-8 locale
on Unix and Unix-like OSes
by using the locale command
or the set-locale function within newLISP.
On Linux, the locale can be changed by setting
the appropriate environment variable.
The following example uses bash
to set the U.S. locale:
(3) The UTF-8–enabled newLISP
automatically switches to the locale found
on the operating system.
Make sure the command shell
is UTF-8–enabled.
When using the Tcl/Tk front-end on Linux/Unix,
Tcl/Tk will automatically switch to UTF-8 display
as long as the Unix environment variable
is set correctly.
The U.S. version of WinXP's notepad.exe
can display Unicode UTF-8–encoded characters,
but the command shell and the Tcl/Tk front-end cannot.
On Linux and other Unixes,
the Xterm shell can be used
when started as follows:
The following procedure can now be used
to check for UTF-8 support.
After starting newLISP, type:
While the uppercase omega (Ω) looks
like a big O on two tiny legs,
the lowercase omega (ω) has
a shape similar to a small w
in the Latin alphabet.
Note: Only the output of println
will be displayed as a character;
println's return value
will appear on the console
as a multi-byte ASCII character.
When UTF-8–enabled newLISP
is used on a non-UTF-8–enabled display,
both the output and the return value
will be two characters.
These are the two bytes necessary
to encode the omega character.
When UTF-8–enabled newLISP is used, the following string functions work
on one- or multi-byte characters rather than one 8-bit byte boundaries: All other string functions work on 8-bit bytes. When positions are returned,
as in find or regex,
they are single 8-bit byte positions rather than character positions which
may be multi-byte.
The get-char and slice functions
do not take multi-byte character offsets, but single-byte offsets, even
in UTF-8 enabled versions of newLISP.
The reverse function reverses
a byte vector, not a character vector. The last three functions can still
be used to manipulate binary non-textual data in the UTF-8–enabled
version of newLISP. To enable UTF-8 in Perl Compatible Regular Expressions (PCRE)
— used by directory, find,
member, parse, regex,
regex-comp and replace —
set the option number accordingly (2048). Note that offset and lengths in
regex results are always in single byte counts.
See the regex documentation for details. Use explode to obtain an array
of UTF-8 characters and to manipulate characters rather than bytes
when a UTF-8–enabled function is unavailable: The above string functions (often used to manipulate non-textual binary data)
now work on character, rather than byte, boundaries,
so care must be exercised when using the UTF-8–enabled version.
The size of the first 127 ASCII characters —
along with the characters in popular code pages such as ISO 8859 —
is one byte long. When working exclusively within these code pages,
UTF-8–enabled newLISP is not required.
The set-locale function alone
is sufficient for localized behavior. Two functions are available for converting between four-byte Unicode (UCS-4)
and multi-byte UTF-8 code. The UTF-8 function converts UCS-4
to UTF-8, and the unicode function converts UTF-8
or ASCII strings into USC-4 Unicode. These functions are rarely used in practice,
as most Unicode text files are already UTF-8–encoded
(rather than UCS-4, which uses four-byte integer characters).
Unicode can be displayed directly when using the
"%ls" format specifier. For further details on UTF-8 and Unicode,
consult UTF-8 and Unicode FAQ
for Unix/Linux by Markus Kuhn.
Some of the example programs contain functions
that use a comma to separate the parameters into two groups.
This is not a special syntax of newLISP,
but rather a visual trick.
The comma is a symbol just like any other symbol.
The parameters after the comma are not required
when calling the function;
they simply declare local variables in a convenient way.
This is possible in newLISP because parameter variables in lambda expressions
are local and arguments are optional:
When calling this function,
only a, b, and c are used as parameters.
The others (x, y, and z)
are initialized to nil
and are local to the function.
After execution, the function's contents are forgotten
and the environment's symbols are restored
to their previous values.
For other ways of declaring and initializing local variables,
see let, letex,
letn and local.
Source code and the newLISP executable can be linked together to build
a self-contained application by using link.lsp. This program is
located in the newlisp/util directory of the distributions.
As an example, the following code is linked to the newLISP executable
to form a simple, self-contained application:
This program, which resides in the file uppercase.lsp, takes the
first word on the command-line and converts it to uppercase. To build this program as a self-contained executable,
follow these four steps: (1) Put the following files into the same directory:
(a) a copy of the newLISP executable; (b) newlisp
(or newlisp.exe on Win32); (c) link.lsp; and (d) the program to
link with (uppercase.lsp in this example). (2) In a shell, go to the directory referred to in step 1
and load link.lsp: (3) In the newLISP shell, type one of the following:
(4) Exit the newLISP shell and type:
The console should print: Note: On Linux/BSD, the new file must be marked
executable for the operating system to recognize it: This gives the file executable permission (this step is unnecessary on Win32).
Note that neither one of the initialization files init.lsp nor
.init.lsp is loaded during startup of linked programs. Source code in newLISP is parsed according to the rules outlined here.
When in doubt, verify the behavior of newLISP's internal parser
by calling parse without optional arguments.
The following rules apply to the naming of symbols
used as variables or functions:
All of the following symbols are legal variable names in newLISP:
Sometimes it is useful to create hash-like lookup dictionaries
with keys containing characters that are illegal in newLISP variables.
The functions sym and context
can be used to create symbols containing these characters:
The last example creates the symbol 1
containing the value 123.
Also note that creating such a symbol does not alter newLISP's normal operations,
since 1 is still parsed as the number one.
newLISP recognizes the following number formats:
Integers are one or more digits long,
optionally preceded by a + or - sign.
Any other character marks the end of the integer
or may be part of the sequence
if parsed as a float (see float syntax below).
Hexadecimals start with a 0x (or 0X),
followed by any combination of the hexadecimal digits:
0123456789abcdefABCDEF.
Any other character ends the hexadecimal number.
Octals start with an optional + (plus) or - (minus) sign and a 0 (zero),
followed by any combination of the octal digits: 01234567.
Any other character ends the octal number.
Floating point numbers can start
with an optional + (plus) or - (minus) sign,
but they cannot be followed by a 0 (zero);
this would make them octal numbers instead of floating points.
A single . (decimal point) can appear anywhere within
a floating point number, including at the beginning.
As described above, scientific notation
starts with a floating point number
called the significand (or mantissa),
followed by the letter e or E
and an integer exponent.
To describe the types and names of a function's parameters,
the following naming convention is used throughout the reference section: Arguments are represented by symbols formed by the argument's type and name,
separated by a - (hyphen). Here, str-format (a string) and
exp-data-1 (an expression) are named "format" and "data-1", respectively. Arguments enclosed in brackets [ and ] are optional. When
arguments are separated by a vertical | then one of them must be chosen. An array (constructed with the array function). One or more expressions for evaluation. The expressions are evaluated sequentially
if there is more than one. true, nil, or an expression evaluating to one of these two.
An expression evaluating to a context (namespace) or a variable symbol
holding a context. Any datatype described in this chapter.
A symbol or an expression evaluating to
an operator symbol or lambda expression.
An integer or an expression evaluating to an integer.
Generally, if a floating point number is used
when an int is expected,
the value is truncated to an integer.
A list of elements (any type)
or an expression evaluating to a list.
An integer, a floating point number,
or an expression evaluating to one of these two.
If an integer is passed,
it is converted to a floating point number.
A list in which each row element is itself a list
or an array in which each row element is itself an array.
All element lists or arrays (rows) are of the same length.
When using det,
multiply,
or invert,
all numbers must be floats or integers.
The dimensions of a matrix are defined
by indicating the number of rows
and the number of column elements per row.
Functions working on matrices
ignore superfluous columns in a row.
For missing row elements,
0.0 is assumed by the functions
det, multiply,
and invert,
while transpose assumes nil.
Special rules apply for transpose
when a whole row is not a list or an array,
but some other data type.
A place referenced by a symbol or a place defined in a list, array
or string by indexing with nth or implicit indexing
or a place referenced by functions like first, last,
assoc or lookup.
A string or an expression that evaluates to a string.
Special characters can be included in quoted strings
by placing a \ (backslash) before the character
or digits to escape them:
Decimals start with a digit. Hexadecimals start with x:.
Instead of a " (double quote),
a { (left curly bracket)
and } (right curly bracket)
can be used to delimit strings.
This is useful when quotation marks need to occur inside strings.
Quoting with the curly brackets
suppresses the backslash escape effect for special characters.
Balanced nested curly brackets may be used within a string.
This aids in writing regular expressions or short sections of HTML.
The tags [text] and [/text]
can be used to delimit long strings
and suppress escape character translation.
This is useful for delimiting long HTML passages
in CGI files written in newLISP
or for situations where character translation
should be completely suppressed.
Always use the [text] tags
for strings longer than 2048 characters.
A symbol or expression evaluating to a symbol.
Most of the context symbols in this manual start with an uppercase letter
to distinguish them from other symbols.
A symbol, an existing context, or an expression evaluating to a symbol
from which a context will be created. If a context does not already exist,
many functions implicitly create them
(e.g., bayes-train, context,
eval-string,
load, sym, and xml-parse).
The context must be specified when these functions are used
on an existing context. Even if a context already exists,
some functions may continue to take quoted symbols (e.g., context).
For other functions, such as context?, the distinction is critical.
Some functions appear in more than one group. Executes the command in str-command by shelling out to the
operating system and executing. This function returns a different value
depending on the host operating system. Use the exec function to execute a shell command
and capture the standard output or to feed standard input.
The process function may be used to launch a
non-blocking child process and redirect std I/O and std error to pipes. Note that ! (exclamation mark) can be also be used as
a command-line shell operator by omitting the parenthesis and space
after the !:
Used in this way,
the ! operator
is not a newLISP function at all,
but rather a special feature of
the newLISP command shell.
The ! must be entered
as the first character
on the command-line.
The functions that use regular expressions (directory,
ends-with, find, parse,
regex, search, starts-with
and 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). Returns the sum of all numbers in int-1 —. 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. The product is calculated for int-1 to int-i. Each result is divided successively until the end of the list is reached.
Division by zero causes an error. 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 mod function.
Floating point values in arguments to
+, -, *, /, and %
are truncated to their floor value.
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.
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.
For floating point values that evaluate to NaN (Not a Number),
both +INF and -INF are treated as 0 (zero).
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.
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.
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):
When int-1 is the only argument <<
and >> shift by one bit.
A bitwise and operation is performed
on the number in int-1 with the number in int-2,
then successively with int-3, etc.
A bitwise or operation is performed
on the number in int-1 with the number in int-2,
then successively with int-3, etc.
A bitwise xor operation is performed
on the number in int-1 with the number in int-2,
then successively with int-3, etc.
A bitwise not operation is performed
on the number in int,
reversing all of the bits.
When used as an operator, the colon : 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 : 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. Using the colon : operator does not prohibit naming the method context explicitly when it is known. In the first usage, the : is part of the syntax for qualifying a
symbol with its context. The second usage of the : as an operator
implements polymorphism by resolving the context at runtime. Note that in the above example, the :move methods are implemented
in a functional way, reassigning shapes with changed x and
y coordinates to myrect and mycircle.
In the first form, 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 spawn. For processes
started using fork, use destroy
instead. On Win32 abort has no function and will always return true.
To abort all child processes spawned from the current process use abort
without any parameters: The function abort is part of the Cilk API for synchronizing
child processes and process parallelization. See the reference for the
function spawn for a full discussion of the Cilk API.
Returns the absolute value of the number in num.
The arc-cosine function is calculated
from the number in 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,
acosh returns NaN.
All of the numbers in num-1, num-2, and on
are summed.
add accepts float or integer operands,
but it always returns a floating point number.
Any floating point calculation with NaN
also returns NaN.
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 import function.
When a string is passed,
the address of the string is automatically used.
As the example shows,
address can be used to do pointer arithmetic
on the string's address.
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 get-char, get-int,
get-long and get-float functions.
One of the expressions exp-1 ... n is selected at random,
and the evaluation result is returned.
Internally, newLISP uses the same function as rand to pick a random number.
To generate random floating point numbers,
use random,
randomize, or normal.
To initialize the pseudo random number generating process
at a specific starting point,
use the seed function.
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.
In the first form,
append works with lists,
appending list-1 through list-n to form a new list.
The original lists are left unchanged.
In the second form append works on arrays:
In the third form, append works on strings. The strings in
str-n are concatenated into a new string and returned.
append is also suitable for processing binary strings containing zeroes.
The string function would cut of strings at zero bytes.
Linkage characters or strings can be specified using the
join function. Use the string
function to convert arguments to strings and append in one step.
Use the functions push or
write-buffer (with its special syntax)
to append to an existing string in place.
Works similarly to 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, append-file
works identically to write-file). This function
returns the number of bytes written. append-file can take a http:// or file:// URL
in str-file-name. In case of the http:// prefix ,
append-file works exactly like 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. 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, append-file can also be used
to transfer files to remote newLISP server nodes.
See also read-file and
write-file.
Applies the contents of func
(primitive, user-defined function, or lambda expression)
to the arguments in list.
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:
The last example shows how apply's reduce functionality
can be used to convert a two-argument function into one that takes multiple arguments.
apply should only be used on functions and operators that evaluate all
of their arguments, not on special forms like dotimes
or case, which evaluate only some of their arguments.
Doing so will cause the function to fail.
Accesses a list of all unbound arguments passed to the currently evaluating
define, 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 args function is useful for defining functions or macros
with a variable number of parameters.
args can be used to define hygienic macros that avoid the danger of
variable capture. See define-macro.
This example prints a line-feed after each argument.
The macro mimics the effect of the built-in function
println.
In the second syntax,
args can take one or more indices (int-idx-n).
The function foo
prints out the arguments in reverse order.
The bar function
shows 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:
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 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.
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 arrays. 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. Arrays are modified and accessed using most of the same functions used for
modifying lists: Care must be taken to use an array when replacing a whole row.
array-list can be used to convert arrays back into lists:
To convert a list back into an array, apply flat to the list:
The array? function
can be used to check if an expression is an array:
When serializing arrays using the function source
or save, the generated code includes the array
statement necessary to create them. This way, variables containing arrays are
correctly serialized when saving with save or creating
source strings using source.
Returns a list conversion from array,
leaving the original array unchanged:
Checks if exp is an array:
Calculates the arcsine function from the number in num-radians
and returns the result.
Calculates the inverse hyperbolic sine of num-radians,
the value whose hyperbolic sine is num-radians.
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.
In the second syntax more then one key expressions can be specified
to search in nested, multilevel association lists: 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:
For making replacements in association lists, use the
setf together with the assoc function.
The lookup function is used to perform association lookup
and element extraction in one step.
The arctangent of num-radians
is calculated and returned.
The 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.
atan2 is useful for converting
Cartesian coordinates
into polar coordinates.
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,
atanh returns NaN; if it is equal to 1, atanh returns infinity.
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.
The BASE64 string in str is decoded.
Note that str is not verified
to be a valid BASE64 string.
The decoded string is returned.
For encoding,
use the base64-enc function.
newLISP's BASE64 handling is derived from
routines found in the Unix curl utility.
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.
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).
Note that 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 base64-dec function.
newLISP's BASE64 handling is derived from routines
found in the Unix curl utility.
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 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 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,
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,
bayes-query uses the following formula:
For N categories,
this formula is used:
The probabilities (p(Mi) or p(A), along with p(B))
represent the Bayesian prior probabilities.
p(Mx|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 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.
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.
The two training sets are loaded, split into tokens,
and processed by the bayes-train function.
In the end, the DoyleDowson dictionary is saved to a file,
which will be used later with the bayes-query function.
The following code illustrates how bayes-query is used
to classify a sentence as Doyle or Dowson:
The queries correctly identify the first sentence as a Dowson sentence,
and the second one as a Doyle sentence.
The second example is frequently found
in introductory literature on Bayesian statistics.
It shows the Chain Bayesian method of
using bayes-query on the data of a previously processed data set:
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?
Note that the Bayesian formulas used
assume statistical independence of events
for the 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.
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:
As expected, the results are the same for probabilities
as they are for frequencies.
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 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.
The first example shows training with two lists of symbols. The second example
illustrates how an _ is prepended when training with strings. bayes-train creates symbols from strings prepending an underscore
character. This is the same way hashes are created and contexts populates with
symbols by bayes-train can be used like hashes:
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 bayes-train function:
The last data are from a popular example used to describe the
bayes-query function in introductory papers
and books about bayesian networks.
Training can be done in different stages by using 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 bayes-train in multiple stages. Categories can also be
singularly trained by specifying an empty list for the absent corpus:
bayes-train will correctly update word counts and totals.
Using bayes-train inside a context other than MAIN
requires the training contexts to have been created previously within
the MAIN context via the context function.
bayes-train is not only useful with the bayes-query function,
but also as a function for counting in general.
For instance, the resulting frequencies
could be analyzed using prob-chi2
against a null hypothesis of proportional distribution
of items across categories.
The 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.
Some built-in functions like cond, define,
doargs, dolist, dostring,
dotimes, when and while
already allow multiple expressions in their bodies,
but begin is often used in an if expression.
The silent function works like begin,
but suppresses console output on return.
The Beta function, beta,
is derived from the log Gamma
gammaln function as follows:
The Incomplete Beta function, betai,
equals the cumulative probability of the Beta distribution, 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:
The first 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.
The second example calculates the one-tailed probability of a variance, F ratio.
In similar fashion, students t could be calculated using betai.
See also the binomial function.
list-variable-associations contains an association list of
symbols and their values. bind sets all symbols
to their associated values. The associated values are evaluated if the bool-eval flag is true: The return value of bind is the value of the last association. bind is often used to bind association lists returned
by unify. This can be used for de-structuring: unify returns an association list and bind binds the
associations. bind together with args can be used to write functions
with named parameters: Arguments are evaluated incrementally in the local environment and assigned to
the local variables.
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:
where x! is the factorial of x
and pow(x, y) is x raised to the power of y.
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 betai function.
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. int with a base of 2 is the inverse function to bits. Up to sixteen (0 to 15) callback functions for up to eight
parameters can be registered with imported libraries. The 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 OpenGL
graphics library: If more than sixteen callback functions are required, slots can be
reassigned to a different callback function. The address returned by callback is registered with the
Glut library.
The above code is a snippet from the file opengl-demo.lsp,
in the examples/ directory of the source distribution of newLISP.
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 match is returned
as the result for the entire case expression.
The example shows how,
if no match is found,
the last expression in the body of a case function
can be evaluated.
In the first syntax,
catch will return the result of the evaluation of exp
or the evaluated argument of a throw
executed during the evaluation of exp:
This form is useful for breaking out of iteration loops
and for forcing an early return
from a function or expression block:
In the second syntax,
catch evaluates the expression exp,
stores the result in symbol,
and returns true.
If an error occurs during evaluation,
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.
When a throw is executed during the evaluation of exp,
catch will return true,
and the throw argument will be stored in symbol:
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 catch can also be used to catch errors.
The throw-error function may be used
to throw user-defined errors.
Returns the next highest integer above number
as a floating point.
See also the floor function.
Changes the current directory to be the one given in str-path.
If successful, true is returned; otherwise nil is returned.
Makes /etc the current directory.
Given a string argument, extracts the character at int-index from str,
returning the ASCII value of that character. If int-index is omitted,
0 (zero) is assumed. The empty string or a binary zero character return nil,
but (char 0) will return "\000".
See Indexing elements of strings and lists.
Given an integer argument,
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.
If the first argument evaluates to a string,
chop returns a copy of str
with the last int-char characters omitted.
If the int-char argument is absent,
one character is omitted.
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).
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.
clean works like filter
with a negated predicate.
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 difference
or intersect
(with the list option).
See also the related function index,
which returns the indices of the remaining elements,
and filter,
which returns all elements for which a predicate returns true.
Closes the file specified by the file handle in int-file.
The handle would have been obtained
from a previous open operation.
If successful, close returns true; otherwise nil is returned.
Note that using close on device
automatically resets it to 0 (zero, the screen device).
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. command-event takes either a symbol of a user-defined function or a lambda
function. The function for 'command-event' must return a string of 254 characters
maximum length. Not returning a string will leave the command-line untranslated and
pass it on to newLISP as is. 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. See also the related 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: 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. This way when shelling out with ! 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: Or if a query is involved: A function specified by 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: When starting the server mode with newlisp httpd-conf.lsp -c -d80 -w ./httpdoc
newLISP will load the definition for command-event for filtering incoming
requests, and the query: Would be translated into: 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.
Like if, cond conditionally evaluates the expressions
within its body.
The exp-conditions 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.
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).
When used with multiple arguments,
the function if
behaves like cond,
except it does not need extra parentheses
to enclose the condition-body pair
of expressions.
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:
consing two atoms constructs a list, not a dotted pair.
Unlike other Lisps that return (s)
as the result of the expression (cons 's nil),
newLISP's 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.
cons behaves like the inverse operation of first
and rest
(or first and last if the list is a pair):
Identical to set in functionality,
constant further protects the symbols from subsequent modification.
A symbol set with constant can only be modified
using the constant function again.
When an attempt is made to modify the contents of a symbol protected with constant,
newLISP generates an error message.
Only symbols from the current context can be used with constant.
This prevents the overwriting of symbols
that have been protected in their home context.
Symbols initialized with set, define,
or define-macro can still be protected by using
the constant function:
The first example defines a constant, aVar,
which can only be changed by using another constant statement.
The second example protects double from being changed
(except by 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.
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.
squareroot will behave like sqrt.
The + (plus sign) is redefined
to use the mixed type floating point mode of add.
The hexadecimal number displayed in the result
is the binary address of the built-in function
and varies on different platforms and OSes.
In the first syntax, context is used to switch to a different context namespace.
Subsequent loads of newLISP source or functions like
eval-string and 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 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.
If a context symbol is referred to before the context exists,
the context will be created implicitly.
Contexts can be copied:
Contexts can be referred to by a variable:
An evaluated context (no quote) can be given as an argument:
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 : (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:
CTX:new will overwrite new in MAIN.
In the second syntax, context can be used 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
Hash functions and dictionaries.
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 context only creates the new symbol
and returns the value contained in it. It does not switch to the new namespace.
In the first syntax,
context? is a predicate that returns true
only if exp evaluates to a context;
otherwise, it returns nil.
The second syntax checks for the existence of a symbol in a context.
The symbol is specified by its name string in str-sym.
Use context to change and create namespaces
and to create hash symbols in contexts.
Make a copy from evaluating expression in exp. Some built-in
functions are destructive, changing the original
contents of a list, array or string they are working on. With copy
their behavior can be made non-destructive. Using copy the functions replace and
rotate are prevented from changing the data.
A modified version of the data is returned.
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.
Calculates the cosine of num-radians
and returns the result.
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.
Counts elements of list-1 in list-2
and returns a list of those counts.
The second example counts all occurrences
of different letters in myFile.txt.
The first list in 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).
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.
cpymem can crash the system
or make it unstable if used incorrectly.
The first example would remove
the protection bit in symbol 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 code
to add up two numbers and return the result:
The binary representation is attached
to a new function created in newLISP:
Use the dump function
to retrieve binary addresses
and the contents from newLISP cells.
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.
crc32 uses an algorithm published
by www.w3.org.
crc32 is often used to verify data integrity
in unsafe data transmissions.
Calculates the critical minimum Chi²
for a given confidence probability num-probability
and the degrees of freedom num-df
for testing the significance of a statistical null hypothesis.
See also the inverse function prob-chi2.
Calculates the critical normal distributed Z value
of a given cumulated probability (num-probability)
for testing of statistical significance and confidence intervals.
See also the inverse function prob-z.
Retrieves the contents of the last
read-line operation.
current-line's contents are also implicitly used
when write-line
is called without a string parameter.
The following source shows the typical code pattern
for creating a Unix command-line filter:
The program is invoked:
This displays all comment lines starting with ;;
from a file given as a command-line argument
when invoking the script filter.
Transforms func from a function f(x, y) that takes
two arguments into a function fx(y) that takes a single argument.
curry works like a macro in that it does not evaluate its arguments.
Instead, they are evaluated during the application of func. curry can be used on all functions taking two arguments.
The first syntax returns the local time zone's
current date and time as a string representation.
In the second syntax, 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 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.
Note that on some Win32-compiled versions,
values resulting in dates earlier than
January 1, 1970, 00:00:00
return nil.
But the MinGW compiled version will also work
with values that result in dates up to 24 hours
prior to 1/1/1970, returning a date-time string for 12/31/1969.
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).
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:
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 documentation for the C function
strftime() in the individual platform's C library.
Leading zeroes in the display of decimal numbers can be suppressed
using - (minus) on Linux/Unix and # (number sign) on Win32.
See also date-value,
parse-date,
time-of-day,
time, and now.
In the first syntax, 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, date-value returns the time value
in seconds for the current time.
The following function can be used
to transform a date-value
back into a list:
See also date, time-of-day,
time, and now.
Calls trace and begins evaluating
the user-defined function in func.
debug is a shortcut for executing (trace true),
then entering the function to be debugged.
See also the trace function.
The number in place is decremented by one (or the optional number
num) and returned. dec performs mixed integer and floating
point arithmetic according to the rules outlined below. place is either a symbol or a place in a list structure, or
an other number returned by an expression.
If place contains a float and num is absent, the input argument
is truncated to an integer.
Integer calculations (without num) 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.
If num is supplied, dec always returns the result as a
floating point number (even for integer arguments). If the symbol in place contains nil, it is treated
as if containing 0 or 0.0: Places in a list structure or a number returned by another expression
can be updated too:
Use the inc function to increment numbers.
This function works similarly to 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 will be translated into symbol references
of the target context.
def-new returns the symbol created:
The function def-new can be used to configure contexts
or context objects in a more granular fashion than is possible
with new, which copies a whole context.
Return the contents of the default functor in context. In many situations newLISP defaults automatically to the default functor
when seeing a context name. In circumstances where this is not the case,
the default function can be used.
Defines the new function sym-name,
with optional parameters sym-param-1—.
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 define
is the assigned lambda expression.
When calling a user-defined function,
the return value is the last expression evaluated
in the function body.
As an alternative, area could be defined
as a function without using define.
lambda or fn expressions may be used by themselves
as anonymous functions without being defined as a symbol:
fn is just a shorter form of writing lambda.
Parameters can have default values specified:
Expressions in exp-default
are evaluated in the function's
current environment.
The second version of define
works like the set function.
Trying to redefine a protected symbol will cause an error message.
Functions defined using define-macro are called fexprs
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 define-macro can be combined with template
expansion using expand or letex. Defines the new macro sym-name, with optional arguments sym-param-1 —.
define-macro is equivalent to assigning a lambda-macro expression to a symbol.
When a macro-defined function is called, arguments are assigned to the variables
in sym-param-1— without evaluating the arguments first.
Then the body expressions are evaluated. When evaluating the
define-macro function, the lambda-macro expression is returned.
Macros in newLISP are similar to define functions,
but they do not evaluate their arguments.
New functions can be created to behave like built-in functions
that delay the evaluation of certain arguments.
Because macros 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.
Expressions in exp-default are evaluated in the function's
current environment. Note that in macros, the danger exists of passing a parameter
with the same variable name as used in the macro definition.
In this case, the macro internal variable would end up
receiving nil instead of the intended value: There are several methods that can be used
to avoid this problem, known as variable capture,
by writing hygienic macros:
The macro in the example is lexically isolated,
and no variable capture can occur.
Instead of the macro being called using (my-setq:my-setq …),
it can be called with just (my-setq …)
because it is a default function.
A third possibility is to refer to passed parameters
using args:
The last example shows how letex can be combined with
define-macro to expand macro variables into an expression to be evaluated:
dolist-while loops through a list
while the condition is true.
Note that a similar feature is already built into
dolist as a break condition
optional parameter.
Also, the expand function performs variable
expansion explicitly, without evaluating the expanded expression.
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 or anything other than nil,
symbols are only deleted when they are not referenced.
Protected symbols of built-in functions and special symbols
like nil and true cannot be deleted.
delete returns true if the symbol was deleted
successfully or nil if the symbol was not 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 a function
which is currently executing can crash the system
or have other unforeseen effects.
Deletes a file given in str-file-name.
Returns true if the file was deleted
successfully or nil if the file was not deleted.
The file name can be given as a URL.
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 delete-url for details.
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 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 delete-file
function is used and a URL is specified for the filename. 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 get-url function for details. 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 fork on Mac OS X and other Unix or
process on all platforms. On Unix, 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, 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.
Returns the determinant of a square matrix.
A matrix can either be a nested list
or an array.
If the matrix is singular,
nil is returned.
See also the other matrix operations
invert, mat,
multiply and transpose.
int is an I/O device number, which is 0 (zero)
for the default STD I/O console window.
int may also be a file handle
previously obtained using open.
When no argument is supplied,
the current I/O device number is returned.
The I/O channel specified by device
is used internally by the functions
print and read-line.
When the current I/O device is 0 (zero), print
sends output to the console window and read-line
accepts input from the keyboard.
If the current I/O device has been set by opening a file,
then print and read-line work on that file.
Note that using close on device
automatically resets device to 0 (zero).
In the first syntax, 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.
In the second syntax, 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.
See also the set functions intersect
and unique.
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.
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 (/) can be included in path names.
When used, a backslash (\) must be
preceded by a second backslash.
In the second syntax, 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-options, special regular expression options
can be specified; see regex for details.
The regular expression forces directory
to return only file names containing the string ".c".
Other functions that use regular expressions
are find, find-all,
parse,
regex, replace,
and search.
Checks if str-path is a directory.
Returns true or nil depending on the outcome.
Successively divides num-1
by the number in num-2—.
div can perform mixed-type arithmetic,
but it always returns floating point numbers.
Any floating point calculation
with NaN also returns NaN.
When num-1 is the only argument,
div calculates the inverse of num-1.
The expressions in body are evaluated
before exp-condition is evaluated.
If the evaluation of exp-condition is not nil,
then the do-until expression is finished;
otherwise, the expressions in body get evaluated again.
Note that do-until evaluates the conditional expression
after evaluating the body expressions,
whereas until checks the condition
before evaluating the body.
The return value of the do-until expression
is the last evaluation of the body expression.
If body is empty, the last result of exp-condition
is returned.
do-until also updates the system iterator symbol $idx.
While do-until goes through the loop at least once,
until never enters the loop.
See also the functions while
and do-while.
The expressions in body are evaluated
before exp-condition is evaluated.
If the evaluation of exp-condition is nil,
then the do-while expression is finished;
otherwise the expressions in body get evaluated again.
Note that do-while evaluates the conditional expression
after evaluating the body expressions,
whereas while checks the condition
before evaluating the body.
The return value of the do-while expression
is the last evaluation of the body expression.
do-while also updates the system iterator symbol $idx.
While do-while goes through the loop at least once,
while never enters the loop.
See also the functions until
and do-until.
Iterates through all members of the argument list
inside a user-defined function or macro. This function or macro can be defined using define,
define-macro, lambda, or
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 doargs expression always returns the result of the last evaluation. doargs also updates the system iterator symbol $idx. The optional break expression causes doargs
to interrupt processing of the arguments: Use the args function to access the entire argument list at once.
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 dolist loop returns with the value of exp-break.
The break condition is tested before evaluating body.
This example prints abcdefg in the console window.
After the execution of dolist,
the value for x remains unchanged
because the x in dolist has local scope.
The return value of 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 dolist,
and it can be accessed during its execution:
The console output is shown in boldface.
$idx is protected and cannot be changed by the user.
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 dolist loop returns with the value of exp-break.
The break condition is tested before evaluating body.
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 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 dostring,
and it can be accessed during its execution.
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 dotimes
expression and behaves according the rules of dynamic scoping.
The loop index is of integer type.
dotimes returns the result of
the last expression evaluated in body.
Optionally, a condition for early loop exit
may be defined in exp-break.
If the break expression evaluates to any non-nil value,
the dotimes loop returns with the value of exp-break.
The break condition is tested before evaluating body.
This prints 0123456789 to the console window.
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 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 hash keys and symbols created by
bayes-train. dotree also updates the system iterator symbol $idx.
This example prints the names of all symbols inside SomeCTX to the console window.
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.
The list contains the following memory addresses and information:
This function is valuable for changing type bits in cells
or hacking other parts of newLISP internals.
See the function cpymem
for a comprehensive example.
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, dup assumes 2.
The last example shows handling of binary information,
creating a string filled with four binary zeroes.
See also the functions sequence
and series.
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.
The first example checks a list,
while the second two examples check a string.
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:
The second example encrypts a whole file:
In the first syntax, 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.
When nil or any expression evaluating to nil
as a third parameter in bool is specified,
the comparison is case-insensitive.
If a regular expression option number is
specified, str-key contains a regular expression pattern. See
regex for valid numbers for option.
In the second syntax,
ends-with checks if a list
ends with the list element in exp.
true or nil is returned depending on outcome.
The last example shows that exp could be a list by itself.
See also the starts-with function.
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. In the second syntax, the name of an environment variable
is given in var-str. env returns the value
of the variable or nil if the variable does not exist
in the environment. 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.
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 sym contains a user-defined function for handling errors.
Whenever an error occurs, the system performs a reset
and executes the user-defined error handler. The error handler can use the
built-in function last-error to retrieve the number
and text of the error.
For a different way of handling errors, see the catch function.
Use throw-error to throw user-defined errors.
eval evaluates the result of evaluating exp in the current variable environment.
As usual, evaluation of variables happens in the current variable environment:
newLISP passes all arguments by value.
Using a quoted symbol,
expressions can be passed
by reference through the symbol.
eval can be used
to access the original contents of the symbol:
In the example, the parameter 'data is quoted,
so 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 Programming
with context objects and the sub-chapter
Passing objects by reference. Passing references into user defined
function using namespaces ids avoids variable capture of
the passed symbol, if the symbol passed is the same used as a
parameter in the function.
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 and error occurs while parsig 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. 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 read-expr which translates a string
without evaluating it. In the first form, 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)). 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.
The example starts a process and performs the shell command ls,
capturing the output in an array of strings.
In the second form,
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.
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.
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. If func-condition is nil?, the result nil is ambiguous.
In this case index or find are the better
method when looking for nil. Use the for-all function
to check if a condition is met for all elements in a list.
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 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.
The expression in num is evaluated,
and the exponential function is calculated based on the result.
exp is the inverse function of log.
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.
expand is useful when composing lambda expressions
or doing variable expansion inside macros.
If more than one symbol is present,
expand will work in an incremental fashion:
Like the apply function,
expand reduces its argument list.
The second syntax of expand allows expansion bindings to be specified
on the fly, without performing a set on the participating variables:
If the bool evaluates to true, the value parts in the
association list are evaluated.
Note that the contents of the variables
in the association list will not change.
This is different from the letex function,
where variables are set by evaluating
and assigning their association parts.
This form of expand is frequently used
in logic programming,
together with the unify function.
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 expand,
symbols must be preset.
Only uppercase variables and those bound
to anything other than nil
will be expanded:
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 expand
can now be written even more simply
using an uppercase variable:
See the letex function,
which also provides an expansion mechanism,
and the function unify,
which is frequently used together with expand.
In the first syntax,
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 also works on binary content:
When called in UTF-8–enabled versions of newLISP,
explode will work on character boundaries
rather than byte boundaries.
In UTF-8–encoded strings,
characters may contain more than one byte.
In the second syntax,
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.
The join and append functions
are inverse operations of explode.
Factors the number in int
into its prime components.
Floating point numbers in num
are truncated to their integer part.
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.
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,
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.
The inverse operation of fft
is the ifft function.
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. 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). In the second example, the last status change date
for the directory /etc is retrieved. file-info gives file statistics (size) for a linked file,
not the link, except for the mode field.
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.
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.
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.
filter works like clean,
but with a negated predicate.
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 difference function or
intersect (with the list option).
See also the related function index, which returns the
indices of the filtered elements and clean,
which returns all elements of a list for which a predicate is false.
If the second argument evaluates to a list, then 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 exp-key is a string, a regular expression option
can be specified with int-option instead and optionally an
additional int-offset parameter. When using regular expressions or comparison functors the system
variable $0 is set to the last element found.
Using match and unify,
list searches can be formulated which are as powerful
as regular expression searches are for strings.
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, 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-option
(i.e., 1 (one) for case-insensitive search or 0 (zero)
for no special options). If int-option is specified
an optional int-offset argument can be specified too
to start the search not at the beginnig but at the offset given.
In any case the position returned by find is calculated
relative to the beginning of the string. 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 regex for the meaning of the
option numbers and more information on regular expression searching.
For other functions using regular expressions,
see directory,
find-all,
parse,
regex,
replace,
and search.
To find expressions in nested
or multidimensional lists,
use the ref and ref-all functions.
In the first syntax, find-all finds all occurrences of str-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 regex for further details).
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 find-all with strings always performs a regular expression search,
even if the option in int-option is omitted.
In the second syntax, find-all searches for all list match
patterns list-pattern in list-lists. As in find-all for
strings, an expression can be specified in exp to process further the matched
sublist: Instead of the system variable $it the variable $0 could be used
as well. find-all for list matches always uses match to compare when
searching for sublists and always needs a list for the pattern expression. In the third syntax, find-all can specify a built-in or user-defined
function used for comparing list elements with the key expression in exp-key: Any type of expression can be searched for or can be contained in the list. find-all
in this syntax works similar to filter but with the added benefit of
being able to define a processing expression for the found element.
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.
In the second syntax,
the first character is returned
from the string in str
as a string.
Note that first works on character boundaries
rather than byte boundaries
when the UTF-8–enabled version of newLISP is used.
See also the functions last
and rest.
Returns a flattened list from a list: flat can be used to iterate through nested lists.
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 + (plus sign), - (minus sign),
or . (period).
If exp is invalid,
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.
Use the int function
to parse integer numbers.
true is returned only
if exp evaluates to a floating point number;
otherwise, nil is returned.
Returns the next lowest integer below number
as a floating point.
See also the ceil function.
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.
The last two statements illustrate
the inner workings of flt.
Use the import function
to import libraries.
fn is used to define anonymous functions,
which are frequently used in map,
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 define.
Instead, a function is defined on the fly:
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 map.
The second example shows strings being sorted by length.
The lambda function
(the longer, traditional form)
can be used in place of fn.
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.0 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 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 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.
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 sequence function
to make a sequence of numbers.
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. Use the exists function
to check if at least one element in a list
meets a condition.
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, fork returns with the child process ID; on failure,
nil is returned. See also the 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 spawn and the Cilk API.
The example illustrates how the child process-thread inherits the symbol space
and how it is independent of the parent process. The 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 pipe can be used
to communicate between processes. The following output is generated by observer-proc
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 destroy function. The process started by fork-destroy-demo will not finish but is
destroyed 50 milli-seconds after start by a call to destroy.
Use the semaphore function for synchronizing processes
and share for sharing memory between processes.
See spawn for a much simpler and automated way to
synchronize processes and collect results.
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.
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.
int, float,
or string can be used
to ensure correct data types and to avoid error messages.
The format string has the following general format:
The % (percent sign)
starts a format specification.
To display a % 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.
When preceded by a 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.
If preceded by a + (plus sign),
positive numbers are displayed with a +.
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:
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: For 64-bit numbers (since version 8.9.7) use the following format
strings on Tru64 Unix:
On Win32 platforms the following characters apply for 64 bit numbers:
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.
The data to be formatted
can be passed inside a list:
If the format string requires it,
newLISP's format will
automatically convert integers
into floating points
or floating points into integers:
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); for payment
at the end of each period, int-type is 1.
If num-type is omitted, payment
at the end of each period is assumed.
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 irr,
nper, npv,
pmt, and pv.
Calculates the incomplete Gamma function
of values a and b in num-a and num-b,
respectively.
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:
See also the prob-chi2 function.
Calculates the log Gamma function of the value x in num-x.
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:
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.
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.
See
Wikipedia
for details and theory about gcd numbers in mathematics.
Gets a character from an address
specified in int-address.
This function is useful when using
imported shared library functions
with import.
Consider the above C function
from a shared library, which returns a
character pointer (address to a string).
Note that it is unsafe to use the get-char function
with an incorrect address in int-address. Doing so
could result in the system crashing or becoming unstable.
See also the address,
get-int,
get-long,
get-float,
get-string,
pack, and unpack functions.
Gets a 64-bit double float from an address
specified in int-address.
This function is helpful when using
imported shared library functions (with import)
that return an address pointer to a double float
or a pointer to a structure containing double floats.
The previous C function is compiled
into a shared library.
foo is imported and returns a pointer
to a double float when called.
Note that 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 address,
get-int,
get-long,
get-char,
get-string,
pack,
and unpack functions.
Gets a 32-bit integer from
the address specified in int-address.
This function is handy when using
imported shared library functions with import,
a function returning an address pointer
to an integer, or a pointer to a structure containing integers.
Consider the C function foo (from a shared library),
which returns an integer pointer (address of an integer).
Note that using get-int with an incorrect address
in int-address is unsafe and could result
in the system crashing or becoming unstable.
See also the address,
get-char,
get-float,
get-long,
get-string,
pack,
and unpack functions.
Gets a 64-bit integer from
the address specified in int-address.
This function is handy when using 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.
Consider the C function foo (from a shared library),
which returns an integer pointer (address of an integer).
Note that using get-long with an incorrect address
in int-address is unsafe and could result
in the system crashing or becoming unstable.
See also the address,
get-char,
get-float,
get-int,
get-string,
pack,
and unpack functions.
Gets a character string from the address
specified in int-address.
This function is helpful when
using imported shared library functions
with import.
Consider the above C function from a shared library,
which returns a character pointer (address to a string).
When a string is passed as an argument,
get-string will take its address as the argument.
Because 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:
See also the get-char,
get-int,
get-float,
pack,
and unpack functions.
Note that get-string can crash the system
or make it unstable if the wrong address is specified.
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,
get-url returns the string ERR: timeout.
When other error conditions occur,
get-url returns a string starting with ERR:
and the description of the error.
get-url requests are also understood by newLISP server nodes.
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 env
function.
The int-timeout can be followed
by an optional custom header in str-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:
newLISP will configure and send
the request and header below:
As an alternative, the str-header
option could be used:
newLISP will now send the
following request and header:
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 put-url
and post-url functions.
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.
global returns the last symbol made global.
The second example shows how constant
and global can be combined into one statement,
protecting and making a previous function definition global.
Checks if symbol in sym is global. Built-in functions, context
symbols, and all symbols made global using the function global
are global:
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.
The second form of if works similarly
to cond, except it does not take
parentheses around the condition-body pair of expressions.
In this form, if can have
an unlimited number of arguments.
The last expression, "n/a", is optional.
When this option is omitted,
the evaluation of (>= x 30)
is returned, behaving exactly like a traditional
cond but without requiring
parentheses around the condition-expression pairs.
In any case, the whole if expression
always returns the last expression or condition evaluated.
See also the unless function.
if-not is equivalent to (if (not
exp-condition exp-1 [exp-2])).
If the value of exp-condition is nil
or the empty list (), exp-1 is evaluated;
otherwise, the optional exp-2 is evaluated.
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,
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.
The inverse operation of ifft
is the fft function.
Imports the function specified in str-function-name
from a shared library named in str-lib-name.
The functions address,
get-char,
get-int,
get-float,
get-string,
pack, and
unpack
can be used to retrieve return values or to unpack data from returned
structure addresses. If the library is not located in the normal library
search path, str-lib-name must contain the full path name.
To transform newLISP data types into the data types needed by the
imported function, use the functions
float for 64-bit double floats,
flt for 32-bit floats,
and 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.
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. 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 returns the address of the function, which can be
used to assign a different name to the imported function.
Note that the Win32 version of newLISP uses standard call stdcall conventions
to call DLL library routines. This is necessary for calling DLLs that belong
to the Win32 operating system (e.g., odbc32.dll). 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.
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).
Increments the number in place by 1 or by the optional number num
and returns the result. inc performs mixed int and float arithmetic according to the rules outlined below.
place is either a symbol or a place in a list structure, or
an other number returned by an expression.
If num is absent, inc always returns
an integer. If the input argument in place is a float and num
is absent, the input argument is truncated to an integer.
Integer calculations (without num) 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.
If num is supplied, inc always returns
the result as floating point, even for integer input arguments.
If the symbol in sym contains nil, it is treated
as if containing 0 or 0.0: Places in a list structure or a number returned by another expression
can be updated too:
Use the dec function for decrementing.
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.
The predicate may be a built-in predicate,
a user-defined function, or a lambda expression.
Use the filter function
to return the elements themselves.
If the value in float is infinite the function returns
true else nil. Note that an integer division by zero e.g. (/ 1 0) will
throw an "division by zero" error and not yield infinity. See also
NaN? to check is a floating point number is valid.
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 + or - sign.
The string must begin with '0x'
for hexadecimal strings or
'0' (zero) for octal strings.
If str is invalid,
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 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).
The inverse function to int with base 2 is
bits. Use the float function
to convert arguments to floating point numbers.
Returns true only if the value
of exp is an integer;
otherwise, it returns nil.
In the first syntax,
intersect returns a list
containing one copy of each element
found both in list-A and list-B.
In the second syntax,
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.
See also the set functions
difference and
unique.
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.
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 array.
invert will return nil
if the matrix is singular and cannot be inverted.
All operations shown here on lists
can be performed on arrays, as well.
See also the matrix functions det,
mat, multiply
and transpose.
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.
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 irr and 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 fv,
nper,
npv,
pmt,
and pv functions.
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.
See also the append,
string,
and explode functions,
which are the inverse of the join operation.
See the description of fn, which is a shorter form of writing lambda. See the description of define-macro. Returns true only if the value of exp is a lambda expression;
otherwise, returns nil.
See define and define-macro for
more information about lambda expressions.
Returns the last element of a list or a string.
In the second version the last character in the string str is returned as a
string.
Note that last works on character boundaries
rather than byte boundaries
when the UTF-8–enabled version of newLISP is used.
See also first, rest and nth.
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
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. For error numbers out of range the string "Unknown error" is
given for the error text. Erros can be trapped by error-event
and userdefined error handlers. See also net-error for errors generated by
networking conditions and sys-error for errors
generated by the operating system.
The token in str is verified as a legal newLISP symbol.
Non-legal symbols can be created using the 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:
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.
Returns the number of elements in a list, the number of rows in
an array, or the number of characters in a string.
length applied to a symbol returns the length of the symbol name.
Applied to a number, length returns the number of bytes needed in
memory to store that number: 4 or 8 for integers and 8 for floating point numbers.
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 let statement. To incrementally use
symbol bindings as evaluated during the initialization of locals in let,
use letn. One or more expressions in exp-body are evaluated using the local
definitions of sym1, sym2 etc. 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. 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:
See also letn for an incremental or nested form of
let.
This functions combines let and 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:
Before the expression '(x y z) gets evaluated, x, y and z
are literally replaced with the initializers from the letex initializer list.
The final expression which gets evaluated is '(1 2 3).
letn is like a nested let and works similarly to let,
but will incrementally use the new symbol bindings when evaluating the initializer expressions
as if several let were nested. In the fully parenthesized first syntax,
initializers are optional and assumed nil if missing. The following comparison
of let and letn show the difference:
While in the first example using let the variable y is
calculated using the binding of x before the let expression,
in the second example using letn the variable y is calculated using
the new local binding of x.
letn works like several nested let. The parentheses
around the initializer expressions can be omitted.
The exp are evaluated and the values used to construct a new list.
Note that arguments of array type are converted to lists.
See also cons and push for other
forms of building lists.
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.
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,
load returns the result of the last expression in the last file evaluated. If a file
cannot be loaded, 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 context switches
will be loaded into the MAIN context.
The str-file-name specs can contain URLs. Both http:// and file://
URLs are supported.
In case expressions evaluated during the load are changing the
context, this will not influence the programming
module doing the load. The current context after the load statement will always be
the same as before the load. Normal file specs and URLs can be mixed in the same load command. 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, 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. 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 / for the directory spec.
Initializes one or more symbols
in sym-1— to nil,
evaluates the expressions in body,
and returns the result of the last evaluation.
local works similarly to let,
but local variables are all initialized to nil.
local provides a simple way
to localize variables
without explicit initialization.
In the first syntax, the expression in num is evaluated and the natural
logarithmic function is calculated from the result.
In the second syntax, an arbitrary base can be specified in num-base.
See also exp, which is the inverse function to log with
base e.
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 Indexing elements of strings and lists.
lookup is similar to assoc but goes one step further
by extracting a specific element found in the list.
See also assoc
Converts the characters of the string
in str to lowercase.
A new string is created,
and the original is left unaltered.
See also the upper-case and
title-case functions.
returns true if exp evaluates
to a lambda-macro expression;
otherwise, nil is returned.
main-args returns a list
with several string members,
one for program invocation
and one for each of
the command-line arguments.
After newlisp 1 2 3 is executed at the command prompt,
main-args returns a list containing the name of
the invoking program and three command-line arguments.
Optionally, 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.
Note that when newLISP is executed from a script,
main-args also returns the name
of the script as the second argument:
Try executing this script with different
command-line parameters.
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.
This example creates a directory named adir
in the current directory with an access mode of
0750 (octal 750 = drwxr-x---).
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.
The second example shows how to dynamically
create a function for map:
We can also use the shorter fn: foo now works like a function-maker:
Note that the quote before the operand can be omitted
because primitives evaluate to themselves in newLISP.
By incorporating map
into the function definition,
we can do the following:
map also sets the internal list index $idx.
The number of arguments used is determined by the length of the first argument list.
Arguments missing in other argument lists cause an error message.
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. case). 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
+, -, *, or /.
This type of arithmetic operator is typically used for integer
operations in newLISP. In the case of mat, however,
all operations will be performed as floating point operations
(add, sub, mul, 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
multiply and invert. Using the second syntax,
all cells in matrix-A
are multiplied with a scalar
in number: See also the other matrix operations det,
invert, multiply,
and transpose.
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 ?, +,
and * can be used in list-pattern.
Wildcard characters may be nested.
match returns a
list of matched expressions.
For each ? (question mark),
a matching expression element is returned.
For each + (plus sign) or
* (asterisk), a list containing
the matched elements is returned.
If the pattern cannot be matched
against the list in list-match,
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 match to work as it did in
versions prior to 8.2.3, showing all list
elements in the returned result.
match is frequently employed as a functor parameter
in find, ref,
ref-all and replace and
is internally used by find-all for lists.
Note that the * operator tries to grab
the fewest number of elements possible,
but match backtracks and grabs more elements
if a match cannot be found.
The + operator works similarly
to the * operator,
but it requires at least one list element.
The following example shows
how the matched expressions
can be bound to variables.
Note that match for strings has been eliminated.
For more powerful string matching, use regex,
find, find-all
or parse.
unify is another function for matching
expressions in a PROLOG like manner.
Evaluates the expressions num-1—
and returns the largest number.
See also the min function.
In the first syntax,
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,
member performs a regular expression search.
In the second syntax,
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.
See also the related functions
slice and
find.
Evaluates the expressions num-1—
and returns the smallest number.
See also the max function.
Calculates the modular value of the
numbers in num-1 and num-2.
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.
Use the % (percent sign)
function when working with integers only.
Evaluates all expressions num-1—,
calculating and returning the product.
mul can perform mixed-type arithmetic,
but it always returns floating point numbers.
Any floating point calculation with
NaN also returns NaN.
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 array.
All operations shown here on lists
can be performed on arrays, as well.
See also the matrix operations det,
invert, mat
and transpose.
Returns as a string, the name of a symbol
without the context prefix.
If the expression in bool
evaluates to anything other than nil,
the name of the symbol's context is returned instead.
When context is supplied,
then name returns the name of the context.
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'.
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 inf? for testing a floating point value for infinity.
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.
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.
Closes a network socket in int-socket that
was previously created by a
net-connect
or net-accept function.
Returns true on success and
nil on failure.
The optional true flag suppresses immediate shutdown
of sockets by waiting for pending data transmissions to finish.
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.
The above program
uses the finger service
on a remote computer.
This service returns information
about an account holder
on this computer.
Some ISP and Unix installations
provide this service.
When executing:
the program tries to connect
to a server named "someSite.com"
and sends the string "johnDoe".
If "someSite.com" is running a finger service,
it sends back information about the account
"johnDoe" on this server.
In case a connection cannot be made,
the function returns the string "no connection."
nameSite is split up into
the account name and host name parts.
net-connect is used to
connect to someSite.com
and returns the socket handle,
which processes incoming data.
In the second syntax, 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.
A local domain file system socket is created and returned.
On the server side, local domain sockets have been created
using net-listen and net-accept.
After the connection has been established the functions net-select,
net-send and 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.
As 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, 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 net-send will send a UDP packet
containing that target address.
When using net-send-to, only one of the
two functions net-connect or net-send-to should
provide a target address. The other function should specify and empty
string "" as the target address. The functions net-receive and
net-receive-from
can both be used and will perform UDP communications when the "udp"
option as been used in net-listen or net-connect.
net-select and net-peek
can be used to check for received data in a non-blocking fashion. net-listen binds a specific
local address and port to the socket. When net-connect is used,
the local address and port will be picked by the socket-stack
functions of the host OS.
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 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 net-listen
together with the UDP multicast option.
On the server side, net-peek or 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 net-send and
net-receive functions
can also be used instead of net-send-to
and net-receive-from.
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.
Note that on the receiving side,
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,
net-listen does not actually put
the receiving side in listen mode,
but rather sets up the sockets
for the specific UDP mode.
The net-select
or net-peek functions
can be used to check for
incoming communications
in a non-blocking fashion.
Retrieves the last error that occurred when calling a any of the
following functions: net-accept,
net-connect,
net-eval,
net-listen,
net-lookup,
net-receive,
net-receive-udp,
net-select,
net-send,
net-send-udp,
and net-service.
Whenever one of these functions fails, it returns nil and net-error
can be used to retrieve more imformation. Functions that communicate using sockets close the socket automatically and
remove it from the net-sessions list. Each successful termination of a net-*
function clears the error number. The following messages are returned: When int-error is specified the number and error text for
that error number is returned. See also last-error and sys-error. 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: 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 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 inetd daemon mode
on how to configure this mode correctly. In the first syntax, 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,
net-eval will wait indefinitely for a response.
Otherwise, if the timeout in milliseconds has expired,
nil is returned; else, the evaluation result of exp
is returned. The second syntax of 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 net-error for a list of
potential error messages. 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 , 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 net-eval
sending 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
put-url or save (with a URL
file name) can be used to transfer programs. The a 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. 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. 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. 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:
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. 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
net-listen. When no str-ip-addr is specified, the current default is returned.
If the 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 multihoned 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 net-error
can be used to report the error. An interface address can be defined as either and IP address or a name. The
return value is the address given in str-ip-addr Listens on a port specified in int-port. A call to net-listen
returns immediately with a socket number, which is then used by
the blocking net-accept function
to wait for a connection. As soon as a connection is accepted,
net-accept returns a socket number
that can be used to communicate with the connecting client. 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 net-listen
to listen on the specified address. In the second syntax, 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 net-accept to accept a client connection;
otherwise, returns nil. 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 net-select,
net-send and 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.
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
net-receive-from
to await incoming UDP data
without using net-accept,
which is only used in TCP communications.
The net-receive-from call
will block until a UDP data packet is received.
Alternatively, net-select
or 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 net-receive-from,
use net-send-to.
Note that net-peer will not work,
as UDP communications do not maintain
a connected socket with address information.
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 net-receive,
net-receive-from,
net-send-to,
net-select,
or net-peek function calls.
Both a UDP server and UDP client
can be set up using net-listen
with the "udp" option.
In this mode, 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 net-listen
and the "udp" option,
the functions net-receive-udp
and net-send-udp
can be used for short transactions
consisting only of one data packet.
net-listen, net-select,
and 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
net-receive-udp
and net-send-udp pair is used,
both sides close the sockets after sending and receiving.
If the optional string str-mode is specified as
"multi" or "m",
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.
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.
On the server side,
net-peek
or net-select
can be used for non-blocking communications.
In the example above,
the server would block
until a datagram is received.
The net-send
and net-receive functions
can be used instead of net-send-to
and net-receive-from.
Returns the IP number and port
of the local computer
for a connection on
a specific int-socket.
Use the net-peer
function to access the remote computer's
IP number and port.
Returns either a hostname string
from str-ip-number
in IP dot format or the IP number
in dot format from str-hostname:
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.
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.
After connecting, the program
waits in a while loop
until aSock can be read.
Use the peek function
to check file descriptors and stdin.
Returns the IP number and port number
of the remote computer
for a connection on int-socket.
Use the net-local function
to access the local computer's IP number and port number.
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 - (hyphen) or
* (star) are not available on IPv6 address mode. In the first syntax, 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. 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 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:
Alternatively, newLISP can be installed
with the set-user-ID bit set to run
in superuser mode.
In the second syntax, 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, 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.
Broadcast or batch mode—as well as normal addresses
and IP numbers or hostnames— can be mixed in one net-ping statement by
putting all of the IP specs into a list.
The second and third lines show how the batch mode of net-ping
can be initiated by specifying the * (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.
net-ping will iterate through all numbers
from either 1 to 254 for the 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, 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 net-ping may return an incomplete list or the empty list ().
In this case, net-error will return a timeout error.
On error, nil is returned and 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 net-ping
invocations. In any case, net-ping will send out packages
as quickly as possible.
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. 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 net-receive is a blocking call
and does not return until the data arrives at int-socket.
Use net-peek
or net-select to find out
if a socket is ready for reading.
Optionally, a wait-string
can be specified
as a fourth parameter.
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.
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.
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,
net-receive is slower than the normal version
because information is read character-by-character.
In most situations, the speed difference can be neglected.
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 net-listen
or 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, net-receive-from
returns nil and closes the socket.
The second line in this example is optional.
Without it, the 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 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.
See also the net-connect function
with the "udp" option and the
net-send-to function
for sending UDP data packets over open connections.
For blocking short UDP transactions,
see the net-send-udp
and net-receive-udp functions.
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, net-receive-udp returns nil.
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 net-receive-udp statement must be set up first.
No previous setup using net-listen
or net-connect is necessary.
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.
See also the net-send-udp
function for sending datagrams and
the pack and 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 net-listen,
or net-connect
together with the "udp" option
to make non-blocking data exchange possible
with net-receive-from
and net-send-to.
In the first form,
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,
net-select can check for a list of sockets
in list-sockets.
The following value can be given for str-mode:
Read, send, or accept operations
can be handled without blocking
by using the net-select function.
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,
net-error is set.
When -1 is specified for int-micro-seconds,
net-select will never time out.
When 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,
net-select will return a list of ready sockets.
The following example would listen on two sockets
and continue accepting and servicing connections:
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
net-error to be set.
Note that supplying a nonexistent socket to net-select
will cause an error to be set in net-error.
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.
net-send returns the number of bytes sent or nil on failure.
On failure, use net-error to get more error information.
The first net-send sends the string "hello there", while
the second net-send sends only the string "hello".
Can be used for either UDP or TCP/IP communications. The socket in int-socket
must have previously been opened with a net-connect
or net-listen function. If the opening functions was used
with the "udp" option, net-listen or 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 net-connect together with net-send-to, then
only one of the functions should specify the remote host. The other should leave
the address as an empty string. In the examples both, the client and the server use 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
net-send-to statement. See also the net-receive-from function
and the net-listen function with the
"udp" option. For blocking short UDP transactions use net-send-udp
and net-receive-udp.
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 net-connect
or net-listen is necessary.
net-send-udp returns immediately
with the number of bytes sent
and closes the socket used.
If no 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 is also suitable
for sending binary information
(e.g., the zero character or other non-visible bytes).
For a more comprehensive example,
see 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:
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 net-connect function
using the "udp" option—together with
the net-send-to function—can
be used to talk to a UDP listener
in a non-blocking fashion.
Makes a lookup in the services database
and returns the standard port number for this service.
Returns nil on failure.
Returns a list of active listening and connection sockets.
In the first syntax,
context-source is the name of an existing context,
and sym-context-target is the name of a new context
to be created just like the original,
with the same variable names and user-defined functions.
If the context in sym-context-target already exists,
then new symbols and definitions are added.
Existing symbols are overwritten
when the expression in bool
evaluates to anything besides nil;
otherwise, the content of existing symbols
will remain.
This makes mixins of context objects possible.
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.
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.
The last lines show how a foreign context
gets merged into the current one
and how map can be used
to merge a list of contexts.
Context symbols need not be mentioned explicitly,
but they can be contained in variables:
The example refers to contexts in variables
and merges context foo into bar.
See also the function def-new
for moving and merging single functions
instead of entire contexts.
See the context function
for a more comprehensive example of new.
If the expression in exp evaluates to nil,
then nil? returns true;
otherwise, it returns nil.
The nil? predicate
is useful for distinguishing between
nil and the empty list ().
Note that nil? means strictly nil
while true? means everything not nil or the
empty list ().
In the first form, 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 seed function.
In the second form,
normal returns a single
normal distributed floating point number:
See also the random
and rand functions
for evenly distributed numbers,
amb for randomizing evaluation
in a list of expressions,
and seed for setting a different start point
for pseudo random number generation.
If exp evaluates to nil,
then true is returned;
otherwise, nil is returned.
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-offset.
This causes the time to be shifted forward or backward in time,
before being split into separate date values. The numbers represent the following date-time fields: 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 microsecond field
depends on the operating system and platform. On some platforms,
the last three digits of the microseconds field are always
0 (zero). On some platforms, the daylight savings flag is not active and
returns 0 (zero) even during daylight savings time. Depending on the geographical area the daylight time savings type
has a different value from 1 to 6: See also the date, date-value,
time, and time-of-day functions.
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 num-fv is omitted,
the future value of the loan is assumed to be 0.0.
If payment is at the end of the period,
int-type is 0;
else it is 1.
If int-type is omitted,
0 is assumed.
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 fv,
irr,
npv,
pmt,
and pv functions.
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.
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 fv,
irr,
nper,
pmt,
and pv functions.
In the first syntax group nth uses int-index an index into the
list, array or str found and returning the element found
at that index. See also 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. The list L can be the context of the default functor L:L.
This allows lists passed by reference: 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 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
nth may be more readable in some situations.
nth works on arrays just like it does on lists:
In the String version, nth returns the character found at the position
int-index in str and returns it as a string. Note that nth works on character boundaries rather than byte
boundaries when using the UTF-8–enabled version of newLISP. See also setf for modifying multidimensional lists and arrays and
push and pop for modifying lists.
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,
null? returns nil.
The predicate null? is useful in conjunction with the functions
filter or clean to check the outcome of other newLISP operations.
See also the predicates empty?,
nil?
and zero?.
true is returned only if exp evaluates to a floating point number or an integer;
otherwise,
nil is returned.
See the functions float? and integer? to test for a specific number type.
The str-path-file is a file name,
and str-access-mode is a string specifying the file access mode.
open returns an integer,
which is a file handle to be used on subsequent read or write operations on the file.
On failure,
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:
The first example uses open to set the device for 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 close on (device)
automatically resets 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 exec or import function:
The named pipe can now be used like a file with open,
read-buffer,
and write-buffer.
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 or expression.
ostype is a built-in system constant
containing the name of the operating system
newLISP is running on. 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: Use 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 System Symbols and Constants in the
appendix.
Packs one or more expressions (exp-1 to exp-n)
into a binary format specified in the format string str-format,
returning the binary structure in a string buffer.
The symmetrical unpack function is used
for unpacking. The expression arguments can also be given in a list.
pack and unpack are useful
when reading and writing binary files
(see read-buffer and
write-buffer)
or when unpacking binary structures
from return values of imported C functions
using import.
The following characters are used in str-format:
Note that newLISP only supports 32-bit, signed integers
and treats lu and ld the same way internally.
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.
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: Note that the list should be referenced directly in 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 > and < specifiers
can be used to switch between little endian
and big endian byte order
when packing or unpacking:
Switching the byte order will affect all number formats with 16-,
32-,
or 64-bit sizes.
The pack and unpack format need not be the same:
The examples show spaces between the format specifiers.
These are not required but can be used to improve readability.
See also the address,
get-int,
get-long
get-char,
get-string,
and unpack functions.
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,
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-data 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.
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),
quotes can be used to limit the pattern.
In this case,
double backslashes must be used
inside the pattern.
The last pattern could be used
for parsing CVS files.
For the regular expression option numbers,
see regex.
parse will return empty fields
around separators
as empty strings:
This behavior is needed
when parsing records
with empty fields.
Parsing an empty string
will always result
in an empty list.
Use the regex function
to break strings up
and the directory,
find,
find-all,
regex,
replace,
and search functions
for using regular expressions.
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 date.
The function parse-date returns the number of seconds passed
since January 1, 1900. This function is not available on Win32 platforms. See the date function for all possible format descriptors.
Returns the number of bytes ready to be read on a file descriptor;
otherwise,
it returns nil if the file descriptor is invalid.
peek can also be used to check stdin.
This function is only available on Unix-like operating systems.
Use the net-peek function
to check for network sockets,
or for the number of available bytes on them.
On Unix systems,
net-peek can be used
to check file descriptors.
The difference is that
net-peek also sets
net-error.
Creates an inter-process communications pipe and returns the
read and write handles to it within a list.
The pipe handles can be passed to a child process launched via
process or to 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 read-line blocks until a newline character is received.
A read-buffer 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 open function for further information.
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).
When paying at the end of each period,
num-type is 0 (zero); otherwise,it is 1.
If omitted,
int-type is assumed to be 0 (zero) for payment at the end of a period.
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 fv,
irr,
nper,
npv,
and pv functions.
Using pop, elements can be removed from lists and characters from strings.
In the first syntax, 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 Indexing elements of strings and lists.
In the second version,
indices are specified in the list list-indexes.
This way,
pop works easily together with ref
and ref-all,
which return lists of indices.
pop changes the contents of the target list.
The popped element is returned.
pop can also be used on strings with one index: Popping an empty string will return an empty string.
See also the push function, the inverse operation to pop.
Removes an association referred to by the key in exp-key from the association
list in list-assoc and returns the popped expression. See also assoc for retrieving associations and setf
for modifying association lists.
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 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 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.
The above example uploads a user name and city using a special format called
application/x-www-form-urlencoded.
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,
post-url assumes application/x-www-form-urlencoded as the default content type.
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 get-url for details on both of these options.
See also the get-url and put-url functions.
Calculates num-1 to the power of num-2 and so forth.
When num-1 is the only argument,
pow assumes 2 for the exponent.
Reformats expressions for print,
save,
or source.
The first parameter,
int-length,
specifies the maximum line length,
and str-tab specifies the string used to indent lines.
All parameters are optional.
pretty-print returns the current settings or the new settings when one or both parameters are specified.
The first example reports the default settings of 64 for the maximum line length and a
TAB character for indenting.
The third example changes the line length only.
Note that pretty-print cannot be used to prevent line breaks from being printed.
To completely suppress pretty printing,
use the function string to convert the expression to a raw unformatted string as follows:
Evaluates and tests if exp is a primitive symbol and returns
true or nil depending on the result.
Evaluates and prints exp-1—
to the current I/O device,
which defaults to the console window.
See the built-in function 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 \:
To finish printing with a line-feed,
use println.
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 device for details on how to specify a different I/O device.
println works exactly like print but emits a line-feed character at the end.
See also the write-line and print functions.
Returns the probability Q of an observed Chi²
statistic in num-chi2 with num-df degrees of freedom to be equal to or greater than.
prob-chi2 is derived from the incomplete Gamma function gammai.
See also the inverse function crit-chi2.
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.
See also the inverse function crit-z.
In the first syntax,
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 destroy, if the process does
not exit by itself. If the path of the executable is unknown, exec together with the Unix which
command can be used to start a program. The pid returned can be used to 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 write-line
and read-line or write-buffer and
read-buffer statements: 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 this case,
peek can be used to check for information on the pipe handles:
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:
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 pipe and share functions for inter-process
communications and the semaphore function for synchronization of several processes.
See the fork function for starting separate newLISP processes on Linux/Unix.
Refines the prompt as shown in the interactive newLISP shell. sym | fun
is either a symbol of a user-defined or the lambda function directly: The current context before calling the prompt-event code is passed as a
parameter to the function. The example redefines the > prompt to be the current context followed
by a colon :, followed by the directory name, followed by the dollar symbol.
Together with the command-event function this can be
used to create fully customized shells or custom command interpreters. The function in prompt-event must return a string of 63 characters maximum.
Not returning a string will leave the prompt unchanged. Checks if a symbol in sym is protected. Protected symbols are built-in
functions, context symbols, and all symbols made constant using the constant
function:
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. 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 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, push works easily together
with ref and 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 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.
push and pop can be combined to model a queue: Because push returns a reference to the list it modified pop
can work on it directly.
See also the pop function, which is the inverse operation to push.
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.
put-url will return ERR:
timeout when the host gives no response and the timeout expires.
On other error conditions,
put-url returns a string starting with ERR: and the description of the error.
put-url requests are also understood by newLISP server nodes.
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.
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:
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.
put-url returns content returned by the put.cgi script.
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 get-url for details on both of these options.
See also the functions get-url and post-url,
which can be used to upload files when formatting form data as multipart/form-data.
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-pmt is assumed to be 0.0 if omitted.
If payment is at the end of each period,
0 (zero) is assumed for int-type;
otherwise, 1 is assumed.
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 fv,
irr,
nper,
npv,
and pmt functions.
Returns exp without evaluating it.
The same effect can be obtained by prepending a ' (single quote) to exp.
Evaluates and tests whether exp is quoted.
Returns true or nil depending on the result.
Note that in the set statement,
''x is quoted twice because the first quote
is lost during the evaluation of the set assignment.
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.
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 random
and normal functions
to generate floating point
random numbers,
and use seed to vary
the initial seed
for random number generation.
In the first form,
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 seed.
When used in the second form,
random returns a single
evenly distributed number:
See also the normal
and rand functions.
Rearranges the order of elements in list
into a random order.
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.
randomize uses
an internal pseudo random sequence generator
that returns the same series of results
each time newLISP is started.
Use the seed function to
change this sequence.
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 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.
Optionally,
a string to be waited for
can be specified in str-wait.
read-buffer 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.
Reads 200 bytes into the symbol buff
from the file aFile.ext.
Reads 1000 bytes or until
the string password: is encountered.
The string password:
will be part of the data returned.
See also the write-buffer function.
Reads a byte from a file specified
by the file handle in int-file.
The file handle is obtained from
a previous open operation.
Each read-char advances
the file pointer by one byte.
Once the end of the file is reached,
nil is returned.
Use read-line
and device to read
whole text lines at a time.
Note that newLISP supplies
a fast built-in function
called copy-file
for copying files.
See also the write-char function.
read-expr parses the first expressions it finds in str-source and
an returns the translated expression without evaluating it. An optional context in
sym-context specifies a namespace for the translated expression. After a call to 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 read-expr repeatedly this number
can be updated using $0. read-expr behaves similar to eval-string
but without the evaluation step: Using read-expr a customized code reader can be programmed
preprocessing expressions before evaluation. Reads a file in str-file-name in one swoop and returns a string buffer
containing the data.
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.
read-file can take an http://
or file:// URL in str-file-name.
When the prefix is http://, read-file works exactly like
get-url and can take the same additional parameters.
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, read-file can also be used
to transfer files from remote newLISP server nodes. See also the write-file and
append-file functions.
Reads a key from the keyboard and returns an integer value.
For navigation keys, more than one 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.
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 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).
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 device
is the keyboard (device 0).
Use the built-in function 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 open statement.
The last buffer contents
from a read-line operation
can be retrieved using current-line.
When read-line is reading from a file or from stdin
in a CGI program or pipe, it will return nil when input is exhausted.
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 write-line statement
takes advantage of the fact
that the result from the last
read-line operation
is stored in a system internal buffer.
When write-line
is used without argument,
it writes the contents
of the last read-line buffer
to the screen.
See also the current-line function
for retrieving this buffer.
Reads an UTF-8 character from a file specified by the file handle in int-file.
The file handle is obtained from a previous open operation.
Each 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 fucntion returns and integer value which can be converted to a displayable UTF-8
character string using the char function. The example reads a file containing UTF-8 encoded text and displays it to the
terminal screen.
Returns the full path
from the relative file path
given in str-path.
If a path is not given,
"." (the current directory) is assumed.
The output length is limited
by the OS's maximum allowed path length.
If real-path fails
(e.g., because of a nonexistent path),
nil is returned.
The function is used for message exchange between child processes
launched with spawn and their parent process. The
message received replaces the contents in sym-message. The function returns nil if no message is pending to be read. For a more detailed discussion of this function and examples, see the
send function.
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. ref can work together with push and
pop, both of which can also take lists of indices. The optional func-compare contains a comparison operator
or function. In this case the system variable $0 contains
the last expression found. The first flat syntax should only be used if exp-key is not a
parenthesized unquoted expression to avoid ambiguity.
The following example shows the use of
match and unify
to formulate searches that are as powerful as regular expressions are
for strings:
The '(X X) pattern with unify searches for a list pair
where the two elements are equal. The 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. Using the new parenthesized syntax, the list can be passed by a context
identifying a default functor: This is suitable when passing lists by reference using a context. See also
the chapter Passing data by reference. See also the ref-all function, which searches for all occurrences
of a key expression in a nested list. Works similarly to ref, but returns a list of all index vectors found
for exp-key in list.
By default, ref-all checks if expressions are equal. With func-compare, more
complex comparison functions can be defined. The first flat syntax should only be used if exp-key is not a
parenthesized unquoted expression.
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 long?).
Using the match and unify functions, list
searches can be formulated that are as powerful as regular expression searches are
for strings.
See also the ref function. 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 directory,
find, find-all,
parse, replace,
and search when using these functions on strings.
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.
Addtionally an int-option can be specified to control certain
regular expression options explained later. The additional int-offset
parameter tells 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 regex results are given based
on single bytes even when running the UTF-8 enabled version of newLISP.
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.
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.
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:
The following constants can be used for int-option.
Several options can be combined using a binary or | (pipe).
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 replace;
it can be combined with PCRE options.
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: 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
for further references and manual pages. Regular expression patterns can be precompiled for higher speed when using
changing repetitive patterns with regex-comp. 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. regex-comp
can be used to pre-compile repetitive patterns to speed up regular
expression searches: 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 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 replace.
Removes the directory
whose path name is specified in str-path.
The directory must be empty for remove-dir to succeed.
Returns nil on failure.
Removes the directory temp
in the current directory.
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.
If the second argument is a list, 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 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 = (equals sign).
Using the match and unify functions,
list searches can be formulated that are as powerful as regular expression string
searches:
The last form of replace has only two arguments: the expression exp
and list. This form removes all exps found in list.
If all arguments are strings, 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 replace
can also process binary 0s (zeros).
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 regex above for details.
By default, 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
replace to replace only the first occurrence. The changed string is returned.
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.
The setf function together with nth,
first or last can also
be used to change elements in a list.
See directory,
find,
find-all,
parse,
regex,
and search
for other functions using regular expressions.
In the first syntax, reset returns to the top level of evaluation,
switches the trace mode off, and switches to the MAIN
context/namespace. 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.
reset may return memory that was claimed by newLISP
to the operating system. reset walks through the entire cell space,
which may take a few seconds in a heavily loaded system. reset occurs automatically after an error condition. In the second syntax, 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/local/bin/newlisp instead of only newlisp. This mode is
not available on Win32. Returns all of the items in a list or a string, except for the first.
rest is equivalent to cdr or tail in other Lisp dialects.
In the second version, rest returns all but the first character
of the string str in a string.
See also the first and last functions.
Note that an implicit rest is available for lists.
See the chapter Implicit rest and slice.
Note that rest works on character boundaries rather
than byte boundaries when the UTF-8–enabled version of newLISP is used.
In the first form,
reverse reverses and returns the list.
Note that reverse is destructive and
changes the original list.
In the second form,
reverse is used to reverse the order
of characters in a string.
See also the sort function.
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,
rotate rotates 1 to the right.
rotate is a destructive function
that changes the contents of
the original list or string.
When working on a string,
rotate works on byte boundaries
rather than character boundaries.
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. Note that rounding for display purposes is better accomplished using
format.
In the first syntax,
the save function writes
the contents of the newLISP workspace
(in textual form) to the file str-file.
save is the inverse function of load.
Using load on files
created with save causes
newLISP to return to the same state
as when save was originally invoked.
System symbols starting with the $ 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 $ character
are not saved.
Specifying system symbols explicitly
causes them to be saved.
Each symbol is saved
by means of a set statement or—if
the symbol contains a lambda or lambda-macro function—by
means of define
or define-macro statements.
save returns true on completion.
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,
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.
save in HTTP mode will
observe a 60-second timeout.
Symbols made using sym
that are incompatible with the normal syntax rules for symbols
are serialized using a sym statement
instead of a set statement.
save serializes contexts and symbols
as if the current context is MAIN.
Regardless of the current context,
save will always generate the same output.
See also the functions load
(the inverse operation of save)
and source,
which saves symbols and contexts to a string
instead of a file.
Searches a file specified by its handle in int-file for a string in str-search.
int-file can be obtained from a previous 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 regex for details.
If int-options is mot specified a faster, plain string search is performed.
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. The file init.lsp is opened and searched for the string 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 directory,
find,
find-all,
parse,
regex,
and replace.
Seeds the internal random generator
that generates numbers for amb,
normal,
rand,
and 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.
After using seed with the same number,
the random generator starts the same sequence of numbers.
This facilitates debugging
when randomized data are involved.
Using 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.
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, seek returns the current
position in the file. If int-file is 0 (zero),
on BSD, seek will return the number of characters printed to STDOUT,
and on Linux and Win32, it will return -1. On failure, seek
returns nil. When int-position is set to -1,
seek sets the file pointer to the end of the file. 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.
newLISP supports file position numbers up to
9,223,372,036,854,775,807.
In the first two forms,
select picks one or more elements
from list using one or more indices
specified in list-selection or the int-index_i.
In the second two forms,
select picks one or more characters
from string
using one or more indices specified in list-selection
or the int-index_i.
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.
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 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 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 semaphore function returns nil.
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: The following example shows semaphores controlling a child process:
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 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 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 fork function to start a new process
and the share function to share information between
processes. For a more comprehensive example of using 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. The send function enables communication between
parent and child processes started with spawn.
Parent processes can send an receive messages to and from
their child processes. A proxy technique – shown further
down – is employed to communicate between process
peers. send and receive do not require
locks or semaphores. Processes started using fork or
process can not use send and receive
message functions, but should use share instead. The content of a message may be any newLISP expression: atomic
expressions like boolean constants, numbers or strings, or any
list expression in valid newLISP syntax. The size of data is unlimited.
For sizes less then the shared memory pagesize, transfer is fastest and
handled by a shared memory interface. For data sizes exceeding the page
size, files are used internally as the medium of transfer. 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 previous message to the same int-pid has not
been read yet by the targeted recipient,
then nil will be returned trying to send a new message. If
the mssage could be sent succesfully then true is returned. The targeted recipient of the message is the parent process: A second message sent by the child process would fail
by returning nil if sent before the first was retrieved.
Trying to pick up the message before it was delivered would fail too
and return nil. Using the until looping function, the
message statement can be repeated until it returns a value
not nil. This way the non-blocking message
function can be made blocking until it succeeds: The sender statement blocks until the message could be deposited
in the recipients mailbox. The receive statement blocks until a new message could be read. As the until statements in this example lack body expressions,
the last value of the evaluated conditional expression is returned. 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 mailbox not picked up yet by the recipient. The example shows
5 child processes constantly delivering status data to a parent
process which will display the data: Running above example produces the following output: Message exchange is synchronous in above code. The sender blocks until a message
can be deposited in an empty mailbox. For an asynchronous message transfer example
see the Code Patterns
document. A timeout mechanism could be part of an until or while
loop to stop waiting after certain time has exspired. 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. The most powerful feature of the message functions is the ability
to send code pieces, which are evaluated by the recipient. Because
messages can contain any expression, they can be transmitted and
evaluated by the recipient using eval. The following example shows how a parent process acts like a message
proxy receiving messages from a child process routing them to another
child process. In effect this implements messages between peer child
processes. The implementarion relies on the fact
that the recipient can evaluate expressions contained in messages
received. These expressions can in turn be statements: Child process pidA sends three messages to pidB.
As this cannot be done directly pidA sends message
statements to the parent for evaluation. The statement: will be evaluated in the environment of the parent process. Even so the
variable pidA and pidB are bound to nil in
thr sender process pidA, in the parent process they will be
bound to the correct pid numbers. After sending the three messages the statement: is sent to the parent process and once evaluated, it will cause the until
loop to finish.
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).
Note that the step size must be a positive number,
even if sequencing from a higher to a lower number.
Use the series function
to generate geometric sequences.
In the first syntax, 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 series
returns an empty list. In the second syntax, series uses a function specified in func
to transform the previous expression in to the next expression: 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 series statement. The series function also updates the internal list $idx
index value, which can be used inside func. Use the sequence function to generate arithmetic sequences.
Evaluates both arguments and then assigns the result of exp
to the symbol found in sym. The 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.
set can take multiple argument pairs. The symbol for assignment could be the result from another newLISP expression:
Symbols can be set to lambda or lambda-macro expressions.
This operation is equivalent to using define
or define-macro. is equivalent to: is equivalent to:
Use the constant function (which works like set)
to protect the symbol from subsequent alteration. Using the setq
or setf function eliminates the need to quote the variable symbol.
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. 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.
By default, newLISP starts up with the POSIX C default locale. This guarantees that
newLISP's behavior will be identical on any platform locale: 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 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.
Since version 8.4.4, newLISP has been parsing decimal comma numbers correctly. Note that using 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 Switching the locale.
Searches for exp-key in list and replaces the found element with
exp-replacement. The list can be nested. The system variables
$it and $0 contains the expression found and can be used in
exp-replacement. The function returns the old replaced element. data could be the context identifier of a default function for passing lists by reference: For examples on how to use func-compare see set-ref-all See also set-ref, which returns the whole changed list
instead of the old element, but otherwise works identically. For changing all
occurrences of an element in a list use set-ref-all. 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 $0
contains the expression found and can be used in exp-replacement. Using the default functor in the (list key) pattern allows the
list to be passed by reference to a user-defined function containing a set-ref-all
statement. This would result in less memory usage and higher speeds in when doing replacements
in large lists: When evaluating (foo data), the list in db:db will be passed
by reference and set-ref-all will make the changes on the original, not on
a copy of db:db. Like with find, replace,
ref and ref-all,
complex searches can be expressed using
match or unify in func-compare: The example sums all numbers found in records starting with the symbol oranges.
Instead of the system variable $it. $0 could be used as well. See also set-ref which replaces only the first element found.
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
set, setq and setf can take multiple argument pairs.
Although both setq and setf point to the same built-in function internally,
throughout this manual setq is used when setting a symbol reference and setf
is used when setting list or array references. 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: Any function returning a list, array or string or a list,array or string element can be
used together with setq or setf. It is important that the list or array
is referenced by a symbol and not a free list, array or free element. In that case an error
exception will be produced: Although the small lists (a b c) and (d e f) are
referenced by l1 and l2, the list produced by
append is a new object not referenced by a symbol.
In the first syntax,
the sgn function is a logical function
that extracts the sign of a real number
according to the following rules:
x > 0 : sgn(x) = 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.
nil is returned.
Any expression or constant can be used for
exp-1, exp-2, or exp-3.
Accesses shared memory
for communicating between
several newLISP processes.
When called without arguments,
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 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 share,
supplying only the shared memory address or handle.
the return value will be any constant or expression (since v.10.1.0)
written into the memory previusly.
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 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. 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 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.
Sets a user-defined handler in sym-handler for a signal specified in int-signal
or sets to a function expression in func-handler.
If nil is specified,
the signal handler will be set to SIG_IGN, and the signal will be ignored.
Specifying true will set the signal handler to SIG_DFL, the default handler
of the underlying platform OS. 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. 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:
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: 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 destroy: If newLISP receives a signal while evaluating another function,
it will still accept the signal and the handler function will be executed: 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. In this example, all signals from 1 to 8 are set to the same handler.
Evaluates one or more expressions in exp-1—.
silent is similar to 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 silent
to get the prompt back.
Calculates the sine function
from num-radians
and returns the result.
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. Gives up CPU time to other processes for the amount of
milliseconds specified in num-milli-seconds.
On some platforms, 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. In the first form, 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,
slice will take the parameter as offset counting from the end and copy
up to that offset. If the parameter is omitted,
slice copies all of the elements to the end of the list.
See also Indexing elements of strings and lists.
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.
slice also works on string buffers containing binary data like 0's (zeroes).
It operates on byte boundaries rather than character boundaries.
See also Indexing elements of strings and lists. Note that slice always works on single 8-bit byte boundaries for
offset and length numbers, even when running the UTF-8 enabled version of newLISP.
Note that an implicit slice
is available for lists.
See the chapter Implicit rest and slice.
Be aware that slice
always works on byte boundaries
rather than character boundaries
in the UTF-8–enabled version of newLISP.
As a result,
slice can be used
to manipulate binary content.
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:
The sort is destructive,
changing the order of the elements in the original list.
The return value of 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.
Works almost identically to 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,
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 $ (dollar sign) character
are only serialized when mentioned explicitly.
Symbols not belonging to the current context
are written out with their context prefix.
As with save,
the formatting of line breaks
and leading spaces or tabs
can be controlled using the
pretty-print function.
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 sync is executed. 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. Note that on Win32, spawn cannot launch child processes and will work
just like a set assigning the evaluation result of exp to
sym. After successfully starting a child process, the 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: 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 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, sync
will stop waiting and return true. When the time specified was
nsufficient , sync will return nil and another
sync statement could be given to further wait and collect results.
A short timeout time can be used to do other processing during waiting: sync when used without any parameters, will not wait but immediately
return a list of pending child processes. For the primes example, the following
sync expression could be used to watch the progress: A parameter of -1 tells sync to wait for a very long time
(~ 1193 hours). A better solution would be to wait for a maximum time,
then abort all pending child processes: The three functions spawn, sync and abort
are part of the 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 sendM and
receive functions. spawn can be called recursively from spawned subtasks: 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. The example
also shows how code written for the Cilk API will work under Win32, too,
with spawn simply working as a set and
sync just returning an empty list. Since version 10.1 a send and 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.
Calculates the square root from
the expression in num
and returns the result.
In the first version,
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 regex for valid option numbers.
In the second version,
starts-with checks to see if a list
starts with the list element in exp.
true or nil is returned
depending on outcome.
See also the ends-with function.
Translates into a string anything that results
from evaluating exp-1—.
If more than one expression is specified,
the resulting strings are concatenated.
If a buffer passed to string
contains \000,
only the string up to the first terminating zero will be copied:
Use the append
and join
(allows the joining string
to be specified) functions
to concatenate strings containing zero bytes.
Use the source function
to convert a lambda expression
into its newLISP source string representation.
Evaluates exp and tests
to see if it is a string.
Returns true or nil
depending on the result.
Successively subtracts
the expressions in num-1,
num-2—.
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.
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 nth,
first, last or implicit
indexing or places referenced by assoc
or lookup. swap is a destructive operation that changes the contents of the
lists, arrays, or symbols involved. Any two places can be swept in the same or different objects. When int-timeout in milliseconds is specified, sync waits
for child processes launched with spawn to finish.
Whenever a child process finishes, sync assigns the evaluation result
of the spawned subtask to the symbol specified in the spawn statement.
The 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 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, sync returns a list of pending child process
PIDs (process identifiers), for which results have not been processed yet. On Win32, sync has no function and returns an empty list ()
if called with no parameters, or true if given with a timeout. When 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,
sync returns immediately. The function sync is part of the Cilk API for synchronizing
child processes and process parallelization. See the reference for the
function spawn for a full discussion of the Cilk API.
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.
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 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,
sym returns nil
if the symbol looked up does not exist.
Using this last form,
sym can be used
to check for the existence
of a symbol.
Because the function sym
returns the symbol looked up or created,
expressions with sym can be embedded
directly in other expressions
that use symbols as arguments.
The following example shows
the use of sym
as a hash-like function
for associative memory access,
as well as symbol configurations
that are not legal newLISP symbols:
The last statement shows
how a symbol can be eliminated
using delete.
The third syntax allows symbols to be used
instead of strings for the symbol name
in the target context.
In this case,
sym will extract the name from the symbol
and use it as the name string
for the symbol in the target context:
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 context function can also be used to
create, set and evaluate symbols.
Evaluates the exp expression
and returns true if the value is a symbol;
otherwise, it returns nil.
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.
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.
The quote can be omitted
because contexts evaluate to themselves.
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 errror 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, sys-error can be checked
for the underlying reason. For file operations,
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. See also last-error and net-error. Calling sys-info without int-idx returns a list of internal
resource statistics. Eight integers report the following status: 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.
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.
Calculates the tangent function from num-radians
and returns the result.
Calculates the hyperbolic tangent of num-radians.
The hyperbolic tangent is defined mathematically as: sinh (x) / cosh (x).
Works together with
the catch function.
throw forces the return of a previous catch statement
and puts the exp into the result symbol of catch.
The last example shows a shorter form of catch,
which returns the throw result directly.
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 begin block will return X
if (foo X) is true;
else Y will be returned:
throw will not cause an error exception.
Use throw-error
to throw user error exceptions.
Causes a user-defined error exception
with text provided by evaluating exp.
The user error can be handled
like any other error exception
using user-defined error handlers
and the error-event function,
or the form of catch
that can capture error exceptions.
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. 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 date,
date-value,
time-of-day,
and now. Returns the time in milliseconds since the start of the current day.
See also the date,
date-value,
time,
and now functions. 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 3 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- for func-event-handler,
timer returns the elapsed time of the timer in progress.
This can be used to program timelines or schedules.
timer called without arguments
returns the symbol of the current event handler.
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 timer,
use the following pattern,
which calls net-select
to test if a socket is ready for reading:
In this example,
the until loop will run
until something can be read from socket,
or until ten seconds have passed
and the timeout variable is set.
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.
See also the lower-case
and upper-case functions.
Tracing is switched on when bool evaluates to anything
other than nil. When no argument is supplied,
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 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.
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.
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 debug function
as a shortcut for the above example.
Sets the characters or string of characters used to enclose expressions
during trace. By default,
the # (number sign) is used to enclose the expression highlighted
in 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.
The first example replaces the default # (number sign)
with a >> and <<. 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. Transposes a matrix by reversing the rows and columns
and converting all of the cells to floating point numbers.
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 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 array. 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,
transpose will assume nil for those missing elements.
Superfluous elements in a row will be ignored. 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: All operations shown here on lists can also be performed on arrays.
See also the matrix operations
det, invert,
mat and multiply.
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.
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.
If the expression in exp
evaluates to anything other than nil
or the empty list (),
true? returns true;
otherwise, it returns nil.
Since version 9.1, true? behaves like if
and rejects the empty list () Converts ASCII/UTF-8 character strings in str
to UCS-4–encoded Unicode of 4-byte integers per character.
This function is only available on UTF-8–enabled versions
of newLISP. On big endian CPU architectures, the byte order will
be reversed from high to low. The unicode and
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.
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.
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,
unify returns an empty list.
newLISP uses a modified J. Alan Robinson unification algorithm
with occurs check.
Like match, unify is frequently
employed as a parameter functor in find,
ref, ref-all and
replace.
unify can take an optional binding
or association list in list-env.
This is useful when chaining unify expressions
and the results of previous unify bindings
must be included:
In the previous example,
X was bound to 123 earlier
and is included in the second statement
to pre-bind X.
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 expand
can be used to actually replace bound variables
with their terms:
The function bind can be used to set unified
variables: This can be used for de-structuring: unify returns an association list and bind binds the associations.
The following example shows how propositional logic
can be modeled using unify
and expand:
The following is a more complex example
showing a small, working PROLOG (Programming in Logic)
implementation.
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 expand
from the definition of prove-rule
and by passing the environment, e,
as an argument to the 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 eval in each rule term.
Returns a unique version of list
with all duplicates removed.
Note that the list does not need to be sorted,
but a sorted list makes unique perform faster.
The functions difference
and intersect work with sets.
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 unless does not have an else condition as in
if, or if-not the statements in body need
not to be grouped with begin: See also the function when.
Unpacks a binary structure
in str-addr-packed
into newLISP variables
using the format in str-format.
unpack is the reverse operation of pack.
Note that str-addr-packed
may also be an integer representing a memory address.
This facilitates the unpacking of structures
returned from imported, shared library functions.
The following characters may define a format:
The > and < specifiers
can be used to switch between
little endian and big endian byte order
when packing or unpacking:
Switching the byte order
will affect all number formats
with 16-, 32-, or 64-bit sizes.
The pack and unpack format
need not be the same,
as in the following example:
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 address,
get-int,
get-long,
get-char,
get-string,
and pack functions.
Evaluates the condition in exp-condition body.
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 until expression. If
body is empty, the result of last exp-condition
is returned. until works like
(while (not …)).
until also updates the system iterator symbol $idx.
Use the do-until function
to test the condition after evaluation
of the body expressions.
Returns a copy of the string in str converted to uppercase.
International characters are converted correctly.
See also the lower-case
and title-case functions.
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. The utf8 function can also be used
to test for the presence of UTF-8–enabled newLISP:
On big endian CPU architectures, the byte order will be reversed
from highest to lowest. The utf8 and 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.
Returns the number of characters in a UTF-8–encoded string.
UTF-8 characters can be encoded in more than one 8-bit byte.
utf8len returns the number of UTF-8 characters in a string.
This function is only available on UTF-8–enabled versions of newLISP. See also the unicode and utf8 functions.
Above Chinese text from UTF-8 Sampler.
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 RFC 4122
for details on UUID generation.
Each invocation of the 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.
Waits for a child process specified in int-pid to end. The child process was
previously started with process or 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, 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 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.
The process my-process is started,
then the main program blocks
in the wait-pid call
until my-process has finished.
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 when does not have an else condition as in
if, the statements in body need not to be grouped with
begin: See also the function unless working like
(when (not ...) ...). 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 while expression.
while also updates the system iterator symbol $idx.
Use the do-while function to evaluate the condition
after evaluating the body of expressions.
Using the first syntax, write-buffer writes int-size bytes
from a buffer in str-buffer to a file specified in int-file,
previously obtained from a file open operation. If int-size
is not specified, all data in sym-buffer or str-buffer is written.
write-buffer returns the number of bytes written
or nil on failure.
The code in the example writes 100 bytes to the file myfile.ext
from the contents in data.
Using the second syntax, write-buffer appends contents from a string
specified in sym-buffer or str-buffer to the string specified
in str-device, which acts like a stream device.
The above example appends a string to str five times. This method is
much faster than using append when concatenating to a string
in place. See also the read-buffer function.
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
open operation. Each write-char advances the file pointer
by one 8-bit byte. write-char returns the number of bytes written.
Use the print
and device functions
to write larger portions of data at a time.
Note that newLISP already supplies a faster
built-in function called
copy-file.
See also the read-char function.
Writes a file in str-file-name with contents in str-buffer
in one swoop and returns the number of bytes written. The file myfile is read, encrypted using the
password secret, and written back into the new file myfile.enc
in the current directory.
write-file can take an http:// or file:// URL
in str-file-name. Whe the prefix http:// is used,
write-file works exactly like put-url
and can take the same additional parameters: The file message.txt is created and written at a remote location,
http://asite.com, with the contents of str-buffer.
In this mode, write-file can also be used to transfer files
to remote newLISP server nodes. See also the append-file
and read-file functions. The string in str and the line termination character(s)
are written to the device specified as either int-file
or str-device. When the string argument is omitted
write-line writes the contents of the last
read-line to either int-file
or str-device. If the first argument is omitted too then it
writes to to standard out (STDOUT) or to whatever device is set by
device. write-line returns the number of bytes written.
The first example opens/creates a file, writes a line to it,
and closes the file. The second example shows the usage of write-line
without arguments. The contents of init.lsp are written to the console
screen.
In the second syntax, a string can be specified
as a device in str-device (like the write-buffer
function). When a string device is written to, the string in str-device
gets appended with str and the line termination character(s). Registers a function in symbol sym or in lambda function func
to monitor HTTP byte transfers initiated by get-url,
post-url or put-url or initiated
by file functions which can take URLs like load,
save, read-file,
write-file and append-file.
E.g. whenever a block of data requested with get-url
arrives the function in sym or func will be called with
the accumulated number of bytes transferred. Likewise when sending data with
post-url or any of the other data sending
functions, sym or func will be called with the number of
bytes already transferred. The computer output is shown in bold. Whenever a block of data is received
the accumulated byte size is printed. Insteead of defining the handler
function directoy with a lambda function in func, a symbol
containing a function definition could have been used: This can be used to monitor the progress of longer
lasting byte transfers in HTTP uploads or downloads.
Returns a list of error information
from the last 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).
Parses a string containing XML 1.0 compliant, well-formed XML.
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 assoc.
When xml-parse fails due to malformed XML, nil is returned
and xml-error can be used to access error information.
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, xml-type-tags,
serves for translating the XML tags.
The following option numbers can be used:
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:
The TEXT elements containing only whitespace make the output very confusing.
As the database in example.xml only contains data,
we can suppress whitespace and comments with option (+ 1 3):
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 xml-type-tags directive.
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.
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.
Using xml-type-tags to suppress
all XML-type tags—along with the option numbers
1, 4, 8, and 16—SXML
formatted output can be generated:
Note that using option number 16
causes an @ (at symbol) to be added to attribute lists.
See also the xml-type-tags function
for further information on XML parsing.
When parsing XML expressions, XML tags are translated into newLISP symbols.
The sym-context option specifies the target context for the symbol
creation:
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. Normally, xml-parse will not return until all parsing has finished.
Using the func-callback option, xml-parse will call back after
each tag closing with the generated S-expression and a start position and
length in the source XML: The following output will be generated by the callback function xml-callback: The example callback handler function filters the tags of interest and processes
them as they occur.
Can suppress completely or replace the XML type tags
"TEXT", "CDATA", "COMMENT", and "ELEMENT" with something else specified
in the parameters.
Note that 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 xml-parse.
Using xml-type-tags without arguments
returns the current type tags:
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".
Checks the evaluation of exp to see if it equals 0 (zero).
zero? will return nil
on data types other than numbers.
newLISP maintains several internal symbol variables. All of them are global
and can be used by the programmer. Some have write protection, others
are user settable. Some will change when used in a sub-expression of the
enclosing expression using it. Others are safe when using reentrant in nested
functions or expressions. All symbols starting with the $ character will not be serialized
when using the save or source functions.
These are preset symbol constants. Two of them are used as namespace templates,
one two write platform independent code. Version 1.2, November 2002
Copyright (C) 2000,2001,2002 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
The purpose of this License is to make a manual, textbook, or other
functional and useful document "free" in the sense of freedom: to
assure everyone the effective freedom to copy and redistribute it,
with or without modifying it, either commercially or noncommercially.
Secondarily, this License preserves for the author and publisher a way
to get credit for their work, while not being considered responsible
for modifications made by others.
This License is a kind of "copyleft", which means that derivative
works of the document must themselves be free in the same sense. It
complements the GNU General Public License, which is a copyleft
license designed for free software.
We have designed this License in order to use it for manuals for
free
software, because free software needs free documentation: a free
program should come with manuals providing the same freedoms that the
software does. But this License is not limited to software manuals;
it can be used for any textual work, regardless of subject matter or
whether it is published as a printed book. We recommend this License
principally for works whose purpose is instruction or reference.
This License applies to any manual or other work, in any medium,
that
contains a notice placed by the copyright holder saying it can be
distributed under the terms of this License. Such a notice grants a
world-wide, royalty-free license, unlimited in duration, to use that
work under the conditions stated herein. The "Document", below,
refers to any such manual or work. Any member of the public is a
licensee, and is addressed as "you". You accept the license if you
copy, modify or distribute the work in a way requiring permission
under copyright law.
A "Modified Version" of the Document means any work containing the
Document or a portion of it, either copied verbatim, or with
modifications and/or translated into another language.
A "Secondary Section" is a named appendix or a front-matter section
of
the Document that deals exclusively with the relationship of the
publishers or authors of the Document to the Document's overall subject
(or to related matters) and contains nothing that could fall directly
within that overall subject. (Thus, if the Document is in part a
textbook of mathematics, a Secondary Section may not explain any
mathematics.) The relationship could be a matter of historical
connection with the subject or with related matters, or of legal,
commercial, philosophical, ethical or political position regarding
them.
The "Invariant Sections" are certain Secondary Sections whose titles
are designated, as being those of Invariant Sections, in the notice
that says that the Document is released under this License. If a
section does not fit the above definition of Secondary then it is not
allowed to be designated as Invariant. The Document may contain zero
Invariant Sections. If the Document does not identify any Invariant
Sections then there are none.
The "Cover Texts" are certain short passages of text that are
listed,
as Front-Cover Texts or Back-Cover Texts, in the notice that says that
the Document is released under this License. A Front-Cover Text may
be at most 5 words, and a Back-Cover Text may be at most 25 words.
A "Transparent" copy of the Document means a machine-readable copy,
represented in a format whose specification is available to the
general public, that is suitable for revising the document
straightforwardly with generic text editors or (for images composed of
pixels) generic paint programs or (for drawings) some widely available
drawing editor, and that is suitable for input to text formatters or
for automatic translation to a variety of formats suitable for input
to text formatters. A copy made in an otherwise Transparent file
format whose markup, or absence of markup, has been arranged to thwart
or discourage subsequent modification by readers is not Transparent.
An image format is not Transparent if used for any substantial amount
of text. A copy that is not "Transparent" is called "Opaque".
Examples of suitable formats for Transparent copies include plain
ASCII without markup, Texinfo input format, LaTeX input format, SGML
or XML using a publicly available DTD, and standard-conforming simple
HTML, PostScript or PDF designed for human modification. Examples of
transparent image formats include PNG, XCF and JPG. Opaque formats
include proprietary formats that can be read and edited only by
proprietary word processors, SGML or XML for which the DTD and/or
processing tools are not generally available, and the
machine-generated HTML, PostScript or PDF produced by some word
processors for output purposes only.
The "Title Page" means, for a printed book, the title page itself,
plus such following pages as are needed to hold, legibly, the material
this License requires to appear in the title page. For works in
formats which do not have any title page as such, "Title Page" means
the text near the most prominent appearance of the work's title,
preceding the beginning of the body of the text.
A section "Entitled XYZ" means a named subunit of the Document whose
title either is precisely XYZ or contains XYZ in parentheses following
text that translates XYZ in another language. (Here XYZ stands for a
specific section name mentioned below, such as "Acknowledgements",
"Dedications", "Endorsements", or "History".) To "Preserve the Title"
of such a section when you modify the Document means that it remains a
section "Entitled XYZ" according to this definition.
The Document may include Warranty Disclaimers next to the notice
which
states that this License applies to the Document. These Warranty
Disclaimers are considered to be included by reference in this
License, but only as regards disclaiming warranties: any other
implication that these Warranty Disclaimers may have is void and has
no effect on the meaning of this License.
You may copy and distribute the Document in any medium, either
commercially or noncommercially, provided that this License, the
copyright notices, and the license notice saying this License applies
to the Document are reproduced in all copies, and that you add no other
conditions whatsoever to those of this License. You may not use
technical measures to obstruct or control the reading or further
copying of the copies you make or distribute. However, you may accept
compensation in exchange for copies. If you distribute a large enough
number of copies you must also follow the conditions in section 3.
You may also lend copies, under the same conditions stated above,
and
you may publicly display copies.
If you publish printed copies (or copies in media that commonly have
printed covers) of the Document, numbering more than 100, and the
Document's license notice requires Cover Texts, you must enclose the
copies in covers that carry, clearly and legibly, all these Cover
Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
the back cover. Both covers must also clearly and legibly identify
you as the publisher of these copies. The front cover must present
the full title with all words of the title equally prominent and
visible. You may add other material on the covers in addition.
Copying with changes limited to the covers, as long as they preserve
the title of the Document and satisfy these conditions, can be treated
as verbatim copying in other respects.
If the required texts for either cover are too voluminous to fit
legibly, you should put the first ones listed (as many as fit
reasonably) on the actual cover, and continue the rest onto adjacent
pages.
If you publish or distribute Opaque copies of the Document numbering
more than 100, you must either include a machine-readable Transparent
copy along with each Opaque copy, or state in or with each Opaque copy
a computer-network location from which the general network-using
public has access to download using public-standard network protocols
a complete Transparent copy of the Document, free of added material.
If you use the latter option, you must take reasonably prudent steps,
when you begin distribution of Opaque copies in quantity, to ensure
that this Transparent copy will remain thus accessible at the stated
location until at least one year after the last time you distribute an
Opaque copy (directly or through your agents or retailers) of that
edition to the public.
It is requested, but not required, that you contact the authors of
the
Document well before redistributing any large number of copies, to give
them a chance to provide you with an updated version of the Document.
You may copy and distribute a Modified Version of the Document under
the conditions of sections 2 and 3 above, provided that you release
the Modified Version under precisely this License, with the Modified
Version filling the role of the Document, thus licensing distribution
and modification of the Modified Version to whoever possesses a copy
of it. In addition, you must do these things in the Modified Version:
A. Use in the Title Page (and on the covers, if
any) a title distinct from that of the Document, and from those of
previous versions (which should, if there were any, be listed in the
History section of the Document). You may use the same title as a
previous version if the original publisher of that version gives
permission. B. List on the Title Page, as authors, one or
more persons or entities responsible for authorship of the
modifications in the Modified Version, together with at least five of
the principal authors of the Document (all of its principal authors, if
it has fewer than five), unless they release you from this requirement. C. State on the Title page the name of the
publisher of the Modified Version, as the publisher. D. Preserve all the copyright notices of the
Document. E. Add an appropriate copyright notice for your
modifications adjacent to the other copyright notices. F. Include, immediately after the copyright
notices, a license notice giving the public permission to use the
Modified Version under the terms of this License, in the form shown in
the Addendum below. G. Preserve in that license notice the full
lists of Invariant Sections and required Cover Texts given in the
Document's license notice. H. Include an unaltered copy of this License. I. Preserve the section Entitled "History",
Preserve its Title, and add to it an item stating at least the title,
year, new authors, and publisher of the Modified Version as given on
the Title Page. If there is no section Entitled "History" in the
Document, create one stating the title, year, authors, and publisher of
the Document as given on its Title Page, then add an item describing
the Modified Version as stated in the previous sentence. J. Preserve the network location, if any, given
in the Document for public access to a Transparent copy of the
Document, and likewise the network locations given in the Document for
previous versions it was based on. These may be placed in the "History"
section. You may omit a network location for a work that was published
at least four years before the Document itself, or if the original
publisher of the version it refers to gives permission. K. For any section Entitled "Acknowledgements"
or "Dedications", Preserve the Title of the section, and preserve in
the section all the substance and tone of each of the contributor
acknowledgements and/or dedications given therein. L. Preserve all the Invariant Sections of the
Document, unaltered in their text and in their titles. Section numbers
or the equivalent are not considered part of the section titles. M. Delete any section Entitled "Endorsements".
Such a section may not be included in the Modified Version. N. Do not retitle any existing section to be
Entitled "Endorsements" or to conflict in title with any Invariant
Section. O. Preserve any Warranty Disclaimers.
If the Modified Version includes new front-matter sections or
appendices that qualify as Secondary Sections and contain no material
copied from the Document, you may at your option designate some or all
of these sections as invariant. To do this, add their titles to the
list of Invariant Sections in the Modified Version's license notice.
These titles must be distinct from any other section titles.
You may add a section Entitled "Endorsements", provided it contains
nothing but endorsements of your Modified Version by various
parties--for example, statements of peer review or that the text has
been approved by an organization as the authoritative definition of a
standard.
You may add a passage of up to five words as a Front-Cover Text, and
a
passage of up to 25 words as a Back-Cover Text, to the end of the list
of Cover Texts in the Modified Version. Only one passage of
Front-Cover Text and one of Back-Cover Text may be added by (or
through arrangements made by) any one entity. If the Document already
includes a cover text for the same cover, previously added by you or
by arrangement made by the same entity you are acting on behalf of,
you may not add another; but you may replace the old one, on explicit
permission from the previous publisher that added the old one.
The author(s) and publisher(s) of the Document do not by this
License
give permission to use their names for publicity for or to assert or
imply endorsement of any Modified Version.
You may combine the Document with other documents released under
this
License, under the terms defined in section 4 above for modified
versions, provided that you include in the combination all of the
Invariant Sections of all of the original documents, unmodified, and
list them all as Invariant Sections of your combined work in its
license notice, and that you preserve all their Warranty Disclaimers.
The combined work need only contain one copy of this License, and
multiple identical Invariant Sections may be replaced with a single
copy. If there are multiple Invariant Sections with the same name but
different contents, make the title of each such section unique by
adding at the end of it, in parentheses, the name of the original
author or publisher of that section if known, or else a unique number.
Make the same adjustment to the section titles in the list of
Invariant Sections in the license notice of the combined work.
In the combination, you must combine any sections Entitled "History"
in the various original documents, forming one section Entitled
"History"; likewise combine any sections Entitled "Acknowledgements",
and any sections Entitled "Dedications". You must delete all sections
Entitled "Endorsements."
You may make a collection consisting of the Document and other
documents
released under this License, and replace the individual copies of this
License in the various documents with a single copy that is included in
the collection, provided that you follow the rules of this License for
verbatim copying of each of the documents in all other respects.
You may extract a single document from such a collection, and
distribute
it individually under this License, provided you insert a copy of this
License into the extracted document, and follow this License in all
other respects regarding verbatim copying of that document.
A compilation of the Document or its derivatives with other separate
and independent documents or works, in or on a volume of a storage or
distribution medium, is called an "aggregate" if the copyright
resulting from the compilation is not used to limit the legal rights
of the compilation's users beyond what the individual works permit.
When the Document is included in an aggregate, this License does not
apply to the other works in the aggregate which are not themselves
derivative works of the Document.
If the Cover Text requirement of section 3 is applicable to these
copies of the Document, then if the Document is less than one half of
the entire aggregate, the Document's Cover Texts may be placed on
covers that bracket the Document within the aggregate, or the
electronic equivalent of covers if the Document is in electronic form.
Otherwise they must appear on printed covers that bracket the whole
aggregate.
Translation is considered a kind of modification, so you may
distribute translations of the Document under the terms of section 4.
Replacing Invariant Sections with translations requires special
permission from their copyright holders, but you may include
translations of some or all Invariant Sections in addition to the
original versions of these Invariant Sections. You may include a
translation of this License, and all the license notices in the
Document, and any Warranty Disclaimers, provided that you also include
the original English version of this License and the original versions
of those notices and disclaimers. In case of a disagreement between
the translation and the original version of this License or a notice
or disclaimer, the original version will prevail.
If a section in the Document is Entitled "Acknowledgements",
"Dedications", or "History", the requirement (section 4) to Preserve
its Title (section 1) will typically require changing the actual
title.
You may not copy, modify, sublicense, or distribute the Document
except
as expressly provided for under this License. Any other attempt to
copy, modify, sublicense or distribute the Document is void, and will
automatically terminate your rights under this License. However,
parties who have received copies, or rights, from you under this
License will not have their licenses terminated so long as such
parties remain in full compliance.
The Free Software Foundation may publish new, revised versions
of the GNU Free Documentation License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns. See
http://www.gnu.org/copyleft/.
Each version of the License is given a distinguishing version
number.
If the Document specifies that a particular numbered version of this
License "or any later version" applies to it, you have the option of
following the terms and conditions either of that specified version or
of any later version that has been published (not as a draft) by the
Free Software Foundation. If the Document does not specify a version
number of this License, you may choose any version ever published (not
as a draft) by the Free Software Foundation.
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. http://fsf.org/
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
newlisp -c -t 3000000 -d 4711 &
inetd daemon mode
net-eval stream tcp nowait root /usr/local/bin/newlisp -c
# as an alternative, a program can also be preloaded
net-eval stream tcp nowait root /usr/local/bin/newlisp -c myprog.lsp
net-eval 4711/tcp # newLISP net-eval requests
service net-eval
{
socket_type = stream
wait = no
user = root
server = /usr/local/bin/newlisp
port = 4711
server_args = -c
only_from = localhost
}
kill -HUP <pid>
telnet localhost 4711
4. Startup, directories, environment
Environment variable NEWLISPDIR
(load (append (env "NEWLISPDIR") "/guiserver.lsp"))
(load (append (env "NEWLISPDIR") "/modules/mysql.lsp"))
(module "mysql.lsp")
The initialization file init.lsp
Directories on Linux, BSD, Mac OS X and other Unix
Directories on Win32
5. Shared library module for Unix
(import "/usr/local/lib/newlisp.so" "newlispEvalStr")
(get-string (newlispEvalStr "(+ 3 4)")) → "7\n"
/* libdemo.c - demo for importing newlisp.so
*
* compile using:
* gcc -ldl libdemo.c -o libdemo
*
* use:
*
* ./libdemo '(+ 3 4)'
* ./libdemo '(symbols)'
*
*/
#include <stdio.h>
#include <dlfcn.h>
int main(int argc, char * argv[])
{
void * hLibrary;
char * result;
char * (*func)(char *);
char * error;
if((hLibrary = dlopen("/usr/local/lib/newlisp.so",
RTLD_GLOBAL | RTLD_LAZY)) == 0)
{
printf("cannot import library\n");
exit(-1);
}
func = dlsym(hLibrary, "newlispEvalStr");
if((error = dlerror()) != NULL)
{
printf("error: %s\n", error);
exit(-1);
}
printf("%s\n", (*func)(argv[1]));
return(0);
}
/* eof */
6. DLL module for Win32 versions
(import "newlisp.dll" "newlispEvalStr")
(get-string (newlispEvalStr "(+ 3 4)")) → "7"
7. Evaluating newLISP expressions
> [cmd]
(define (foo x y)
(+ x y))
[/cmd]
(lambda (x y) (+ x y))
> (foo 3 4)
7
> _
Integer, floating point data and operators
(constant '+ add)
(constant '- sub)
(constant '* mul)
(constant '/ div)
;; or all 4 operators at once
(constant '+ add '- sub '* mul '/ div)
(import "mylib.dll" "foo") ; importing int foo(int x) from C
(foo (int x)) ; passed argument as integer
(import "mylib.dll" "bar") ; importing C int bar(double y)
(bar (float y)) ; force double float
Evaluation rules and data types
nil → nil
true → true
123 → 123
0xE8 → 232 ; hexadecimal prefixed by 0x
055 → 45 ; octal prefixed by 0 (zero)
1.23 → 1.23
123e-3 → 0.123 ; scientific notation
"hello" →"hello"
"\032\032\065\032" →" A "
"\x20\x20\x41\x20" →" A "
"\t\r\n" →"\t\r\n"
"\x09\x0d\x0a" →"\t\r\n"
;; null characters are legal in strings:
"\000\001\002" → "\000\001\002"
{this "is" a string} → "this \"is\" a string"
;; use [text] tags for text longer than 2048 bytes:
[text]this is a string, too[/text]
→ "this is a string, too"
character description \" for a double quote inside a quoted string \n for a line-feed character (ASCII 10) \r for a return character (ASCII 13) \t for a TAB character (ASCII 9) \nnn for a three-digit ASCII number (nnn format between 000 and 255) \xnn for a two-digit-hex ASCII number (xnn format between x00 and xff)
(lambda (x) (* x x)) → (lambda (x) (* x x))
(lambda-macro (a b) (set (eval a) b)) → (lambda-macro (a b) (set (eval a) b))
(fn (x) (* x x)) → (lambda (x) (* x x)) ; an alternative syntax
(set 'something 123) → 123
something → 123
(context 'CTX) → CTX
CTX → CTX
add → add <B845770D>
(eval (eval add)) → add <B845770D>
(constant '+ add) → add <B845770D>
+ → add <B845770D>
'something → something
''''any → '''any
'(a b c d) → (a b c d)
(+ 1 2 3 4) → 10
(define (double x) (+ x x)) → (lambda (x) (+ x x))
(set 'double (lambda (x) (+ x x)))
(double 20) → 40
((lambda (x) (* x x)) 5) → 25
((if (> X 10) * +) X Y)
(set 'A (array 2 2 '(1 2 3 4))) → ((1 2) (3 4))
(eval A) → ((1 2) (3 4))
8. Lambda expressions in newLISP
(set 'double (lambda (x) (+ x x)))
(set 'double (fn (x) (+ x x))) ; alternative syntax
(last double) → (+ x x) ; treat lambda as a list
(append (lambda (x)) '((+ x x))) → (lambda (x) (+ x x))
(cons '(x) (lambda (+ x x))) → (lambda (x) (+ x x))
(length (lambda (x) (+ x x))) → 2
(first (lambda (x) (+ x x))) → (x)
((lambda (x) (+ x x)) 123) → 246
(apply (lambda (x) (+ x x)) '(123)) → 246
(map (lambda (x) (+ x x)) '(1 2 3)) → (2 4 6)
(set 'double (lambda (x) (+ x x))) → (lambda (x) (+ x x))
(double 123) → 246
(define (double x) (+ x x))) → (lambda (x) (+ x x))
(double 123) → 246
(set 'double (lambda (x) (+ x x))) → (lambda (x) (+ x x))
(last double) → (+ x x)
(setf (nth 1 double) '(mul 2 x)) → (lambda (x) (mul 2 x))
double → (lambda (x) (mul 2 x))
(double 123) → 246
9. nil, true, cons, and ()
(set 'lst '(nil nil nil)) → (nil nil nil)
(map symbol? lst) → (true true true)
(if nil "no" "yes") → "yes"
(if true "yes" "no") → "yes"
(map not lst) → (true true true)
10. Arrays
function description
append
appends arrays
array
creates and initializes an array with up to 16 dimensions
array-list
converts an array into a list
array?
checks if expression is an array
det
returns the determinant of a matrix
first
returns the first row of an array
invert
returns the inversion of a matrix
last
returns the last row of an array
mat
perform scalar operations on matrices
multiply
multiplies two matrices
nth
returns an element of and array
rest
returns all but the first row of an array
setf
sets contents of an array reference
slice
returns a slice of an array
sort
sort the elements in an array
transpose
transposes a matrix
11. Indexing elements of strings, lists, and arrays
Implicit indexing for nth
(set 'lst '(a b c (d e) (f g)))
(lst 0) → a ; same as (nth (lst 0))
(lst 3) → (d e)
(lst 3 1) → e ; same as (nth (lst 3 1))
(lst -1) → (f g)
(set 'myarray (array 3 2 (sequence 1 6)))
(myarray 1) → (3 4)
(myarray 1 0) → 3
(myarray 0 -1) → 2
("newLISP" 3) → "L"
(lst '(3 1)) → e
(set 'vec (ref 'e lst)) → (3 1)
(lst vec) → e
Implicit indexing and the default functor
(set 'MyList:MyList '(a b c d e f g))
(MyList 0) → a
(MyList 3) → d
(MyList -1) → g
(3 2 MyList) → (d e)
(-3 MyList) → (e f g)
(set 'aList MyList)
(aList 3) → d
(set 'MyList:MyList '(a b c d e f g))
(setf (MyList 3) 999) → 999
(MyList 3) → 999
MyList:MyList → (a b c 999 e f g)
Implicit indexing for rest and slice
(set 'lst '(a b c d e f g))
; or as array
(set 'lst (array 7 '(a b c d e f g)))
(1 lst) → (b c d e f g)
(2 lst) → (c d e f g)
(2 3 lst) → (c d e)
(-3 2 lst) → (e f)
(2 -2 lst) → (c d e)
(set 'str "abcdefg")
(1 str) → "bcdefg"
(2 str) → "cdefg"
(2 3 str) → "cde"
(-3 2 str) → "ef"
(2 -2 str) → "cde"
Modify references in lists, arrays and strings
; lists
(set 'lst '(a b c d (e f g)))
(lst 1) → b
(setf (lst 1) 'z) → z
lst → (a z c d (e f g))
(setf (lst -1) '(E F G)) → (E F G)
lst → (a z c d (E F G))
; arrays
(set 'myarray (array 2 3 (sequence 1 6))) → ((1 2 3) (4 5 6))
(setf (myarray 1 2) 66) → 66
myarray → ((1 2 3) (4 5 66))
; strings
(set 's "NewLISP)
(setf (s 0) "n") → "n"
s → "newLISP"
12. Destructive versus nondestructive functions
function description
bind
binds variable associations in a list
constant
sets the contents of a variable and protects it
dec
decrements a number referenced by a variable, list or array
define
sets the contents of a variable
inc
increments a number referenced by a variable, list or array
net-receive
reads into a buffer variable
pop
pops an element from a list or string
pop-assoc
removes an association from an association list
push
pushes a new element onto a list or string
read-buffer
reads into a buffer variable
receive
receives a message from a parent or child process
replace
replaces elements in a list or string
reverse
reverses a list or string
rotate
rotates the elements of a list or characters of a string
set
sets the contents of a variable
setf setq
sets the contents of a variable, list, array or string
set-ref
searches for an element in a nested list and replaces it
set-ref-all
searches for an element in a nested list and replaces all instances
sort
sorts the elements of a list or array
swap
swaps two elements inside a list or string
write-buffer
writes to a string buffer or file
write-line
writes to a string buffer or file
Make a destructive function 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)
13. Dynamic and lexical scoping
> (set 'x 1)
1
> (define (f) x)
(lambda () x)
> (f)
1
> (define (g x) (f))
(lambda (x) (f))
> (g 0)
0
> (f)
1
> _
(define (inc-symbol x y) (inc (eval x) y))
(set 'y 200)
(inc-symbol 'y 123) → 246
y → 200 ; y is still 200
14. Early return from functions, loops, and blocks
Using catch and throw
(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
(catch
(dotimes (i N)
(if (= (foo i) 100) (throw i))))
→ value of i when foo(i) equals 100
(catch (begin
(foo1)
(foo2)
(if condition-A (throw 'x))
(foo3)
(if condition-B (throw 'y))
(foo4)
(foo5)))
Using and and or
(and
(func-a)
(func-b)
(func-c)
(func-d))
(or
(func-a)
(func-b)
(func-c)
(func-d))
15. Contexts
(symbols)
Symbol creation in contexts
Creating contexts
(context 'FOO)
(set 'var 123)
(define (func x y z)
... )
(context MAIN)
FOO:var → 123
(FOO:func p q r)
(symbols FOO) → (FOO:func FOO:var FOO:x FOO:y FOO:z)
Implicitly creating contexts
> (set 'ACTX:var "hello")
"hello"
> ACTX:var
"hello"
> _
(define (ACTX:foo x y)
(+ x y))
;;; file MY_PROG.LSP
;;
;; everything from here on goes into GRAPH
(context 'GRAPH)
(define (draw-triangle x y z)
(…))
(define (draw-circle)
(…))
;; show the runtime context, which is GRAPH
(define (foo)
(context))
;; switch back to MAIN
(context 'MAIN)
;; end of file
(GRAPH:draw-triangle 1 2 3)
(GRAPH:foo) → GRAPH
;; same symbol name, but different context name
(= 'A:val 'B:val) → nil
(= (name 'A:val) (name 'B:val)) → true
Global scope
(set 'aVar 123) → 123
(global 'aVar) → aVar
(context 'FOO) → FOO
aVar → 123
Symbol protection
> (constant 'aVar 123) → 123
> (set 'aVar 999)
ERR: symbol is protected in function set : aVar
>_
(constant (global 'aVar) 123)
Overwriting global symbols and built-ins
(context 'Account)
(define (Account:new …)
(…))
(context 'MAIN)
Variables containing contexts
(set 'FOO:x 123)
(set 'ctx FOO) → FOO
ctx:x → 123
(set 'ctx:x 999) → 999
FOO:x → 999
(define (update ctx val)
(set 'ctx:sum val)
(ctx:func 999)
)
(context 'FOO)
(define (func x)
(println "=>" x))
(context MAIN)
> (update FOO 123)
=> 999
> FOO:sum
123
>
Sequence of creating or loading contexts
;; demo - file for loading contexts
(context 'FOO)
(set 'ABC 123)
(context MAIN)
(context 'ABC)
(set 'FOO 456)
(context 'MAIN)
> (load "demo")
ERR: symbol is protected in function set : FOO
> _
;; begin of file - MyModule.lsp
(load "This.lsp")
(load "That.lsp")
(load "Other.lsp")
(context 'MyModule)
…
(define (func x y z) (…))
…
(context 'MAIN)
(MyModule:func 1 2 3)
(exit)
;; end of file
Contexts as programming modules
;; file db.lsp, commonly used database functions
(context 'db)
;; Variables used throughout this namespace
(define db:handle)
(define db:host "http://localhost)
;; Constants
(constant 'Max_N 1000000)
(constant 'Path "/usr/data/")
;; Functions
(define (db:open ... )
... )
(define (db:close ... )
... )
(define (db:update ... )
... )
;; Multi context file multi.lsp
(context 'A-ctx)
...
(context MAIN)
(context 'B-ctx)
...
(context MAIN)
(context 'C-ctx)
...
(context MAIN)
Contexts as data containers
;; Config.lsp - configuration setup
(context 'Config)
(set 'user-name "admin")
(set 'password "secret")
(set 'db-name "/usr/data/db.lsp")
...
;; eof
(load "Config.lsp")
(set 'file (open Config:db-name "read"))
...
...
(save "Config.lsp" 'Config)
Loading and declaring contexts
;; pre-declaring contexts, finish with Main to return
(map context '(Utilities Config Acquisition Analysis SysLog Main))
;; loading context module files
(load "Utilities.lsp" "Acquisition.lsp")
(load "http://192.168.1.34/Config.lsp") ; load module from remote location
(load "Analysis.lsp" "SysLog.lsp")
(define (run)
... )
(run)
;; end of file
Serializing contexts
(save "mycontext.lsp" 'MyCtx) ; save MyCtx to mycontext.lsp
(load "mycontext.lsp") ; loads MyCtx into memory
(save "mycontexts.lsp" 'Ctx1 'Ctx2 'Ctx3) ; save multiple contexts at once
16. The context default functor
;; the default function
(define (Foo:Foo a b c) (+ a b c))
(Foo 1 2 3) → 6
;; forward declaration of a default function
(define Fubar:Fubar)
(context 'Foo)
(define (Foo:Foo a b c)
…
(Fubar a b) ; forward reference
(…)) ; to default function
(context MAIN)
;; definition of previously declared default function
(context 'Fubar)
(define (Fubar:Fubar x y)
(…))
(context MAIN)
Functions with memory
;; a function with memory
(define (Gen:Gen x)
(if Gen:acc
(inc Gen:acc x)
(setq Gen:acc x)))
(Gen 1) → 1
(Gen 1) → 2
(Gen 2) → 4
(Gen 3) → 7
gen:acc → 7
Hash functions and dictionaries
(define Myhash:Myhash) ; create namespace and default functor
; or as an alternative use
(new Tree 'MyHash) ; create from built-in template
(Myhash "var" 123) ; create and set variable/value pair
(Myhash "var") ; → 123 ; retrieve value
(define Foo:Foo)
(Foo "John Doe" 123) → 123
(Foo "#1234" "hello world") → "hello world"
(Foo "var" '(a b c d)) → (a b c d)
(Foo "John Doe") → 123
(Foo "#1234") → "hello world"
(Foo "var") → (a b c d)
(Foo "bar") → nil
(Foo) → (("#1234" "hello world") ("John Doe" 123) ("var" (a b c d)))
(Foo '(("#1234" "hello world") ("John Doe" 123) ("var" (a b c d))) → Foo
(dolist (item (Foo)) (println (item 0) " -> " (item 1)))
#1234 -> hello world
John Doe -> 123
var -> (a b c d)
(pop (Foo "var")) → a
(Foo "var") → (b c d)
(push 'z (Foo "var")) → (z b c d)
(Foo "var") → (z b c d)
(Foo "bar" "hello world")
(Foo "bar" (upper-case $it))
(Foo "bar") → "HELLO WORLD"
(Foo "bar" 123) → 123
(setf (Foo "bar") 456) → 456
(Foo "bar") → 456
; save dictionary
(save "Foo.lsp" 'Foo)
; load dictionary
(load "Foo.lsp")
(Foo) → (("#1234" "hello world") ("John Doe" 123) ("var" (a b c d)))
(symbols Foo) → (Foo:Foo Foo:_#1234 Foo:_John Doe Foo:_var)
Passing data by reference
;; the default functor for holding data
(define Mylist:Mylist '(a b c d e f g))
(Mylist 3) → d
(setf (Mylist 3) 'D) → D
Mylist:Mylist → (a b c D e f g)
;; access list or string data from a default functor
(first Mylist) → a
(reverse Mylist) → (g f e D c b a)
(set 'Str:Str "acdefghijklmnop")
(upper-case Str) → "ACDEFGHIJKLMNOP"
;; use a default functor to hold a list
(set 'Mydb:Mydb (sequence 1 100000))
(define (change-db obj idx value)
(setf (obj idx) value))
; pass by context reference
(change-db Mydb 1234 "abcdefg")
(Mydb 1234) → "abcdefg"
(define (change-list aList) (push 999 (eval aList)))
(set 'data '(1 2 3 4 5))
; note the quote ' in front of data
(change-list 'data) → (999 1 2 3 4 5)
data → (999 1 2 3 4 5)
;; pass data by symbol reference
> (set 'aList '(a b c d))
(a b c d)
> (change-list 'aList)
ERR: list or string expected : (eval aList)
called from user defined function change-list
>
;; pass data by context reference
(set 'Mydb:data (sequence 1 100000))
(define (change-db obj idx value)
(setf (obj:data idx) value))
(change-db Mydb 1234 "abcdefg")
(nth (Mydb:data 1234)) → "abcdefg"
17. Functional object-oriented programming
FOOP classes and constructors
; built-in generic FOOP object constructor
(define (Class:Class)
(cons (context) (args)))
; create some new classes
(new Class 'Rectangle)
(new Class 'Circle)
(context 'Geometry)
(new Class 'MAIN:Rectangle)
(new Class 'MAIN:Circle)
...
; overwrite simple constructor
(define (Circle:Circle x y radius)
(list Circle x y radius))
; constructor with defaults
(define (Circle:Circle (x 10) (y 10) (radius 3))
(list Circle x y radius))
(Circle) → (Circle 10 10 3)
Objects and associations
(set 'myrect (Rectangle 5 5 10 20)) → (Rectangle 5 5 10 20)
(set 'mycircle (Circle 1 2 10)) → (Circle 1 2 10)
; create classes
(new Class 'Person)
(new Class 'Address)
(new Class 'City)
(new Class 'Street)
; create an object containing other objects
(set 'JohnDoe (Person (Address (City "Boston") (Street 123 "Main Street"))))
→ (Person (Address (City "Boston") (Street 123 "Main Street")))
(assoc Address JohnDoe) → (Address (City "Boston") (Street 123 "Main Street"))
(assoc (list Address Street) JohnDoe) → (Street 123 "Main Street")
(setf (assoc (list Address Street) JohnDoe) '(Street 456 "Main Street"))
→ (Street 456 "Main Street")
The colon : operator and polymorphism
;; class methods for rectangles
(define (Rectangle:area p)
(mul (p 3) (p 4)))
(define (Rectangle:move p dx dy)
(list Rectangle (add (p 1) dx) (add (p 2) dy) (p 3) (p 4)))
;; class methods for circles
(define (Circle:area c)
(mul (pow (c 3) 2) (acos 0) 2))
(define (Circle:move p dx dy)
(list Circle (add (p 1) dx) (add (p 2) dy) (p 3)))
(:area myrect) → 200 ; same as (Rectangle:area myrect)
(:area mycircle) → 314.1592654 ; same as (Circle:area mycircle)
;; map class methods uses curry to enclose the colon operator and class function
(map (curry :area) (map eval '(myrect mycircle))) → (200 314.1592654)
(map (curry :area) '((Rectangle 5 5 10 20) (Circle 1 2 10))) → (200 314.1592654)
(set 'myrect (:move myrect 2 3)) → (Rectangle 7 8 10 20)
(set 'mycircle (:move mycircle 4 5)) → (Circle 5 7 10)
(new Class 'Foo)
(define (Foo:modify obj val) (setf (obj 1) val))
(define (Foo:show obj) (default obj))
(set 'MyFoo:MyFoo (Foo 123)) => (Foo 123)
(:modify MyFoo 999) => 999
(:show MyFoo) => (Foo 999)
18. Concurrent processing and distributed computing
Cilk API
Distributed network computing
19. XML, S-XML, and XML-RPC
<?xml version="1.0"?>
<DATABASE name="example.xml">
<!--This is a database of fruits-->
<FRUIT>
<NAME>apple</NAME>
<COLOR>red</COLOR>
<PRICE>0.80</PRICE>
</FRUIT>
</DATABASE>
Parsing without options:
(xml-parse (read-file "example.xml"))
→ (("ELEMENT" "DATABASE" (("name" "example.xml")) (("TEXT" "\r\n")
("COMMENT" "This is a database of fruits")
("TEXT" "\r\n ")
("ELEMENT" "FRUIT" () (
("TEXT" "\r\n\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"))))
S-XML generation using all options:
(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"))))
XML-RPC
method description
system.listMethods
Returns a list of all method names
system.methodHelp
Returns help for a specific method
system.methodSignature
Returns a list of return/calling signatures for a specific method
newLISP.evalString
Evaluates a Base64 newLISP expression string
(load "xmlrpc-client.lsp") ; load XML-RPC client routines
(XMLRPC:newLISP.evalString
"http://localhost:8080/xmlrpc.cgi"
"(+ 3 4)") → "7"
20. Customization, localization, and UTF-8
Customizing function names
(constant 'plus +)
(constant '+ add)
(constant '- sub)
(constant '* mul)
(constant '/ div)
(constant 'wurzel sqrt) ; German for 'square-root'
; make the new symbol global at the same time
(constant (global 'imprime) print) ; Spanish for 'print'
…
Switching the locale
(set-locale "")
locale -a
(set-locale "es_US")
Decimal point and decimal comma
;; switch to German locale on a Linux system
(set-locale "de_DE") → ("de_DE" ",")
;; newLISP source and output use a decimal comma
(div 1,2 3) → 0,4
Australia, Botswana, Canada (English-speaking), China, Costa Rica,
Dominican Republic, El Salvador, Guatemala, Honduras, Hong Kong, India, Ireland,
Israel, Japan, Korea (both North and South), Malaysia, Mexico, Nicaragua,
New Zealand, Panama, Philippines, Puerto Rico, Saudi Arabia, Singapore, Switzerland,
Thailand, United Kingdom, and United States.
Albania, Andorra, Argentina, Austria, Belarus, Belgium, Bolivia,
Brazil, Bulgaria, Canada (French-speaking), Croatia, Cuba, Chile, Colombia,
Czech Republic, Denmark, Ecuador, Estonia, Faroes, Finland, France, Germany,
Greece, Greenland, Hungary, Indonesia, Iceland, Italy, Latvia, Lithuania,
Luxembourg, Macedonia, Moldova, Netherlands, Norway, Paraguay, Peru, Poland,
Portugal, Romania, Russia, Serbia, Slovakia, Slovenia, Spain, South Africa,
Sweden, Ukraine, Uruguay, Venezuela, and Zimbabwe.
Unicode and UTF-8 encoding
export LC_CTYPE=en_US.UTF-8
LC_CTYPE=en_US.UTF-8 xterm
(println (char 937)) ; displays Greek uppercase omega
(println (lower-case (char 937))) ; displays lowercase omega
Functions working on UTF-8 characters
function description
char
translates between characters and ASCII/Unicode
chop
chops characters from the end of a string
date
converts date number to string (when used with the third argument)
dostring
evaluates once for each character in a string
explode
transforms a string into a list of characters
first
gets first element in a list (car, head) or string
last
returns the last element of a list or string
lower-case
converts a string to lowercase characters
nth
gets the nth element of a list or string
pop
deletes an element from a list or string
push
inserts a new element in a list or string
rest
gets all but the first element of a list (cdr, tail) or string
select
selects and permutes elements from a list or string
title-case
converts the first character of a string to uppercase
trim
trims a string from both sides
upper-case
converts a string to uppercase characters
(join (reverse (explode str))) ; reverse UTF-8 characters
21. Commas in parameter lists
(define (my-func a b c , x y z)
(set 'x …)
(…))
22. Linking newLISP source and executable
;; uppercase.lsp - Link example
(println (upper-case (main-args 1)))
(exit)
newlisp link.lsp
(link "newlisp.exe" "uppercase.exe" "uppercase.lsp") ; Win32
(link "newlisp" "uppercase" "uppercase.lsp") ; Linux/BSD
uppercase "convert me to uppercase"
CONVERT ME TO UPPERCASE
chmod 755 uppercase
newLISP Function Reference
1. Syntax of symbol variables and numbers
Symbols for variable names
# ; " ' ( ) { } . , 0 1 2 3 4 5 6 7 8 9
" ' ( ) : , and the space character. These mark the end of a variable symbol.
myvar
A-name
X34-zz
[* 7 5 ()};]
*111*
(set (sym "(#:L*") 456) → 456
(eval (sym "(#:L*")) → 456
(set (sym 1) 123) → 123
(eval (sym 1)) → 123
1 → 1
(+ 1 2) → 3
Numbers
123
+4567
-999
0xFF → 255
0x10ab → 4267
0X10CC → 4300
012 → 10
010 → 8
077 → 63
-077 → -63
1.23 → 1.23
-1.23 → -1.23
+2.3456 → 2.3456
.506 → 0.506
1.23e3 → 1230
-1.23E3 → -1230
+2.34e-2 → 0.0234
.506E3 → 506
2. Data types and names in the reference
array
body
1 7.8
nil
(+ 3 4)
"Hi" (+ a b)(print result)
(do-this)(do-that) 123
bool
true, nil, (<= X 10)
context
MyContext, aCtx, TheCTX
exp
func
+, add, (first '(add sub)), (lambda (x) (+ x x))
int
123, 5, (* X 5)
list
(a b c "hello" (+ 3 4))
num
1.234, (div 10 3), (sin 1)
matrix
((1 2 3 4)
(5 6 7 8)
(9 10 11 12)) ; 3 rows 4 columns
((1 2) (3 4) (5 6)) ; 3 rows 2 columns
place
str
"Hello", (append first-name " Miller")
character description
\n
the line-feed character (ASCII 10)
\r
the carriage return character (ASCII 13)
\t
the tab character (ASCII 9)
\nnn
a decimal ASCII code where nnn is between 000 and 255
\xnn
a hexadecimal code where nn is between 00 and FF
"\065\066\067" → "ABC"
"\x41\x42\x43" → "ABC"
(print "<A HREF=\"http://mysite.com\">" ) ; the cryptic way
(print {<A HREF="http://mysite.com">} ) ; the readable way
;; also possible because the inner brackets are balanced
(regex {abc{1,2}} line)
(print [text]
this could be
a very long (> 2048 characters) text,
i.e. HTML.
[/text])
sym
'xyz, (first '(+ - /)), '*, '- , someSymbol,
sym-context
3. Functions in groups
List processing, flow control, and integer arithmetic
+, -, *, /, %
integer arithmetic
<, >, =
compares any data type: less, greater, equal
<=, >=, !=
compares any data type: less-equal, greater-equal, not-equal
:
constructs a context symbol and applies it to an object
and
logical and
append
appends lists ,arrays or strings to form a new list, array or string
apply
applies a function or primitive to a list of arguments
args
retrieves the argument list of a function or macro expression
assoc
searches for keyword associations in a list
begin
begins a block of functions
bind
binds variable associations in a list
case
branches depending on contents of control variable
catch
evaluates an expression, possibly catching errors
chop
chops elements from the end of a list
clean
cleans elements from a list
cond
branches conditionally to expressions
cons
prepends an element to a list, making a new list
constant
defines a constant symbol
count
counts elements of one list that occur in another list
curry
transforms a function f(x, y) into a function fx(y)
define
defines a new function or lambda expression
define-macro
defines a macro or lambda-macro expression
def-new
copies a symbol to a different context (namespace)
difference
returns the difference between two lists
doargs
iterates through the arguments of a function
dolist
evaluates once for each element in a list
dostring
evaluates once for each character in a string
dotimes
evaluates once for each number in a range
dotree
iterates through the symbols of a context
do-until
repeats evaluation of an expression until the condition is met
do-while
repeats evaluation of an expression while the condition is true
dup
duplicates a list or string a specified number of times
ends-with
checks the end of a string or list against a key of the same type
eval
evaluates an expression
exists
checks for the existence of a condition in a list
expand
replaces a symbol in a nested list
first
gets the first element of a list or string
filter
filters a list
find
searches for an element in a list or string
flat
returns the flattened list
fn
defines a new function or lambda expression
for
evaluates once for each number in a range
for-all
checks if all elements in a list meet a condition
if
evaluates an expression conditionally
index
filters elements from a list and returns their indices
intersect
returns the intersection of two lists
lambda
defines a new function or lambda expression
last
returns the last element of a list or string
length
calculates the length of a list or string
let
declares and initializes local variables
letex
expands local variables into an expression, then evaluates
letn
initializes local variables incrementally, like nested lets
list
makes a list
local
declares local variables
lookup
looks up members in an association list
map
maps a function over members of a list, collecting the results
match
matches patterns against lists; for matching against strings, see
find and regex
member
finds a member of a list or string
name
returns the name of a symbol or its context as a string
not
logical not
nth
gets the nth element of a list or string
or
logical or
pop
deletes and returns an element from a list or string
push
inserts a new element into a list or string
quote
quotes an expression
ref
returns the position of an element inside a nested list
ref-all
returns a list of index vectors of element inside a nested list
rest
returns all but the first element of a list or string
replace
replaces elements inside a list or string
reverse
reverses a list or string
rotate
rotates a list or string
select
selects and permutes elements from a list or string
set
sets the binding or contents of a symbol
setf setq
sets contents of a symbol or list, array or string reference
set-ref
searches for an element in a nested list and replaces it
set-ref-all
searches for an element in a nested list and replaces all instances
silent
works like begin but suppresses console output of the return value
slice
extracts a sublist or substring
sort
sorts the members of a list
starts-with
checks the beginning of a string or list against a key of the same type
swap
swaps two elements inside a list or string
unify
unifies two expressions
unique
returns a list without duplicates
unless
evaluates an expression conditionally
until
repeats evaluation of an expression until the condition is met
when
evaluates a block of statements conditionally
while
repeats evaluation of an expression while the condition is true
String and conversion functions
address
gets the memory address of a number or string
append
appends lists, arrays or strings to form a new list, array or string
bits
translates a number into binary representation
char
translates between characters and ASCII codes
chop
chops off characters from the end of a string
dostring
evaluates once for each character in a string
dup
duplicates a list or string a specified number of times
ends-with
checks the end of a string or list against a key of the same type
encrypt
does a one-time–pad encryption and decryption of a string
eval-string
compiles, then evaluates a string
explode
transforms a string into a list of characters
find
searches for an element in a list or string
find-all
returns a list of all pattern matches found in string
first
gets the first element in a list or string
float
translates a string or integer into a floating point number
format
formats numbers and strings as in the C language
get-char
gets a character from a memory address
get-float
gets a double float from a memory address
get-int
gets a 32-bit integer from a memory address
get-long
gets a long 64-bit integer from a memory address
get-string
gets a string from a memory address
int
translates a string or float into an integer
join
joins a list of strings
last
returns the last element of a list or string
lower-case
converts a string to lowercase characters
member
finds a list or string member
name
returns the name of a symbol or its context as a string
nth
gets the nth element in a list or string
pack
packs newLISP expressions into a binary structure
parse
breaks a string into tokens
pop
pops from a string
push
pushes onto a string
regex
performs a Perl-compatible regular expression search
regex-comp
pre-compiles a regular expression pattern
replace
replaces elements in a list or string
rest
gets all but the first element of a list or string
reverse
reverses a list or string
rotate
rotates a list or string
select
selects and permutes elements from a list or string
setf setq
sets contents of a string reference
slice
extracts a substring or sublist
source
returns the source required to bind a symbol as a string
starts-with
checks the start of the string or list against a key string or list
string
transforms anything into a string
sym
translates a string into a symbol
title-case
converts the first character of a string to uppercase
trim
trims a string on one or both sides
unicode
converts ASCII or UTF-8 to UCS-4 Unicode
utf8
converts UCS-4 Unicode to UTF-8
utf8len
returns length of an UTF-8 string in UTF-8 characters
unpack
unpacks a binary structure into newLISP expressions
upper-case
converts a string to uppercase characters
Floating point math and special functions
abs
returns the absolute value of a number
acos
calculates the arc-cosine of a number
acosh
calculates the inverse hyperbolic cosine of a number
add
adds floating point or integer numbers and returns a floating point number
array
creates an array
array-list
returns a list conversion from an array
asin
calculates the arcsine of a number
asinh
calculates the inverse hyperbolic sine of a number
atan
calculates the arctangent of a number
atanh
calculates the inverse hyperbolic tangent of a number
atan2
computes the principal value of the arctangent of Y / X in radians
beta
calculates the beta function
betai
calculates the incomplete beta function
binomial
calculates the binomial function
ceil
rounds up to the next integer
cos
calculates the cosine of a number
cosh
calculates the hyperbolic cosine of a number
crc32
calculates a 32-bit CRC for a data buffer
crit-chi2
calculates the Chi² for a given probability
crit-z
calculates the normal distributed Z for a given probability
dec
decrements a number in a variable, list or array
div
divides floating point or integer numbers
erf
calculates the error function of a number
exp
calculates the exponential e of a number
factor
factors a number into primes
fft
performs a fast Fourier transform (FFT)
floor
rounds down to the next integer
flt
converts a number to a 32-bit integer representing a float
gammai
calculates the incomplete Gamma function
gammaln
calculates the log Gamma function
gcd
calculates the greatest common divisor of a group of integers
ifft
performs an inverse fast Fourier transform (IFFT)
inc
increments a number in a variable, list or array
inf?
checks if a floating point value is infinite
log
calculates the natural or other logarithm of a number
min
finds the smallest value in a series of values
max
finds the largest value in a series of values
mod
calculates the modulo of two numbers
mul
multiplies floating point or integer numbers
NaN?
checks if a float is NaN (not a number)
round
rounds a number
pow
calculates x to the power of y
sequence
generates a list sequence of numbers
series
creates a geometric sequence of numbers
sgn
calculates the signum function of a number
sin
calculates the sine of a number
sinh
calculates the hyperbolic sine of a number
sqrt
calculates the square root of a number
sub
subtracts floating point or integer numbers
tanh
calculates the hyperbolic tangent of a number
uuid
returns a UUID (Universal Unique IDentifier)
Matrix functions
det
returns the determinant of a matrix
invert
returns the inversion of a matrix
mat
performs scalar operations on matrices
multiply
multiplies two matrices
transpose
returns the transposition of a matrix
Array functions
append
appends arrays
array
creates and initializes an array with up to 16 dimensions
array-list
converts an array into a list
array?
checks if expression is an array
det
returns the determinant of a matrix
first
returns the first row of an array
invert
returns the inversion of a matrix
last
returns the last row of an array
mat
performs scalar operations on matrices
multiply
multiplies two matrices
nth
returns an element of an array
rest
returns all but the first row of an array
setf
sets contents of an array reference
slice
returns a slice of an array
transpose
transposes a matrix
Bit operators
<<, >>
bit shift left, bit shift right
&
bitwise and
|
bitwise inclusive or
^
bitwise exclusive or
~
bitwise not
Predicates
atom?
checks if an expression is an atom
array?
checks if an expression is an array
context?
checks if an expression is a context
directory?
checks if a disk node is a directory
empty?
checks if a list or string is empty
file?
checks if a file exists
float?
checks if an expression is a float
global?
checks if a symbol is global
inf?
checks if a floating point value is infinite
integer?
checks if an expression is an integer
lambda?
checks if an expression is a lambda expression
legal?
checks if a string contains a legal symbol
list?
checks if an expression is a list
macro?
checks if an expression is a lambda-macro expression
NaN?
checks if a float is NaN (not a number)
nil?
checks if an expression is nil
null?
checks if an expression is nil, "", (), 0 or 0.0
number?
checks if an expression is a float or an integer
protected?
checks if a symbol is protected
primitive?
checks if an expression is a primitive
quote?
checks if an expression is quoted
string?
checks if an expression is a string
symbol?
checks if an expression is a symbol
true?
checks if an expression is not nil
zero?
checks if an expression is 0 or 0.0
Time and date functions
date
converts a date-time value to a string
date-value
calculates the time in seconds since January 1, 1970 for a date and time
parse-date
parses a date string and returns the number of seconds passed since January 1, 1900
now
returns a list of current date-time information
time
calculates the time it takes to evaluate an expression in milliseconds
time-of-day
calculates the number of milliseconds elapsed since the day started
Simulation and modeling functions
amb
randomly selects an argument and evaluates it
bayes-query
calculates Bayesian probabilities for a data set
bayes-train
counts items in lists for Bayesian or frequency analysis
normal
makes a list of normal distributed floating point numbers
prob-chi2
calculates the cumulated probability of Chi²
prob-z
calculates the cumulated probability of a Z-value
rand
generates random numbers in a range
random
generates a list of evenly distributed floats
randomize
shuffles all of the elements in a list
seed
seeds the internal random number generator
Pattern matching
ends-with
tests if a list or string ends with a pattern
find
searches for a pattern in a list or string
find-all
finds all occurrences of a pattern in a string
match
matches list patterns
parse
breaks a string along around patterns
regex
finds patterns in a string
replace
replaces patterns in a string
search
searches for a pattern in a file
starts-with
tests if a list or string starts with a pattern
unify
performs a logical unification of patterns
Financial math functions
fv
returns the future value of an investment
irr
calculates the internal rate of return
nper
calculates the number of periods for an investment
npv
calculates the net present value of an investment
pv
calculates the present value of an investment
pmt
calculates the payment for a loan
Input/output and file operations
append-file
appends data to a file
close
closes a file
current-line
retrieves contents of last read-line buffer
device
sets or inquires about current print device
exec
launches another program, then reads from or writes to it
load
loads and evaluates a file of newLISP code
open
opens a file for reading or writing
peek
checks file descriptor for number of bytes ready for reading
print
prints to the console or a device
println
prints to the console or a device with a line-feed
read-buffer
reads binary data from a file
read-char
reads an 8-bit character from a file
read-file
reads a whole file in one operation
read-key
reads a keyboard key
read-line
reads a line from the console or file
read-utf8
reads UTF-8 character from a file
save
saves a workspace, context, or symbol to a file
search
searches a file for a string
seek
sets or reads a file position
write-buffer
writes binary data to a file or string
write-char
writes a character to a file
write-file
writes a file in one operation
write-line
writes a line to the console or a file
Processes and the Cilk API
!
shells out to the operating system
abort
aborts a child process started with spawn
destroy
destroys a process created with fork or process
exec
runs a process, then reads from or writes to it
fork
launches a newLISP child process
pipe
creates a pipe for interprocess communication
process
launches a child process, remapping standard I/O and standard error
receive
receive a message from another process
semaphore
creates and controls semaphores
send
send a message to another process
share
shares memory with other processes
spawn
launches a child process for Cilk process management
sync
waits for child processes launched with spawn and collects results
wait-pid
waits for a child process to end
File and directory management
change-dir
changes to a different drive and directory
copy-file
copies a file
delete-file
deletes a file
directory
returns a list of directory entries
file-info
gets file size, date, time, and attributes
make-dir
makes a new directory
real-path
returns the full path of the relative file path
remove-dir
removes an empty directory
rename-file
renames a file or directory
HTTP networking API
base64-enc
encodes a string into BASE64 format
base64-dec
decodes a string from BASE64 format
delete-url
deletes a file or page from the web
get-url
reads a file or page from the web
post-url
posts info to a URL address
put-url
uploads a page to a URL address
xfer-event
registers an event handler for HTTP byte transfers
xml-error
returns last XML parse error
xml-parse
parses an XML document
xml-type-tags
shows or modifies XML type tags
Socket TCP/IP and UDP network API
net-accept
accepts a new incoming connection
net-close
closes a socket connection
net-connect
connects to a remote host
net-error
returns the last error
net-eval
evaluates expressions on multiple remote newLISP servers
net-eval
Sets the default interface IP address on multihoned computers.
net-listen
listens for connections to a local socket
net-local
returns the local IP and port number for a connection
net-lookup
returns the name for an IP number
net-peer
returns the remote IP and port for a net connect
net-peek
returns the number of characters ready to be read from a network socket
net-ping
sends a ping packet (ICMP echo request) to one or more addresses
net-receive
reads data on a socket connection
net-receive-from
reads a UDP on an open connection
net-receive-udp
reads a UDP and closes the connection
net-select
checks a socket or list of sockets for status
net-send
sends data on a socket connection
net-send-to
sends a UDP on an open connection
net-send-udp
sends a UDP and closes the connection
net-service
translates a service name into a port number
net-sessions
returns a list of currently open connections
Reflection and customization
command-event
pre-processes the command-line and HTTP requests
pretty-print
changes the pretty-printing characteristics
prompt-event
customizes the interactive newLISP shell prompt
read-expr
reads and optionally translates s-expressions from source
source
returns the source required to bind a symbol to a string
System functions
$
accesses system variables $0 -> $15
catch
evaluates an expression, catching errors and early returns
context
creates or switches to a different namespace
copy
copies the result of an evaluation
debug
debugs a user-defined function
delete
deletes symbols from the symbol table
default
returns the contents of a default functor from a context
env
gets or sets the operating system's environment
error-event
defines an error handler
exit
exits newLISP, setting the exit value
global
makes a symbol accessible outside MAIN
import
imports a function from a shared library
last-error
report the last error number and text
main-args
gets command-line arguments
new
creates a copy of a context
ostype
contains a string describing the OS platform
pretty-print
changes the pretty-printing characteristics
reset
goes to the top level
set-locale
switches to a different locale
signal
sets a signal handler
sleep
suspends processing for specified milliseconds
symbols
returns a list of all symbols in the system
sys-error
reports OS system error numbers
sys-info
gives information about system resources
throw
causes a previous catch to return
throw-error
throws a user-defined error
timer
starts a one-shot timer, firing an event
trace
sets or inquires about trace mode
trace-highlight
sets highlighting strings in trace mode
Importing libraries
address
returns the memory address of a number or string
flt
converts a number to a 32-bit integer representing a float
float
translates a string or integer into a floating point number
get-char
gets a character from a memory address
get-float
gets a double float from a memory address
get-int
gets a 32-bit integer from a memory address
get-long
gets a long 64-bit integer from a memory address
get-string
gets a string from a memory address
import
imports a function from a shared library
int
translates a string or float into an integer
pack
packs newLISP expressions into a binary structure
unpack
unpacks a binary structure into newLISP expressions
newLISP internals API
cpymem
copies memory between addresses
dump
shows memory address and contents of newLISP cells
read-expr
reads and optionally translates s-expressions from source
4. Functions in alphabetical order
!
syntax: (! str-shell-command)
(! "vi")
(! "ls -ltr")
> !ls -ltr ; executed in the newLISP shell window
$
syntax: ($ int-idx)
(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"
+, -, *, / ,%
syntax: (+ int-1 [int-2 ... ])
syntax: (- int-1 [int-2 ... ])
syntax: (* int-1 [int-2 ... ])
syntax: (/ int-1 [int-2 ... ])
syntax: (% int-1 [int-2 ... ])
(+ 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
<, >, =, <=, >=, !=
syntax: (< exp-1 exp-2 [exp-3 ... ])
syntax: (> exp-1 exp-2 [exp-3 ... ])
syntax: (= exp-1 exp-2 [exp-3 ... ])
syntax: (<= exp-1 exp-2 [exp-3 ... ])
syntax: (>= exp-1 exp-2 [exp-3 ... ])
syntax: (!= exp-1 exp-2 [exp-3 ... ])
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)
<<, >>
syntax: (<< int-1 int-2 [int-3 ... ])
syntax: (>> int-1 int-2 [int-3 ... ])
syntax: (<< int-1)
syntax: (>> int-1)
(>> 0x800000000000000 1) → 0xC00000000000000 ; not 0x040000000000000!
(<< 1 3) → 8
(<< 1 2 1) → 8
(>> 1024 10) → 1
(>> 160 2 2) → 10
(<< 3) → 6
(>> 8) → 4
&
syntax: (& int-1 int-2 [int-3 ... ])
(& 0xAABB 0x000F) → 11 ; which is 0xB
|
syntax: (| int-1 int-2 [int-3 ... ])
(| 0x10 0x80 2 1) → 147
^
syntax: (^ int-1 int-2 [int-3 ... ])
(^ 0xAA 0x55) → 255
~
syntax: (~ int)
(format "%X" (~ 0xFFFFFFAA)) → "55"
(~ 0xFFFFFFFF) → 0
:
syntax: (: sym-function list-object [ ... ])
(define (Rectangle:area p)
(mul (p 3) (p 4)))
(define (Circle:area c)
(mul (pow (c 3) 2) (acos 0) 2))
(define (Rectangle:move p dx dy)
(list rectangle (add (p 1) dx) (add (p 2) dy) (p 3) (p 4)))
(define (Circle:move p dx dy)
(list circle (add (p 1) dx) (add (p 2) dy) (p 3)))
(set 'myrect '(Rectangle 5 5 10 20)) ; x y width height
(set 'mycircle '(Circle 1 2 10)) ; x y radius
;; explicit naming of the context methods
(Rectangle:area myrect) → 200
(Circle:area mycircle) → 314.1592654
(set 'myrect (Rectangle:move myrect 2 3))
(set 'mycircle ((Circle:move mycircle 4 5))
;; using the : (colon) operator to polymorphically
;; 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) (map eval '(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
(set 'myrect (:move myrect 2 3)) → (Rectangle 7 8 10 20)
(set 'mycircle (:move mycircle 4 5)) → (Circle 5 7 10)
abort
syntax: (abort int-pid)
syntax: (abort)
(abort 2245) → true
(abort) → true ; abort all
abs
syntax: (abs num)
(abs -3.5) → 3.5
acos
syntax: (acos num)
(acos 1) → 0
(cos (acos 1)) → 1
acosh
syntax: (acosh num-radians)
(acosh 2) → 1.316957897
(cosh (acosh 2)) → 2
(acosh 0.5) → NaN
add
syntax: (add num-1 [num-2 ... ])
(add 2 3.25 9) → 14.25
(add 1 2 3 4 5) → 15
address
syntax: (address int)
syntax: (address float)
syntax: (address str)
(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
amb
syntax: (amb exp-1 [exp-2 ... ])
(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
and
syntax: (and exp-1 [exp-2 ... ])
(set 'x 10) → 10
(and (< x 100) (> x 2)) → true
(and (< x 100) (> x 2) "passed") → "passed"
(and '()) → ()
(and true) → true
(and) → nil
append
syntax: (append list-1 [list-2 ... ])
syntax: (append array-1 [array-2 ... ])
syntax: (append str-1 [str-2 ... ])
(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")
(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))
(set 'more " how are you") → " how are you"
(append "Hello " "world," more) → "Hello world, how are you"
append-file
syntax: (append-file str-filename str-buffer)
(write-file "myfile.txt" "ABC")
(append-file "myfile.txt" "DEF")
(read-file "myfile.txt") → "ABCDEF"
(append-file "http://asite.com/message.txt" "More message text.")
apply
syntax: (apply func list [int-reduce])
(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
(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
args
syntax: (args)
syntax: (args int-idx-1 [int-idx-2 ... ])
(define-macro (print-line)
(dolist (x (args))
(print x "\n")))
(print-line "hello" "World")
(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
(define (foo a b) (args))
(foo 1 2) → ()
(foo 1 2 3 4 5) → (3 4 5)
array
syntax: (array int-n1 [int-n2 ... ] [list-init])
(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)
(set 'myarray (array 3 4 (sequence 1 12)))
→ ((1 2 3 4) (5 6 7 8) (9 10 11 12))
(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)
(array-list myarray) → ((1 2 3 4) (a b c d) (1 2 3 99))
(set 'aList '((1 2) (3 4))) → ((1 2) (3 4))
(set 'aArray (array 2 2 (flat aList))) → ((1 2) (3 4))
(array? myarray) → true
(array? (array-list myarray)) → nil
(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)))))
array-list
syntax: (array-list array)
(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)
array?
syntax: (array? exp)
(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
asin
syntax: (asin num-radians)
(asin 1) → 1.570796327
(sin (asin 1)) → 1
asinh
syntax: (asinh num-radians)
(asinh 2) → 1.443635475
(sinh (asinh 2)) → 2
assoc
syntax: (assoc exp-key list-alist)
syntax: (assoc list-exp-key list-alist)
(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
(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")
(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"
atan
syntax: (atan num-radians)
(atan 1) → 0.7853981634
(tan (atan 1)) → 1
atan2
syntax: (atan2 num-Y-radians num-X-radians)
(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
atanh
syntax: (atanh num-radians)
(atanh 0.5) → 0.5493061443
(tanh (atanh 0.5)) → 0.5
(atanh 1.1) → NaN
(atanh 1) → inf
atom?
syntax: (atom? exp)
(atom? '(1 2 3)) → nil
(and (atom? 123)
(atom? "hello")
(atom? 'foo)) → true
(atom? ''foo) → nil
base64-dec
syntax: (base64-dec str)
(base64-dec "SGVsbG8gV29ybGQ=") → "Hello World"
base64-enc
syntax: (base64-enc str)
(base64-enc "Hello World") → "SGVsbG8gV29ybGQ="
bayes-query
syntax: (bayes-query list-L context-D [bool-chain [bool-probs]])
R.A. Fisher Chi² method
;; 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)
(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)
Chain Bayesian method
(set 'Data:test-positive '(8 18))
(set 'Data:test-negative '(2 72))
(set 'Data:total '(10 90))
(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)
Specifying probabilities instead of counts
(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)
bayes-train
syntax: (bayes-train list-M1 [list-M2 ... ] sym-context-D)
(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)
; use a bayes-trained context namespace like 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)))
(set 'Data:tested-positive '(8 18))
(set 'Data:tested-negative '(2 72))
(set 'Data:total '(10 90))
(bayes-train shakespeare1 '() 'data)
(bayes-train shakespeare2 '() 'data)
(bayes-train '() hemingway1 'data)
(bayes-train '() hemingway2 'data)
(bayes-train shakepeare-rest hemingway-rest 'data)
begin
syntax: (begin body)
(begin
(print "This is a block of 2 expressions\n")
(print "================================"))
beta
syntax: (beta cum-a num-b)
(beta 1 2) → 0.5
betai
syntax: (betai num-x num-a num-b)
(betai 0.5 3 8) → 0.9453125
;; probability of F ratio for df1/df2
;;
(define (f-prob f df1 df2)
(let (prob (mul 2 (betai (div df2 (add df2 (mul df1 f)))
(mul 0.5 df2)
(mul 0.5 df1))))
(div (if (> prob 1) (sub 2 prob) prob) 2)))
bind !
syntax: (bind list-variable-associations [bool-eval])
(set 'lst '((a (+ 3 4)) (b "hello")))
(bind lst) → "hello"
a → (+ 3 4)
b → "hello"
(bind lst true) → "hello"
a → 7
(bind (unify '(p X Y a) '(p Y X X))) → a
X → a
Y → a
(set 'struct '((one "two") 3 (four (x y z))))
(set 'pattern '((A B) C (D E)))
(bind (unify pattern struct))
A → one
B → "two"
C → 3
D → four
E → (x y z)
(define-macro (foo)
(local (len width height)
(bind (args) true)
(println "len:" len " width:" width " height:" height)
))
> (foo (width (+ 15 5)) (height 30) (len 10))
len:10 width:20 height:30
> (foo (width (+ 15 5)) (height (* width 2)) (len 10))
len:10 width:20 height:40
`>
binomial
syntax: (binomial int-n int-k float-p)
(binomial 10 3 0.5) → 0.1171875
bits
syntax: (bits int [bool])
(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
callback
syntax: (callback int-index sym-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))
...
case
syntax: (case exp-switch (exp-1 body-1) [(exp-2 body-2) ... ])
(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"
catch
syntax: (catch exp)
syntax: (catch exp symbol)
(catch (dotimes (x 1000)
(if (= x 500) (throw x)))) → 500
(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
(catch (func 3 4) 'result) → nil
result
→ "ERR: invalid function in function catch : (func 3 4)"
(constant 'func +) → add <4068A6>
(catch (func 3 4) 'result) → true
result → 7
(catch (dotimes (x 100)
(if (= x 50) (throw "fin")) 'result) → true
result → "fin"
ceil
syntax: (ceil number)
(ceil -1.5) → -1
(ceil 3.4) → 4
change-dir
syntax: (change-dir str-path)
(change-dir "/etc")
char utf8
syntax: (char str [int-index])
syntax: (char int)
(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 65) → "A"
(char 66) → "B"
(char (char 65)) → 65 ; two inverse applications
(map char (sequence 1 255)) ; returns current character set
chop utf8
syntax: (chop str [int-chars])
syntax: (chop list [int-elements])
(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)
clean
syntax: (clean exp-predicate list)
(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))
close
syntax: (close int-file)
(close (device)) → true
(close 7) → true
(close aHandle) → true
command-event
syntax: (command-event sym | func)
(command-event (fn (s)
(if (starts-with s "[a-zA-Z]" 0) (append "!" s) s)))
#!/usr/local/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)))
GET /index.html
GET /index.cgi?userid=joe&password=secret
;; httpd-conf.lsp
;;
; filter and translate HTTP request 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)
))
GET /cmd.exe?dir
GET /errorpage.html
cond
syntax: (cond (exp-condition-1 body-1) [(exp-condition-2 body-2) ... ])
(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"
(cond ((+ 3 4))) → 7
cons
syntax: (cons exp-1 exp-2)
(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) → ()
(cons (first '(a b c)) (rest '(a b c))) → (a b c)
(cons (first '(x y)) (last '(x y))) → (x y)
constant !
syntax: (constant sym-1 exp-1 [sym-2 exp-2 ... ])
(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)))
(constant 'squareroot sqrt) → sqrt <406C2E>
(constant '+ add) → add <4068A6>
context
syntax: (context [sym-context])
syntax: (context sym-context str | sym [exp-value])
(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
(set 'person:age 0) ; no need to create context first
(set 'person:address "") ; useful for quickly defining data structures
(new person 'JohnDoe) → JohnDoe
(set 'JohnDoe:age 99)
(set 'human JohnDoe)
human:age → 99
(set 'human:address "1 Main Street")
JohnDoe:address → "1 Main Street"
> (context 'FOO)
FOO
FOO> (context MAIN)
MAIN
> (set 'old FOO)
FOO
> (context 'BAR)
BAR
BAR> (context MAIN:old)
FOO
FOO>
(context 'CTX)
(define (CTX:new var)
(…))
(context 'MAIN)
;; 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
context?
syntax: (context? exp)
syntax: (context? exp str-sym)
(context? MAIN) → true
(set 'x 123)
(context? x) → nil
(set 'FOO:q "hola") → "hola"
(set 'ctx FOO)
(context? ctx) → true ; ctx contains context foo
(context? FOO "q") → true
(context? FOO "p") → nil
copy
syntax: (copy exp)
(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"
copy-file
syntax: (copy-file str-from-name str-to-name)
(copy-file "/home/me/newlisp/data.lsp" "/tmp/data.lsp")
cos
syntax: (cos num-radians)
(cos 1) → 0.5403023059
(set 'pi (mul 2 (acos 0))) → 3.141592654
(cos pi) → -1
cosh
syntax: (cosh num-radians)
(cosh 1) → 1.543080635
(cosh 10) → 11013.23292
(cosh 1000) → inf
(= (cosh 1) (div (add (exp 1) (exp -1)) 2)) → true
count
syntax: (count list-1 list-2)
(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))
cpymem
syntax: (cpymem int-from-address int-to-address int-bytes)
(cpymem (pack "c c" 0 32) (last (dump 'sym)) 2)
(set 's "0123456789")
(cpymem "xxx" (+ (address s) 5) 3)
s → "01234xxx89")
55 push epb
8B EC mov ebp, esp
8B 45 08 mov eax, [ebp+08]
03 45 0C add eax, [ebp+0c]
5D pop ebp
C3 ret
;; set code
(set 'bindata (pack "ccccccccccc"
0x55 0x8B 0xEC 0x8B 0x45 0x08 0x03 0x45 0x0C 0x5D 0xC3))
;; get function template
(set 'foo print)
;; change type to library import and OS calling conventions
;(cpymem (pack "ld" 265) (first (dump foo)) 4) ; Win32 stdcall
(cpymem (pack "ld" 264) (first (dump foo)) 4) ; Linux cdecl
;; set code pointer
(cpymem (pack "ld" (address bindata)) (+ (first (dump foo)) 12) 4)
;; execute
(foo 3 4) → 7
crc32
syntax: (crc32 str-data)
(crc32 "abcdefghijklmnopqrstuvwxyz") → 1277644989
crit-chi2
syntax: (crit-chi2 num-probability num-df)
(crit-chi2 0.99 4) → 13.27670443
crit-z
syntax: (crit-z num-probability)
(crit-z 0.999) → 3.090232372
current-line
syntax: (current-line)
#!/usr/local/bin/newlisp
(set 'inFile (open (main-args 2) "read"))
(while (read-line inFile)
(if (starts-with (current-line) ";;")
(write-line)))
(exit)
./filter myfile.lsp
curry
syntax: (curry func exp)
(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))
date utf8
syntax: (date)
syntax: (date int-secs [int-offset])
syntax: (date int-secs int-offset str-format)
(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"
(set-locale "german") → "de_DE"
(date (date-value) 0 "%A %-d. %B %Y")
→ "Montag 7. März 2005"
; on Linux - suppresses the leading 0
(set-locale "C") ; default POSIX
(date (date-value) 0 "%A %B %d %Y")
→ "Monday March 07 2005"
(date (date-value) 0 "%a %#d %b %Y")
→ "Mon 7 Mar 2005"
; suppressing leading 0 on Win32 using #
(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
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
date-value
syntax: (date-value int-year int-month int-day [int-hour int-min int-sec])
syntax: (date-value)
(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"
(define (value-date val)
(append
(slice (now (- (/ val 60) (/ (date-value) 60) )) 0 5)
(list (% val 60))))
(value-date 1014854400) → (2002 2 28 0 0 0)
debug
syntax: (debug func)
;; instead of doing
(trace true)
(my-func a b c)
(trace nil)
;; use debug as a shortcut
(debug (my-func a b c))
dec !
syntax: (dec place [num])
(set x 10) → 10
(dec x) → 9
x → 9
(dec x 0.25) → 8.75
x → 8.75
z → nil
(dec z) → -1
(set z nil)
(dec z 0.01) → -0.01
(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
def-new
syntax: (def-new sym-source [sym-target])
> (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)
default
syntax: (default context)
(define Foo:Foo 123)
(default Foo) → 123
(setf (default Foo) 456)
(set 'ctx Foo)
(default ctx) → 456
Foo:Foo → 456
define !
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)
(define (area x y) (* x y)) → (lambda (x y) (* x y))
(area 2 3) → 6
(set 'area (lambda (x y) (* x y))
((lambda ( x y) (* x y)) 2 3) → 6
((fn ( x y) (* x y)) 2 3) → 6
(define (foo (a 1) (b 2))
(list a b))
(foo) → (1 2)
(foo 3) → (3 2)
(foo 3 4) → (3 4)
(define-macro (foo (a 10) (b (div a 2)))
(list a b))
(foo) → (10 5)
(foo 30) → (30 15)
(foo 3 4) → (3 4)
(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))
define-macro
syntax: (define-macro (sym-name [sym-param-1 ... ]) body)
syntax: (define-macro (sym-name [(sym-param-1 exp-default) ... ]) body)
(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
(define-macro (foo (a 1) (b 2))
(list a b))
(foo) → (1 2)
(foo 3) → (3 2)
(foo 3 4) → (3 4)
(define-macro (foo (a 10) (b (div a 2)))
(list a b))
(foo) → (10 5)
(foo 30) → (30 15)
(foo 3 4) → (3 4)
;; 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
;; a 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
;; avoid variable capture in macros using the args function
(define-macro (my-setq) (set (args 0) (eval (args 1))))
(define-macro (dolist-while)
(letex (var (args 0 0)
lst (args 0 1)
cnd (args 0 2)
body (cons 'begin (1 (args))))
(let (res)
(catch (dolist (var lst)
(if (set 'res cnd) body (throw res)))))))
> (dolist-while (x '(a b c d e f) (!= x 'd)) (println x))
a
b
c
nil
>
delete
syntax: (delete symbol [bool])
syntax: (delete sym-context [bool])
(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
delete-file
syntax: (delete-file str-file-name)
(delete-file "junk")
(delete-file "http://asite.com/example.html")
(delete-file "file://aFile.txt")
delete-url
syntax: (delete-file str-url)
(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")
destroy
syntax: (destroy int-pid)
syntax: (destroy int-pid int-signal)
(set 'pid (process "/usr/local/bin/bc" bcin bcout))
(destroy pid)
(set 'pid (fork (dotimes (i 1000) (println i) (sleep 10))))
(sleep 100) (destroy pid)
det
syntax: (det matrix)
(set 'A '((-1 1 1) (1 4 -5) (1 -2 0)))
(det A) → -1
device
syntax: (device [int])
(device (open "myfile" "write")) → 5
(print "This goes in myfile") → "This goes in myfile"
(close (device)) → true
difference
syntax: (difference list-A list-B)
syntax: (difference list-A list-B bool)
(difference '(2 5 6 0 3 5 0 2) '(1 2 3 3 2 1)) → (5 6 0)
(difference '(2 5 6 0 3 5 0 2) '(1 2 3 3 2 1) true) → (5 6 0 5 0)
directory
syntax: (directory [str-path])
syntax: (directory str-path str-pattern [int-option])
(directory "/bin")
(directory "c:/")
(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")
directory?
syntax: (directory? str-path)
(directory? "/etc") → true
(directory? "/usr/local/bin/emacs/") → nil
div
syntax: (div num-1 num-2 [num-3 ... ])
syntax: (div num-1)
(div 10 3) → 3.333333333
(div 120 (sub 9.0 6) 100) → 0.4
(div 10) → 0.1
do-until
syntax: (do-until exp-condition [body])
(set 'x 1)
(do-until (> x 0) (inc x))
x → 2
(set 'x 1)
(until (> x 0) (inc x))
x → 1
do-while
syntax: (do-while exp-condition body)
(set 'x 10)
(do-while (< x 10) (inc x))
x → 11
(set 'x 10)
(while (< x 10) (inc x))
x → 10
doargs
syntax: (doargs (sym [exp-break]) body)
(define (foo)
(doargs (i) (println i)))
> (foo 1 2 3 4 5)
1
2
3
4
5
(define-macro (foo)
(doargs (i (= i 'x))
(println i)))
> (foo a b c x e f g)
a
b
c
true
dolist
syntax: (dolist (sym list [exp-break]) 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
(dolist (x '(a b d e f g))
(println $idx ":" x)) → g
0:a
1:b
2:d
3:e
4:f
5:g
dostring utf8
syntax: (dostring (sym string [exp-break]) 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 - 。
dotimes
syntax: (dotimes (sym-var int-count [exp-break]) body)
(dotimes (x 10)
(print x)) → 9 ; return value
dotree
syntax: (dotree (sym sym-context [bool]) body)
;; faster and less memory overhead
(dotree (s SomeCTX) (print s " "))
;; slower and higher memory usage
(dolist (s (symbols SomeCTX)) (print s " "))
dump
syntax: (dump [exp])
(dump 'a) → (9586996 5 9578692 9578692 9759280)
(dump 999) → (9586996 130 9578692 9578692 999)
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 float4 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
dup
syntax: (dup exp int-n [bool])
syntax: (dup exp)
(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 "*") → "**"
empty?
syntax: (empty? exp)
syntax: (empty? str)
(set 'var '())
(empty? var) → true
(empty? '(1 2 3 4)) → nil
(empty? "hello") → nil
(empty? "") → true
encrypt
syntax: (encrypt str-source str-pad)
(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"
(write-file "myfile.enc"
(encrypt (read-file "myfile") "29kH67*"))
ends-with
syntax: (ends-with str-data str-key [option])
syntax: (ends-with list exp)
(ends-with "newLISP" "LISP") → true
(ends-with "newLISP" "lisp") → nil
(ends-with "newLISP" "lisp" nil) → true
;; use regular expressions
(ends-with "newLISP" "lisp|york" 1) → true
(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
env
syntax: (env)
syntax: (env var-str)
syntax: (env var-str value-str)
(env)
→ (("PATH" "/bin:/usr/local/bin:/sbin") ("TERM" "xterm-color") ... ))
(env "PATH") → "/bin:/usr/local/bin:/usr/local/bin"
(env "NEWLISPBIN" "/usr/local/bin/") → true
(env "NEWLISPBIN") → "/usr/local/bin/"
(env "NEWLISPBIN" "") → true
(env "NEWLISPBIN") → nil
erf
syntax: (erf num)
(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)
error-event
syntax: (error-event sym)
syntax: (error-event func)
(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
eval
syntax: (eval exp)
(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
; 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
(define (change-list aList) (push 999 (eval aList)))
(set 'data '(1 2 3 4 5))
(change-list 'data) → (999 1 2 3 4 5)
eval-string
syntax: (eval-string str-source [sym-context [exp-error [int-offset]]])
(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
exec
syntax: (exec str-process)
syntax: (exec str-process [str-stdin])
(exec "ls *.c") → ("newlisp.c" "nl-math.c" "nl-string.c")
(exec "cgiProc" query)
exists
syntax: (exists func-condition list)
(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
exit
syntax: (exit [int])
(exit 5)
exp
syntax: (exp num)
(exp 1) → 2.718281828
(exp (log 1)) → 1
expand
syntax: (expand exp sym-1 [sym-2 ... ])
syntax: (expand exp list-assoc [bool])
syntax: (expand exp)
(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))
(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
(set 'a '(b c))
(set 'b 1)
(expand '(a b c) 'a 'b) → ((1 c) 1 c)
syntax: (expand list list-assoc [bool])
(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)
syntax: (expand list)
(set 'A 1 'Bvar 2 'C nil 'd 5 'e 6)
(expand '(A (Bvar) C d e f)) → (1 (2) C d e f)
(define (raise-to Power)
(expand (fn (base) (pow base Power))))
> (define cube (raise-to 3))
(lambda (base) (pow base 3))
> (cube 4)
64
> _
explode utf8
syntax: (explode str [int-chunk [bool]])
syntax: (explode list [int-chunk [bool]])
(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")
(explode "\000\001\002\003")
→ ("\000" "\001" "\002" "\003")
(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 h) 2) → ((a b) (c d) (e f) (g))
; omit last chunk if too short
(explode '(a b c d e f g h) 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))
factor
syntax: (factor int)
(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)
fft
syntax: (fft list-num)
(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))
file-info
syntax: (file-info str-name [int-index [bool-flag]])
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
(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"
file?
syntax: (file? str-name)
(if (file? "afile") (set 'fileNo (open "afile" "read")))
filter
syntax: (filter exp-predicate exp-list)
(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))
find
syntax: (find exp-key list [func-compare | int-option])
syntax: (find str-key str-data [int-option [int-offset]])Find an expression in a list
; 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)
Find a string in a string
; 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"
find-all
syntax: (find-all str-pattern str-text [exp [int-option]])
syntax: (find-all list-pattern list-lists [exp])
syntax: (find-all exp-key list exp func-compare)
(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")
(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)
(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 $0 or $it
(find-all 5 '(2 7 4 5 9 2 4 9 7 4 8) (* 3 $it) <) → (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")
first utf8
syntax: (first list)
syntax: (first array)
syntax: (first str)
(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
(first "newLISP") → "n"
(first (rest "newLISP")) → "e"
flat
syntax: (flat 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))
float
syntax: (float exp [exp-default])
(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)))
float?
syntax: (float? exp)
(set 'num 1.23)
(float? num) → true
floor
syntax: (floor number)
(floor -1.5) → -2
(floor 3.4) → 3
flt
syntax: (flt number)
(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)
fn
syntax: (fn (list-parameters) exp-body)
(map (fn (x) (+ x x)) '(1 2 3 4 5)) → (2 4 6 8 10)
(sort '(".." "..." "." ".....") (fn (x y) (> (length x) (length y))))
→ ("....." "..." ".." ".")
for
syntax: (for (sym num-from num-to [num-step [exp-break]]) body)
> (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
> _
for-all
syntax: (for-all func-condition list)
(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
fork
syntax: (fork exp)
> (set 'x 0)
0
> (fork (while (< x 20) (println (inc x)) (sleep 1000)))
176
> 1
2
3
4
5
6
#!/usr/local/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)
process 5
process 4
process 3
process 2
process 1
(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
>
format
syntax: (format str-format exp-data-1 [exp-data-2 ... ])
syntax: (format str-format list-data)
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
format description lld decimal (64-bit) llu unsigned decimal (64-bit) llx hexadecimal (64-bit) llX hexadecimal uppercase(64-bit)
format description ld decimal (64-bit) lu unsigned decimal (64-bit) lx hexadecimal (64-bit) lX hexadecimal uppercase(64-bit)
format description I64d decimal (64-bit) I64u unsigned decimal (64-bit) I64x hexadecimal (64-bit) I64X hexadecimal uppercase(64-bit)
(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"
(format "%c" 65) → "A"
(set 'L '("hello" 123))
(format "%15s %d" L) → " hello 123"
(format "%f" 123) → 123.000000
(format "%d" 123.456) → 123
fv
syntax: (fv num-rate num-nper num-pmt num-pv [int-type])
(fv (div 0.07 12) 240 775.30 -100000) → -0.5544645052
gammai
syntax: (gammai num-a num-b)
(gammai 4 5) → 0.7349740847
Q(Chi²|df) = Q(df/2, Chi²/2) = gammai(df/2, Chi²/2)
gammaln
syntax: (gammaln num-x)
(exp (gammaln 6)) → 120
Beta(z,w) = Exp(Gammaln(z) + Gammaln(w) - Gammaln(z+w))
gcd
syntax: (gcd int-1 [int-2 ... ])
(gcd 0) → 0
(gcd 0 0) → 0
(gcd 10) → 10
(gcd 12 36) → 12
(gcd 15 36 6) → 3
get-char
syntax: (get-char int-address)
char * foo(void)
{
char * result;
result = "ABCDEFG";
return(result);
}
(import "mylib.so" "foo")
(print (get-char (foo) )) → 65
(print (get-char (+ (foo) 1))) → 66
get-float
syntax: (get-float int-address)
double float * foo(void)
{
double float * result;
…
*result = 123.456;
return(result);
}
(import "mylib.so" "foo")
(get-float (foo)) → 123.456
get-int
syntax: (get-int int-address)
int * foo(void)
{
int * result;
…
*result = 123;
return(result);
}
int foo-b(void)
{
int result;
…
result = 456;
return(result);
}
(import "mylib.so" "foo")
(get-int (foo)) → 123
(foo-b) → 456
get-long
syntax: (get-long int-address)
long long int * foo(void)
{
int * result;
…
*result = 123;
return(result);
}
long long int foo-b(void)
{
int result;
…
result = 456;
return(result);
}
(import "mylib.so" "foo")
(get-int (foo)) → 123
(foo-b) → 456
get-string
syntax: (get-string int-address)
char * foo(void)
{
char * result;
result = "ABCDEFG";
return(result);
}
(import "mylib.so" "foo")
(print (get-string (foo))) → "ABCDEFG"
(set 'buff "ABC\000\000\000") → "ABC\000\000\000"
(length buff) → 6
(get-string buff) → "ABC"
(length (get-string buff)) → 3
get-url
syntax: (get-url str-url [str-option] [int-timeout [str-header]])
(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/")
Custom header
(get-url "http://somehost.com" 5000)
GET / HTTP/1.1
Host: somehost.com
User-Agent: newLISP v8800
Connection: close
(get-url "http://somehost.com" 5000
"User-Agent: Mozilla/4.0\r\nCookie: name=fred\r\n")
GET / HTTP/1.1
Host: somehost.com
User-Agent: Mozilla/4.o
Cookie: name=fred
Connection: close
global
syntax: (global sym-1 [sym-2 ... ])
(global 'aVar 'x 'y 'z) → z
(define (foo x)
(…))
(constant (global 'foo))
global?
syntax: (global? sym)
global? 'print) → true
(global 'var) → var
(global? 'var) → true
(constant (global 'foo))
(global? 'foo) → true
if
syntax: (if exp-condition exp-1 [exp-2])
syntax: (if exp-cond-1 exp-1 exp-cond-2 exp-2 [ ... ])
(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
(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"
if-not
syntax: (if-not exp-condition exp-1 [exp-2])
(set 'x 50) → 50
(if-not (< x 100) "big" "small") → "small"
(set 'x 1000) → 1000
(if-not (< x 100) "big" "small") → "big"
ifft
syntax: (ifft list-num)
(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))
import
syntax: (import str-lib-name str-function-name ["cdecl"])
;; import in Linux
(import "libc.so.6" "printf") → printf <400862A0>
;; import in Mac OS X
(import "libc.dylib" "printf") → printf <90022080>
;; import on Win32
(import "msvcrt.dll" "printf") → printf <77C4186A>
(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
;;this pops up a message box
(MessageBoxA 0 "This is the body" "Caption" 1)
;; allocating space for a string return value
(import "kernel32.dll" "GetWindowsDirectoryA")
(set 'str (dup "\000" 64) ; reserve space and initialize
(GetWindowsDirectoryA str (length str))
str → "C:\\WINDOWS\000 "
(slice str 0 (find "\000" str)) → "C:\\WINDOWS"
;; or use trim
(trim str) → "C:\\WINDOWS"
;; passing an integer parameter by reference
(import "kernel32.dll" "GetComputerNameA")
(set 'str (dup "\000" 64) ; reserve space, initialize
;; get size in a buffer lpNum
(set 'lpNum (pack "lu" (length str)))
;; call the function
(GetComputerNameA str lpNum)
str → "LUTZ-PC\000 "
(trim str) → "LUTZ-PC"
(set 'imprime (import "libc.so.6" "printf"))
→ printf <400862A0>
(imprime "%s %d" "hola" 123)
→ "hola 123"
;; force cdecl calling conventions on Win32
(import "sqlite.dll" "sqlite_open" "cdecl") → sqlite_open <673D4888>
inc !
syntax: (inc place [num])
(set 'x 0) → 0
(inc x) → 1
x → 1
(inc x 0.25) → 1.25
x → 1.25
(inc x) → 2 ; gets truncated
z → nil
(inc z) → 1
(set 'z nil)
(inc z 0.01) → 0.01
(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
index
syntax: (index exp-predicate exp-list)
(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)
inf?
syntax: (inf? float)
(inf? (div 1 0)) → true
(div 0 0) → NaN
int
syntax: (int exp [exp-default [int-base]])
(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" "not a number") → "not a number"
(print "Enter a num:")
(set 'num (int (read-line)))
(int (bits 12345) 0 2) → 12345
integer?
syntax: (integer? exp)
(set 'num 123) → 123
(integer? num) → true
intersect
syntax: (intersect list-A list-B)
syntax: (intersect list-A list-B bool)
(intersect '(3 0 1 3 2 3 4 2 1) '(1 4 2 5))
→ (2 4 1)
(intersect '(3 0 1 3 2 3 4 2 1) '(1 4 2 5) true)
→ (1 2 4 2 1)
invert
syntax: (invert matrix)
(set 'A '((-1 1 1) (1 4 -5) (1 -2 0)))
(invert A) → ((10 2 9) (5 1 4) (6 1 5))
irr
syntax: (irr list-amounts [list-times [num-guess]])
(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
join
syntax: (join list-of-strings [str-joint [bool-trail-joint]])
(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-"
lambda
lambda-macro
lambda?
syntax: (lambda? exp)
(define (square x) (* x x)) → (lambda (x) (* x x))
square → (lambda (x) (* x x))
(lambda? square) → true
last utf8
syntax: (last list)
syntax: (last array)
syntax: (last str)
(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
(last "newLISP") → "P"
last-error
syntax: (last-error)
syntax: (last-error int-error)
(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")
legal?
syntax: (legal? str)
(symbol? (sym "one two")) → true
(legal? "one two") → nil ; contains a space
(set (sym "one two") 123) → 123
(eval (sym "one two")) → 123
length
syntax: (length exp)
(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
let
syntax: (let ((sym1 [exp-init1]) [(sym2 [exp-init2]) ... ]) body)
syntax: (let (sym1 exp-init1 [sym2 exp-init2 ... ]) body)
(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)))
((lambda (sym1 [sym2 ... ]) exp-body ) exp-init1 [ exp-init2 ])
letex
syntax: (letex ((sym1 [exp-init1]) [(sym2 [exp-init2]) ... ]) body)
syntax: (letex (sym1 exp-init1 [sym2 exp-init2 ... ]) body)
(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")
letn
syntax: (letn ((sym1 [exp-init1]) [(sym2 [exp-init2]) ... ]) body)
syntax: (letn (sym1 exp-init1 [sym2 exp-init2 ... ]) body)
(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)
(letn (x 1 y x)
(+ x y)) → 2
;; same as nested let's
(let (x 1)
(let (y x)
(+ x y))) → 2
list
syntax: (list exp-1 [exp-2 ... ])
(list 1 2 3 4 5) → (1 2 3 4 5)
(list 'a '(b c) (+ 3 4) '() '*) → (a (b c) 7 () *)
list?
syntax: (list? exp)
(set 'var '(1 2 3 4)) → (1 2 3 4)
(list? var) → true
(define (double x) (+ x x))
(list? double) → true
load
syntax: (load str-file-name-1 [str-file-name-2 ... ] [sym-context])
(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/local/share/newlisp/mysql.lsp")
local
syntax: (local (sym-1 [sym-2 ... ]) body)
log
syntax: (log num)
syntax: (log num num-base)
(log 1) → 0
(log (exp 1)) → 1
(log 1024 2) → 10
(log (exp 1) (exp 1)) → 1
lookup
syntax: (lookup exp-key list-assoc [int-index [exp-default]])
(set 'params '(
(name "John Doe")
(age 35)
(gender "M")
(balance 12.34)
))
(lookup 'age params) → 35
(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"
lower-case utf8
syntax: (lower-case str)
(lower-case "HELLO WORLD") → "hello world"
(set 'Str "ABC")
(lower-case Str) → "abc"
Str → "ABC"
macro?
syntax: (macro? exp)
(define-macro (mysetq lv rv) (set lv (eval rv)))
(macro? mysetq) → true
main-args
syntax: (main-args)
syntax: (main-args int-index)
newlisp 1 2 3
> (main-args)
("/usr/local/bin/newlisp" "1" "2" "3")
newlisp a b c
> (main-args 0)
"/usr/local/bin/newlisp"
> (main-args -1)
"c"
> (main-args 2)
"b"
> (main-args 10)
nil
#!/usr/local/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/local/bin/newlisp" "./script" "1" "2" "3")
make-dir
syntax: (make-dir str-dir-name [int-mode])
;; 0 (zero) in front of 750 makes it an octal number
(make-dir "adir" 0750)
map
syntax: (map exp-functor list-args-1 [list-args-2 ... ])
(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)
(define (foo op p)
(append (lambda (x)) (list (list op p 'x))))
(define (foo op p)
(append (fn (x)) (list (list op p 'x))))
(foo 'add 2) → (lambda (x) (add 2 x))
(map (foo add 2) '(1 2 3 4 5)) → (3 4 5 6 7 8)
(map (foo mul 3) '(1 2 3 4 5)) → (3 6 9 12 15)
(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)
(map (fn (x) (list $idx x)) '(a b c)) → ((0 a) (1 b) (2 c))
mat
syntax: (mat + | - | * | / matrix-A matrix-B)
syntax: (mat + | - | * | / matrix-A number)
(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))
(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))
match
syntax: (match list-pattern list-match [bool])
(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)) → 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
(map set '(x y) (match '(a (? c) d *) '(a (b c) d e f)))
x → b
y → (e f)
max
syntax: (max num-1 [num-2 ... ])
(max 4 6 2 3.54 7.1) → 7.1
member
syntax: (member exp list)
syntax: (member str str-key [num-option])
(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
(member "LISP" "newLISP") → "LISP"
(member "LI" "newLISP") → "LISP"
(member "" "newLISP") → "newLISP"
(member "xyz" "newLISP") → nil
(member "li" "newLISP" 1) → "LISP"
min
syntax: (min num-1 [num-2 ... ])
(min 4 6 2 3.54 7.1) → 2
mod
syntax: (mod num-1 num-2 [num-3 ... ])
(mod 10.5 3.3) → 0.6
(mod -10.5 3.3) → -0.6
mul
syntax: (mul num-1 num-2 [num-3 ... ])
(mul 1 2 3 4 5 1.1) → 132
(mul 0.5 0.5) → 0.25
multiply
syntax: (multiply matrix-A matrix-B)
(set 'A '((1 2 3) (4 5 6)))
(set 'B '((1 2) (1 2) (1 2)))
(multiply A B) → ((6 12) (15 30))
name
syntax: (name symbol [bool])
syntax: (name context)
(set 'ACTX:var 123)
(set 'sm 'ACTX:var)
(string sm) → "ACTX:var"
(name sm) → "var"
(name sm true) → "ACTX"
; name from context
(set 'ctx ACTX)
(name ctx) → "ACTX"
NaN?
syntax: (NaN? float)
; 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
net-accept
syntax: (net-accept int-socket)
(set 'socket (net-listen 1234))
(net-accept socket)
net-close
syntax: (net-close int-socket [true])
(net-close aSock)
net-connect
syntax: (net-connect str-remote-host int-port [str-mode [int-ttl]])
syntax: (net-connect str-file-path)
(define (finger nameSite , socket buffer user site)
(set 'user ((parse nameSite "@") 0))
(set 'site ((parse nameSite "@") 1))
(set 'socket (net-connect site 79))
(if socket
(net-send socket (append user "\r\n"))
"no connection")
(net-receive socket str 512)
(print "\n" str "\n"))
(finger "johnDoe@someSite.com")
Local domain Unix sockets
(net-connect "/tmp/mysocket") → 3
; on OS/2 use "\\socket\\" prefix
(net-connect "\\socket\\mysocket")
UDP communications
;; 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)
UDP multicast communications
;; 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 4096 "hello")
;; example server
(net-listen 4096 "226.0.0.1" "multi") → 5
(net-receive-from 5 20)
→ ("hello" "192.168.1.94" 32769)
UDP broadcast communications
;; 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)
net-error
syntax: (net-error)
syntax: (net-error int-error)
no description 1 Cannot open socket 2 Host name not known 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
(net-error) → nil
(net-connect "jhghjgkjhg" 80) → nil
(net-error) → (2 "ERR: Host name not known")
(net-error 10) → (10 "Cannot bind socket")
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]])
newlisp -c -d 4711 &
; or with logging connections
newlisp -l -c -d 4711 &
; comminicate via Uix loacal domain socket
newlisp -c /tmp/mysocket
; the code to be evaluated is given in an 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
; 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)
(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)
(net-eval (list
(list (Nodes 0 0) (Nodes 0 1) (Progs 0))
(list (Nodes 1 0) (Nodes 1 1) (Progs 1))
) 3000 myhandler)
net-interface
syntax: (net-interface str-ip-addr)
syntax: (net-interface)
(net-interface "192.168.1.95") → "192.168.1.95"
(net-interface "localhost") → "127.0.0.1"
net-listen
syntax: (net-listen int-port [str-ip-addr [str-mode]])
syntax: (net-listen str-file-path)
(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"))
;; listen on a specific address
(net-listen port "192.168.1.54")
Local domain Unix sockets
(net-listen "/tmp/mysocket") → 5
; on OS/2 use "\\socket\\" prefix
(net-listen "\\socket\\mysocket")
(net-accept 5)
UDP communications
(net-listen 10002 "192.168.1.120" "udp")
(net-listen 10002 "" "udp")
UDP multicast communications
;; 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)
net-local
syntax: (net-local int-socket)
(net-local 16) → ("204.179.131.73" 1689)
net-lookup
syntax: (net-lookup str-ip-number)
syntax: (net-lookup str-hostname [bool])
(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)
→ "127.0.0.2"
net-peek
syntax: (net-peek int-socket)
(set 'aSock (net-connect "aserver.com" 123))
(while ( = (net-peek aSock) 0)
(do-something-else))
(net-receive aSock buff 1024)
net-peer
syntax: (net-peer int-socket)
(net-peer 16) → ("192.100.81.100" 13)
net-ping
syntax: (net-ping str-address [int-timeout [int-count]])
syntax: (net-ping list-addresses [int-timeout [int-count]])
sudo newlisp
(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
(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
→ ()
net-receive !
syntax: (net-receive int-socket sym-buffer int-max-bytes [wait-string])
(define (gettime)
(net-connect "netcom.com" 13)
(net-receive socket buf 256)
(print buf "\n")
(net-close socket))
(define (net-receive-line socket sBuff)
(net-receive socket sBuff 256 "\n"))
(set 'bytesReceived (net-receive-line socket 'sm))
net-receive-from
syntax: (net-receive-from int-socket int-max-size)
;; 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
net-receive-udp
syntax: (net-receive-udp int-port int-maxsize [int-microsec [str-addr-if]])
;; 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)
net-select
syntax: (net-select int-socket str-mode int-micro-seconds)
syntax: (net-select list-sockets str-mode int-micro-seconds)
"write" or "w" to check if ready for writing.
"exception" or "e" to check for an error condition.
(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)
(set 'listen-list '(1001 1002))
(while (not (net-error))
(dolist (conn (net-select listen-list "r" 1000))
(accept-connection conn)) ; build and accept-list
(dolist (conn (net-select accept-list "r" 1000))
(read-connection conn)) ; read on conn socket
(dolist (conn (net-select accept-list "w" 1000))
(write-connection conn))) ; write on conn socket
net-send
syntax: (net-send int-socket str-buffer [int-num-bytes])
(set 'buf "hello there")
(net-send sock buf) → 11
(net-send sock buf 5) → 5
(net-send sock "bye bye") → 7
net-send-to
syntax: (net-send-to str-remotehost int-remoteport str-buffer int-socket)
;;;;;;;;;;;;;;;;;; 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))
net-send-udp
syntax: (net-send-udp str-remotehost int-remoteport str-buffer [bool])
(net-send-udp "somehost.com" 3333 "Hello") → 5
(net-send-udp "192.168.1.255" 2000 "Hello" true) → 5
net-service
syntax: (net-service str-service str-protocol)
(net-service "ftp" "tcp") → 21
(net-service "finger" "tcp") → 79
(net-service "net-eval" "tcp") → 4711 ; if configured
net-sessions
syntax: (net-sessions)
new
syntax: (new context-source sym-context-target [bool])
syntax: (new context-source)
(new CTX 'CTX-2) → CTX-2
;; force overwrite of existing symbols
(new CTX MyCTX true) → MyCTX
(set 'CTX:x 123)
(new CTX) → MAIN ; copies x into MAIN
x → 123
(map new '(Ct-a Ct-b Ct-c)) ; merge into current context
(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)
nil?
syntax: (nil? exp)
(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
normal
syntax: (normal float-mean float-stdev int-n)
syntax: (normal float-mean float-stdev)
(normal 10 3 10)
→ (7 6.563476562 11.93945312 6.153320312 9.98828125
7.984375 10.17871094 6.58984375 9.42578125 12.11230469)
(normal 0 1) → 0.6630859375
not
syntax: (not exp)
(not true) → nil
(not nil) → true
(not '()) → true
(not (< 1 10)) → nil
(not (not (< 1 10))) → true
now
syntax: (now [int-offset])
(now) → (2002 2 27 18 21 30 140000 57 3 300 0)
(apply date-value (now)) → 1014834090
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 Sunday time zone offset in minutes west of GMT daylight savings time type (0–6) on Linux/Unix
or bias in minutes on Win32
type area 0 not on dst
1 USA style dst
2 Australian style ds
3 Western European dst
4 Middle European dst
5 Eastern European dst
6 Canada
nper
syntax: (nper num-interest num-pmt num-pv [num-fv int-type])
(nper (div 0.07 12) 775.30 -100000) → 239.9992828
npv
syntax: (npv num-interest list-values)
(npv 0.1 '(1000 1000 1000))
→ 2486.851991
(npv 0.1 '(-2486.851991 1000 1000 1000))
→ -1.434386832e-08 ; ~ 0.0 (zero)
nth utf8
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)
(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
(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
(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
(nth 0 "newLISP") → "n"
("newLISP" 0) → "n"
("newLISP" -1) → "P"
null?
syntax: (null? exp)
(map null? '(1 0 0.0 2 NaN "hello" "" (a b c) () nil true))
→ (nil true true true nil true nil true nil true true nil)
(filter null? '(1 0 2 0.0 NaN "hello" "" (a b c) () nil true))
→ (0 0 NaN "" () nil)
(clean null? '(1 0 2 0.0 NaN "hello" "" (a b c) () nil true))
→ (1 2 "hello" (a b c) true)
number?
syntax: (number? exp)
(set 'x 1.23)
(set 'y 456)
(number? x) → true
(number? y) → true
(number? "678") → nil
open
syntax: (open str-path-file str-access-mode [str-option])
"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)
(exec "mkfifo myfifo")
;; or alternatively
(import "/lib/libc.so.6" "mkfifo")
(mkfifo "/tmp/myfifo" 0777)
or
syntax: (or exp-1 [exp-2 ... ])
(set 'x 10)
(or (> x 100) (= x 10)) → true
(or "hello" (> x 100) (= x 10)) → "hello"
(or '()) → nil
(or true) → true
(or) → nil
ostype
syntax: ostype
ostype → "Win32"
(if
(= ostype "Linux") (import "libz.so")
(= ostype "BSD") (import "libz.so")
(= ostype "OSX") (import "libz.dylib")
...
(println "cannot import libz on this platform")
)
pack
syntax: (pack str-format exp-1 [exp-2 ... ])
syntax: (pack str-format list)
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
>
switch to big endian byte order
<
switch to little endian byte order
(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)
(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)
(set 'lst '("A" "B" "C"))
(set 'adr (pack "lululu" lst))
(map get-string (unpack "lululu" adr)) → ("A" "B" "C")
(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 "<ld" 1) → "\000\000\000\001" ;; force big endian
(set 's (pack "s3" "ABC"))
(unpack "c c c" s) → (65 66 67)
parse
syntax: (parse str-data [str-break [int-option]])
(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")
(parse "1,2,3," ",") → ("1" "2" "3" "")
(parse "1,,,4" ",") → ("1" "" "" "4")
(parse "," ",") → ("" "")
(parse "") → ()
(parse "" " ") → ()
parse-date
syntax: (parse-date str-date str-format)
(parse-date "2007.1.3" "%Y.%m.%d") → 1167782400
(parse-date "January 10, 07" "%B %d, %y") → 1168387200
peek
syntax: (peek int-handle)
(peek 0) ; check # of bytes ready on stdin
pipe
syntax: (pipe)
(pipe) → (3 4) ; 3 for read, 4 for writing
pmt
syntax: (pmt num-interest num-periods num-principal
[num-future-value int-type])
(pmt (div 0.07 12) 240 100000) → -775.2989356
pop ! utf8
syntax: (pop list [int-index-1 [int-index-2 ... ]])
syntax: (pop list [list-indexes])
syntax: (pop str [int-index [int-length]])
(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
;; 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) → ""
pop-assoc !
syntax: (pop-assoc exp-key list-assoc)
syntax: (pop-assoc list-keys list-assoc)
;; 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))))
post-url
syntax: (post-url str-url str-content [str-content-type [str-option] [int-timeout [ str-header]]])
;; 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"
Additional parameters
pow
syntax: (pow num-1 num-2 [num-3 ... ])
syntax: (pow num-1)
(pow 100 2) → 10000
(pow 100 0.5) → 10
(pow 100 0.5 3) → 1000
(pow 3) → 9
pretty-print
syntax: (pretty-print [int-length [str-tab]])
(pretty-print) → (64 " ") ; default setting
(pretty-print 90 "\t") → (90 "\t")
(pretty-print 100) → (100 "\t")
;; print without formatting
(print (string my-expression))
primitive?
syntax: (primitive? exp)
(set 'var define)
(primitive? var) → true
print
syntax: (print exp-1 [exp-2 ... ])
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
(print (set 'res (+ 1 2 3)))
(print "the result is" res "\n")
"\065\066\067" → "ABC"
println
syntax: (println exp-1 [exp-2 ... ])
prob-chi2
syntax: (prob-chi2 num-chi2 num-df)
(prob-chi2 10 6) → 0.1246520195
prob-z
syntax: (prob-z num-z)
(prob-z 0.0) → 0.5
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-pipe-error])
(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
;; Linux/Unix
;; create pipes
(map set '(myin bcout) (pipe))
(map set '(bcin myout) (pipe))
;; launch Unix 'bc' calculator application
(process "/usr/local/bin/bc" bcin bcout) → 7916
(write-buffer myout "3 + 4\n") ; bc expects a line-feed
(read-line myin) → "7"
;; bc can use bignums with arbitrary precision
(write-buffer 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)
→ 1932
(write-line myout "(+ 3 4)")
(read-line myin) → "7"
;; 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-buffer 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)))
(process "app" 0 appout)
prompt-event
syntax: (prompt-event sym | func)
(prompt-event (fn (ctx) (string ctx ":" (real-path) "$ ")))
protected?
syntax: (protected? sym)
(protected? 'println) → true
(constant 'aVar 123)
(protected? 'aVar) → true
push ! utf8
syntax: (push exp list [int-index-1 [int-index-2 ... ]])
syntax: (push exp list [list-indexes])
syntax: (push str-1 str-2 [int-index])
; 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 strings
(set 'str "abcdefg")
(push "hijk" str -1) → "abcdefghijk"
str → "abcdefghijk"
(push "123" str) → "123abcdefghijk"
(push "4" str 3) → "1234abcdefghijk"
;; push on a string reference
(set 'lst '("abc" "xyz"))
(push 9 (lst 0)) → "xabc"
lst → ("xabc" "xyz")
; push on un-initialized symbol
aVar → nil
(push 999 aVar) → (999)
aVar → (999)
; 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)
put-url
syntax: (put-url str-url str-content [str-option] [int-timeout [str-header]])
(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!")
<directory /www/htdocs>
Options All
Script PUT /cgi-bin/put.cgi
</directory>
#!/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-buffer (device) buffer len))
(if (not n)
(set 'cnt len)
(begin
(inc cnt n)
(write-buffer result buffer))))
(set 'path (append
"/usr/home/johndoe"
(env "PATH_TRANSLATED")))
(write-file path result)
)
)
(exit)
Additional parameters
pv
syntax: (pv num-int num-nper num-pmt [num-fv int-type])
(pv (div 0.07 12) 240 775.30) → -100000.1373
quote
syntax: (quote exp)
(quote x) → x
(quote 123) → 123
(quote (a b c)) → (a b c)
(= (quote x) 'x) → true
quote?
syntax: (quote? exp)
(set 'var ''x) → 'x
(quote? var) → true
rand
syntax: (rand int-range [int-N])
(dotimes (x 100) (print (rand 2))) =>
11100000110100111100111101 ... 10111101011101111101001100001000
(rand 3 100) → (2 0 1 1 2 0 …)
random
syntax: (random float-offset float-scale int-n)
syntax: (random float-offset float-scale)
(random 0 1 10)
→ (0.10898973 0.69823783 0.56434872 0.041507289 0.16516733
0.81540917 0.68553784 0.76471068 0.82314585 0.95924564)
(random 10 5) → 11.0971
randomize
syntax: (randomize list [bool])
(randomize '(a b c d e f g)) → (b a c g d e f)
(randomize (sequence 1 5)) → (3 5 4 1 2)
read-buffer !
syntax: (read-buffer int-file sym-buffer int-size [str-wait])
(set 'handle (open "aFile.ext" "read"))
(read-buffer handle buff 200)
(read-buffer handle buff 1000 "password:")
read-char
syntax: (read-char int-file)
(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")
read-expr
syntax: (read-expr str-source [sym-context [exp-error [int-offset]]])
(set 'code "; a statement\n(define (double x) (+ x x))")
(read-expr code) → (define (double x) (+ x x))
$0 → 41
(read-expr "(+ 3 4)") → (+ 3 4)
(eval-string "(+ 3 4)") → 7
read-file
syntax: (read-file str-file-name)
(write-file "myfile.enc"
(encrypt (read-file "/home/lisp/myFile") "secret"))
(read-file "http://asite.com/somefile.tgz" 10000)
read-key
syntax: (read-key)
(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))
read-line
syntax: (read-line [int-file])
(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)
read-utf8
syntax: (read-utf8 int-file)
(set 'fle (open "utf8text.txt" "read"))
(while (setq chr (read-utf8 fle))
(print (char chr)))
real-path
syntax: (real-path [str-path])
(real-path) → "/usr/home/fred" ; current directory
(real-path "./somefile.txt")
→ "/usr/home/fred/somefile.txt"
receive !
syntax: (receive int-pid sym-message)
; sending process
(send spid "hello") → true
; receiving process
(receive rpid msg) → true
msg → "hello"
ref
syntax: (ref exp-key list [func-compare])
(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)
(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 the empty list is returned
(ref 'foo plist) → ()
; with optional comparison function
(set 'L '(a b (c d (e) f)))
; not specifying a comparison functor assumes =
(ref 'e L) → (2 2 0)
$0 → e
; a is the first symbol where e is greater
(ref 'e L >) → (0)
$0 → a
; use an anonymous comparison function
(ref 'e L (fn (x y) (or (= x y) (= y 'd)))) → (2 1)
$0 → d
; define the comparison function first
(define (is-it-or-d x y) (or (= x y) (= y 'd)))
(ref 'e L is-it-or-d) → (2 1)
$0 → d
(set 'L '((l 3) (a 12) (k 5) (a 10) (z 22)))
; use match as a comparison function
(ref '(a ?) L match) → (1)
$0 → (a 12)
; use unify as a comparison function
(set 'L '( ((a b) (c d)) ((e e) (f g)) ))
(ref '(X X) L unify) → (1 0)
$0 → (e e)
(ref '(X g) L) unify) → (1 1)
$0 → (f g)
(set 'C:C '(a b (c d) e f))
(ref 'd C) → (2 1)
ref-all
syntax: (ref-all exp-key list [func-compare])
(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))
; 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))
(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))
; 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))
; 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))
regex
syntax: (regex str-pattern str-text [int-option [int-offset]])
(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"
;; 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)
;; brackets inside brackets are balanced
(regex {\d{1,3}} "qwerty567asdfg") → ("567" 6 3)
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 replace PRECOMPILED 0x10000 pattern is pre-compiled, can only be combined with RREPLACE_ONCE 0x8000
i for PCRE_CASELESS m for PCRE_MULTILINE s for PCRE_DOTALL x for PCRE_EXTENDED
regex-comp
syntax: (regex-comp str-pattern [int-option])
; 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)
)
remove-dir
syntax: (remove-dir str-path)
(remove-dir "temp")
rename-file
syntax: (rename-file str-path-old str-path-new)
(rename-file "data.lisp" "data.backup")
replace !
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-option)List replacement
;; 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))
; 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
;; 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
;; string replacement
(set 'str "this isa sentence")
(replace "isa" str "is a") → "this is a sentence"
Regular expression replacement
;; 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
reset
syntax: (reset)
syntax: (reset true)
rest utf8
syntax: (rest list)
syntax: (rest array)
syntax: (rest str)
(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 '()) → ()
(rest "newLISP") → "ewLISP"
(first (rest "newLISP")) → "e"
reverse !
syntax: (reverse list)
syntax: (reverse string)
(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)
(set 'str "newLISP")
(reverse str) → "PSILwen"
str → "PSILwen"
rotate !
syntax: (rotate list [int-count])
syntax: (rotate str [int-count])
(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"
round
syntax: (round number [int-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
save
syntax: (save str-file)
syntax: (save str-file sym-1 [sym-2 ... ])
(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)
search
syntax: (search int-file str-search [bool-flag [int-options]])
(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)
seed
syntax: (seed int-seed)
(seed 12345)
(seed (date-value))
seek
syntax: (seek int-file [int-position])
(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
select utf8
syntax: (select list list-selection)
syntax: (select list [int-index_i ... ])
syntax: (select string list-selection)
syntax: (select string [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)
(set 'str "abcdefg")
(select str '(0 3 2 5 3)) → "adcfd"
(select str '(-2 -1 0)) → "fga"
(select str -2 -1 0) → "fga"
semaphore
syntax: (semaphore)
syntax: (semaphore int-id)
syntax: (semaphore int-id int-wait)
syntax: (semaphore int-id int-signal)
syntax: (semaphore int-id 0)
;; 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)
;; counter process output in bold
(define (counter n)
(println "counter started")
(dotimes (x n)
(semaphore sid -1)
(println x)))
;; hit extra <enter> 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
> _
send
syntax: (send int-pid exp)
; child process dispatching message
(set 'ppid (sys-info -4)) ; get parent pid
(send ppid "hello") ; send message
; parent process receiving message
(receive child-pid msg) → true
msg → "hello"
; blocking sender
(until (send pid msg)) ; returns true afer delivery
; blocking receiver
(until (receive pid msg)) ; returns true after pickup
Listening for messages and retrying send
; 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
(dotimes (i 5) (spawn 'result (child-process)))
(for (i 1 3)
(dolist (cpid (sync)) ; iterate thru child pids
(until (receive cpid msg))
(print "pid:" cpid "->" (format "%-2d " msg)))
(println)
)
(abort) ; cancel child-processes
(exit)
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
Messages containing code for evaluation
; sender process of the message
(set 'pidA (spawn 'result
(begin
(dotimes (i 3)
(set 'ppid (sys-info -4))
(set 'pid (sys-info -3))
(set 'msg '(until (send pidB (string "greetings from " pidA))))
(until (send ppid msg))) ; send expression in msg
; make parent exit until loop
(until (send ppid '(set 'finished true)))
)))
; final message recipient
(set 'pidB (spawn 'result
(begin
(set 'ppid (sys-info -4))
(set 'pid (sys-info -3))
(while true
(until (receive ppid msg))
(println pid " received " msg))
)))
; receive and evaluate messages from pidA
(until finished (if (receive pidA msg) (eval msg)))
(abort) (sleep 100)
(exit)
(until (send pidB (string "greetings from " pidA)))
(set 'finished true))
sequence
syntax: (sequence num-start num-end [num-step])
(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)
series
syntax: (series num-start num-factor num-count)
syntax: (series exp-start func num-count)
(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)
; embed the function f(x) = 1 / (1 + x)
(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")
set !
syntax: (set sym-1 exp-1 [sym-2 exp-2 ... ])
(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"
(set 'lst '(x y z)) → (x y z)
(set (first lst) 123) → 123
x → 123
(set 'double (lambda (x) (+ x x)))
→ (lambda (x) (+ x x))
(define (double x) (+ x x))
→ (lambda (x) (+ x x))
(define double (lambda (x) (+ x x)))
→ (lambda (x) (+ x x))
set-locale
syntax: (set-locale [str-locale [int-category]])
(set-locale) ; report current locale
(set-locale "") ; set default locale of your platform
;; after newLISP start up
(set-locale) → ("C" ".")
set-ref !
syntax: (set-ref (list exp-key) exp-replacement [func-compare])
(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)))
(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))
set-ref-all !
syntax: (set-ref-all exp-key list exp-replacement [func-compare])
(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)))
(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)))
(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) ... )
setq setf !
syntax: (setq place-1 exp-1 [place-2 exp-2 ... ])
(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"
(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"
(setq l1 '(a b c))
(setq l2 '(d e f))
(setf 1 (append l1 l2) 99)
ERR: no symbol reference found in function setf
sgn
syntax: (sgn num)
syntax: (sgn num exp-1 [exp-2 [exp-3]])
x < 0 : sgn(x) = -1
x = 0 : sgn(x) = 0
(sgn -3.5) → -1
(sgn 0) → 0
(sgn 123) → 1
(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
share
syntax: (share)
syntax: (share int-address-or-handle)
syntax: (share int-address-or-handle exp-value)
syntax: (share nil int-address)
(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 mmem)) → 10
(share nil mem) → true ; unmap only on Unix
signal
syntax: (signal int-signal sym-handler)
syntax: (signal int-signal func-handler)
syntax: (signal int-signal nil | true)
syntax: (signal int-signal)
(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
(signal SIGINT exit) → $signal-2
(signal SIGINT (fn (s) (println "signal " s " occurred")))
kill -s SIGINT 2035
(destroy 2035) → true
(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
…
(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))
silent
syntax: (silent [exp-1 [exp-2 ... ]])
(silent (my-func)) ; same as next
(silent) (my-func) ; same effect as previous
sin
syntax: (sin num-radians)
(sin 1) → 0.8414709838
(set 'pi (mul 2 (acos 0))) → 3.141592654
(sin (div pi 2)) → 1
sinh
syntax: (sinh num-radians)
(sinh 1) → 1.175201194
(sinh 10) → 11013.23287
(sinh 1000) → inf
(sub (tanh 1) (div (sinh 1) (cosh 1))) → 0
sleep
syntax: (sleep num-milliseconds)
(sleep 1000) ; sleeps 1 second
(sleep 0.5) ; sleeps 500 micro seconds
slice
syntax: (slice list int-index [int-length])
syntax: (slice array int-index [int-length])
syntax: (slice str int-index [int-length])
(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))
(slice "Hello World" 6 2) → "Wo"
(slice "Hello World" 0 5) → "Hello"
(slice "Hello World" 6) → "World"
(slice "newLISP" -4 2) → "LI"
sort !
syntax: (sort list [func-compare])
Atoms: nil, true, integer or float, string, symbol, primitive
Lists: quoted expression, list, lambda, lambda-macro
(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)
;; the quote can be omitted beginning with version 8.4.5
(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))))
source
syntax: (source)
syntax: (source sym-1 [sym-2 ... ])
(define (double x) (+ x x))
(source 'double) → "(define (double x)\n (+ x x))\n\n"
spawn
syntax: (spawn sym exp)
; 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)
(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 "."))
(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)))
(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")
)
(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
sqrt
syntax: (sqrt num)
(sqrt 10) → 3.16227766
(sqrt 25) → 5
starts-with
syntax: (starts-with str str-key [num-option])
syntax: (starts-with list [exp])
(starts-with "this is useful" "this") → true
(starts-with "this is useful" "THIS") → nil
(starts-with "this is useful" "THIS" nil) → true
;; use regular expressions
(starts-with "this is useful" "this|that" 1) → true
(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
string
syntax: (string exp-1 [exp-2 ... ])
(string 'hello) → "hello"
(string 1234) → "1234"
(string '(+ 3 4)) → "(+ 3 4)"
(string (+ 3 4) 8) → "78"
(string 'hello " " 123) → "hello 123"
(set 'buff "ABC\000\000\000") → "ABC\000\000\000"
(length buff) → 6
(string buff) → "ABC"
(length (string buff)) → 3
string?
syntax: (string? exp)
(set 'var "hello")
(string? var) → true
sub
syntax: (sub num-1 [num-2 ... ])
(sub 10 8 0.25) → 1.75
(sub 123) → -123
swap !
syntax: (swap place-1 place-2)
(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))
sync
syntax: (sync int-timeout [func-inlet])
syntax: (sync)
; 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)
; return a list of pending child processes
(sync) → (245 246 247 248)
sym
syntax: (sym string [sym-context nil-flag])
syntax: (sym number [sym-context nil-flag])
syntax: (sym symbol [sym-context nil-flag])
(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
;; 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
(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)
symbol?
syntax: (symbol? exp)
(set 'x 'y) → y
(symbol? x) → true
(symbol? 123) → nil
(symbol? (first '(var x y z))) → true
symbols
syntax: (symbols [context])
(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
sys-error
syntax: (sys-error)
syntax: (sys-error int-error)
syntax: (sys-error 0)
;; 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-info
syntax: (sys-info [int-idx])
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, cygwin=5, win32=6, os/2=7, tru64unix=9
bit 9 will be set for IPv6 versions (add 256)
bit 8 will be set for UTF-8 versions (add 128)
bit 7 will be added for library versions (add 64)
(sys-info) → (401 268435456 376 1 0 2048 39220 10002 131)
(sys-info 3) → 1
(sys-info -2) → 10002
tan
syntax: (tan num-radians)
(tan 1) → 1.557407725
(set 'pi (mul 2 (asin 1))) → 3.141592654
(tan (div pi 4)) → 1
tanh
syntax: (tanh num-radians)
(tanh 1) → 0.761594156
(tanh 10) → 0.9999999959
(tanh 1000) → 1
(= (tanh 1) (div (sinh 1) (cosh 1))) → true
throw
syntax: (throw exp)
(define (throw-test)
(dotimes (x 1000)
(if (= x 500) (throw "interrupted"))))
(catch (throw-test) 'result) → true
result → "interrupted"
(catch (throw-text)) → "interrupted"
(catch (begin
…
(if (foo X) (throw X) Y)
…
))
throw-error
syntax: (throw-error 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
time
syntax: (time exp [int-count)
(time (myprog x y z)) → 450.340
(time (myprog x y z) 10) → 4420.021
time-of-day
syntax: (time-of-day)
timer
syntax: (timer sym | func-event-handler num-seconds [int-option])
syntax: (timer sym | func-event-handler)
syntax: (timer)
(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
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
(read-buffer socket buffer 1024)
(set 'done true)))
)
(if timeout
(println "timeout")
(println buffer))
(exit)
title-case utf8
syntax: (title-case str [bool])
(title-case "hello") → "Hello"
(title-case "hELLO" true) → "Hello"
(title-case "hELLO") → "HELLO"
trace
syntax: (trace [bool])
[-> 2] s|tep n|ext c|ont q|uit >
;; 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
trace-highlight
syntax: (trace-highlight str-pre str-post [str-header str-footer])
;; active expressions are enclosed in >> and <<
(trace-highlight ">>" "<<")
;; 'bright' color on a VT100 or similar terminal window
(trace-highlight "\027[1m" "\027[0m")
transpose
syntax: (transpose matrix)
(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))
(transpose '((a b) (c d) (e f))) → ((a c e) (b d f))
(set 'A '((1 2 3) (4 5) (7 8 9)))
(transpose A) → ((1 4 7) (2 5 8) (3 nil 9))
(set 'A '((1 2 3) X (7 8 9)))
(transpose A) → ((1 X 7) (2 X 8) (3 X 9))
trim utf8
syntax: (trim str [str-char])
syntax: (trim str str-left-char str-right-char)
(trim " hello ") → "hello"
(trim "----hello-----" "-") → "hello"
(trim "00012340" "0" "") → "12340"
(trim "1234000" "" "0") → "1234"
(trim "----hello=====" "-" "=") → "hello"
true?
syntax: (true? exp)
(map true? '(x 1 "hi" (a b c) nil ()))
→ (true true true true nil nil)
(true? nil) → nil
(true? '()) → nil
unicode
syntax: (unicode str-utf8)
(unicode "new")
→ "n\000\000\000e\000\000\000w\000\000\000\000\000\000\000"
(utf8 (unicode "new")) → "new"
unify
syntax: (unify exp-1 exp-2 [list-env])
(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
;; some examples taken from http://en.wikipedia.org/wiki/Unification
(unify '(f X) '(f 123)) → ((X 123))
(unify '(A B) '(X A) '((X 123)))
→ ((X 123) (A 123) (B 123))
Use unify with expand
(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)
(bind (unify '(f (g A) A) '(f B xyz)))
A → xyz
B → (g xyz)
Use unify with bind for de-structuring
(set 'struct '((one "two") 3 (four (x y z))))
(set 'pattern '((A B) C (D E)))
(bind (unify pattern struct))
A → one
B → "two"
C → 3
D → four
E → (x y z)
Model propositional logic with unify
; 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)
;; 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 term)
(or (if (find term facts) true) (catch (prove-rule term))))
(define (prove-rule term)
(dolist (r rules)
(if (list? (set 'e (unify term (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
unique
syntax: (unique list)
(unique '(2 3 4 4 6 7 8 7)) → (2 3 4 6 7 8)
unless
syntax: (unless exp-condition body)
(unless (starts-with (read-line) "quit")
(process (current-line))
...
(finish)
)
unpack
syntax: (unpack str-format str-addr-packed)
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
>
switches to big endian byte order
<
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))
;; on a little endian system (e.g., Intel CPUs)
(set 'buff (pack "d" 1)) → "\001\000"
(unpack "d" buff) → (1)
(unpack ">d" buff) → (256)
(set 's (pack "s3" "ABC"))
(unpack "c c c" s) → (65 66 67)
until
syntax: (until exp-condition [body])
(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")
upper-case utf8
syntax: (upper-case str)
(upper-case "hello world") → "HELLO WORLD"
utf8
syntax: (utf8 str-unicode)
(unicode "new")
→ "n\000\000\000e\000\000\000w\000\000\000\000\000\000\000"
(utf8 (unicode "new")) → "new"
(if utf8 (do-utf8-version-of-code) (do-ascii-version-of-code))
utf8len
syntax: (utf8len str)
(utf8-len "我能吞下玻璃而不伤身体。") → 12
(length "我能吞下玻璃而不伤身体。") → 36
uuid
syntax: (uuid [str-node])
;; 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"
wait-pid
syntax: (wait-pid int-pid [int-options | nil])
(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))
when
syntax: (when exp-condition body)
(when (read-line)
(set 'result (analyze (current-line)))
(report result)
(finish)
)
while
syntax: (while exp-condition body)
(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")
write-buffer !
syntax: (write-buffer int-file str-buffer [int-size])
syntax: (write-buffer str-device str-buffer [int-size])
(set 'handle (open "myfile.ext" "write"))
(write-buffer handle data 100)
(write-buffer handle "a quick message\n")
;; fast in-place string appending
(set 'str "")
(dotimes (x 5) (write-buffer str "hello"))
str → "HelloHelloHelloHelloHello")
;; much slower method of string concatenation
(dotimes (x 5) (set 'str (append str "hello")))
write-char
syntax: (write-char int-file int-byte1 [int-byte2 ... ])
(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-file in-file))
(write-char out-file chr))
(close in-file)
(close out-file)
"finished")
write-file
syntax: (write-file str-file-name str-buffer)
(write-file "myfile.enc"
(encrypt (read-file "/home/lisp/myFile") "secret"))
(write-file "http://asite.com/message.txt" "This is a message" )
write-line !
syntax: (write-line [int-file [str]])
syntax: (write-line [str-device [str]])
(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))
;; using a string device:
(set 'str "")
(dotimes (x 4) (write-line str "hello"))
str → "hello\r\nhello\r\nhello\r\nhello\r\n" ; on Win32
str → "hello\nhello\nhello\nhello\n" ; on Linux/Unix
xfer-event
syntax: (xfer-event sym | func)
(xfer-event (fn (n) (println "->" n)))
(length (get-url "http://yahoo.com"))
->3779
->5219
->6659
->8099
->9490
9490
(define (report n) (println "->" n))
(xfer-event 'report)
xml-error
syntax: (xml-error)
(xml-parse "<atag>hello</atag><fin") → nil
(xml-error) → ("expected closing tag: >" 18)
xml-parse
syntax: (xml-parse string-xml [int-options [sym-context [func-callback]]])
(set 'xml
"<person name='John Doe' tel='555-1212'>nice guy</person>")
(xml-parse xml)
→ (("ELEMENT" "person"
(("name" "John Doe")
("tel" "555-1212"))
(("TEXT" "nice guy"))))
Modifying the translation process.
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
XML source:
<?xml version="1.0" ?>
<DATABASE name="example.xml">
<!--This is a database of fruits-->
<FRUIT>
<NAME>apple</NAME>
<COLOR>red</COLOR>
<PRICE>0.80</PRICE>
</FRUIT>
<FRUIT>
<NAME>orange</NAME>
<COLOR>orange</COLOR>
<PRICE>1.00</PRICE>
</FRUIT>
<FRUIT>
<NAME>banana</NAME>
<COLOR>yellow</COLOR>
<PRICE>0.60</PRICE>
</FRUIT>
</DATABASE>
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"))))
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"))))))))
Suppressing XML type tags with 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"))))
(xml-type-tags nil nil nil nil)
(xml-parse "<msg>Hello World</msg>" (+ 1 2 4 8 16) 'CTX)
→ ((CTX:msg "Hello World"))
Parsing into SXML (S-expressions XML) format:
(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"))))
Parsing into a specified context
(xml-type-tags nil nil nil nil)
(xml-parse (read-file "example.xml") (+ 1 2 4 8 16) 'CTX)
→((CTX:DATABASE (@ (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"))))
Using a call back function
;; 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)
parsed expression:(NAME "apple"), source:<NAME>apple</NAME>
parsed expression:(COLOR "red"), source:<COLOR>red</COLOR>
parsed expression:(PRICE "0.80"), source:<PRICE>0.80</PRICE>
parsed expression:(NAME "orange"), source:<NAME>orange</NAME>
parsed expression:(COLOR "orange"), source:<COLOR>orange</COLOR>
parsed expression:(PRICE "1.00"), source:<PRICE>1.00</PRICE>
parsed expression:(NAME "banana"), source:<NAME>banana</NAME>
parsed expression:(COLOR "yellow"), source:<COLOR>yellow</COLOR>
parsed expression:(PRICE "0.60"), source:<PRICE>0.60</PRICE>
xml-type-tags
syntax: (xml-type-tags [exp-text-tag exp-cdata-tag exp-comment-tag exp-element-tags])
(xml-type-tags) → ("TEXT" "CDATA" "COMMENT" "ELEMENT")
(xml-type-tags nil 'cdata '!-- nil)
zero?
syntax: (zero? exp)
(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)
newLISP APPENDIX
Error codes
description no not enough memory 1 environment stack overflow 2 call stack overflow 3 problem accessing file 4 not an expression 5 missing parenthesis 6 string token too long 7 missing argument 8 number or string expected 9 value expected 10 string expected 11 symbol expected 12 context expected 13 symbol or context expected 14 list expected 15 list or array expected 16 list or symbol expected 17 list or string expected 18 list or number expected 19 array expected 20 array, list or string expected 21 lambda expected 22 lambda-macro expected 23 invalid function 24 invalid lambda expression 25 invalid macro expression 26 invalid let parameter list 27 problem saving file 28 division by zero 29 matrix expected 30 wrong dimensions 31 matrix is singular 32 syntax in regular expression 33 throw without catch 34 problem loading library 35 import function not found 36 symbol is protected 37 error number too high 38 regular expression 39 missing end of text [/text] 40 mismatch in number of arguments 41 problem in format string 42 data type and format don't match 43 invalid parameter 44 invalid parameter: 0.0 45 invalid parameter: NaN 46 illegal parameter type 47 symbol not in MAIN context 48 symbol not in current context 49 target cannot be MAIN 50 list index out of bounds 51 array index out of bounds 52 string index out of bounds 53 nesting level too deep 54 invalid syntax 55 user error 56 user reset - 57 received SIGINT - 58 function is not reentrant 59 local symbol is protected 60 no symbol reference found 61 list is empty 62 I/O error 63 working directory not found 64 invalid PID 65
TCP/IP and UDP Error Codes
description no No error 0 Cannot open socket 1 Host name not known 2 Not a valid service 3 Connection failed 4 Accept failed 5 Connection closed 6 Connection broken 7 Socket send() failed 8 Socket recv() failed 9 Cannot bind socket 10 Too many sockets in net-select 11 Listen failed 12 Badly formed IP 13 Select failed 14 Peek failed 15 Not a valid socket 16 Operation timed out 17 HTTP bad formed URL 18 HTTP file operation failed 19 HTTP transfer failed 20
System Symbols and Constants
Variables changed by the system
name purpose protected reentrant $0 - $15 Used primarily in regular expressions. $0
is also used to record the last state or count of execution of a function.
no no $args Contains the list parameters not bound to local
variables. Normally the function args is used to retrieve
the contents of this variable. yes yes $idx The function dolist
maintains this as a list index or offset. The functions
map, series,
while, until,
do-while and do-until
maintain this variable as an iteration counter starting with 0 (zero) for
the first iteration.
yes yes $it The anaphoric $it refers to the
result inside an executing expression, i.e. in self referential assignments. In
some functions $0 servers the same purpose and both carry the same value.
$it is only available inside the function expression setting it, and
is set to nil on exit of that expression. The following functions use it:
hashes, find-all,
replace, set-ref,
set-ref-all and setf setq.
yes no $main-args Contains the list of command line arguments
passed by the OS to newLISP when it was started. Normally the function
main-args is used to retrieve the contents.
yes n/a
Predefined variables and functions.
name purpose protected reentrant Class Is the predefined general FOOP class constructor
which can be used together with new to create new FOOP classes, e.g:
(new Class 'Rectangle) would create a class and object constructor for
a user class Rectangle. See the
FOOP classes and constructors chapter in the users
manual for details.
no n/a ostype Contains a string identifying the OS-Platform
for which the running newLISP version has been compiled. See the reference section for
details
yes n/a Tree Is a predefined namespace to serve as a hash like
dictionary. Instead of writing (define Foo:Foo) to create a Foo
dictionary, the expression (new Tree 'Foo) can be used as well. See the chapter
Hash functions and dictionaries foe details.
no n/a module Is a predefined function to load modules.
Instead of using load together with the NEWLISPDIR environment
variable, the module function loads automatically from
$NEWLISPDIR/modules/.
no n/a
GNU Free Documentation License
0. PREAMBLE
1. APPLICABILITY AND DEFINITIONS
2. VERBATIM COPYING
3. COPYING IN QUANTITY
4. MODIFICATIONS
5. COMBINING DOCUMENTS
6. COLLECTIONS OF DOCUMENTS
7. AGGREGATION WITH INDEPENDENT WORKS
8. TRANSLATION
9. TERMINATION
10. FUTURE REVISIONS OF THIS LICENSE
GNU GENERAL PUBLIC LICENSE
Preamble
TERMS AND CONDITIONS
0. Definitions.
1. Source Code.
2. Basic Permissions.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
4. Conveying Verbatim Copies.
5. Conveying Modified Source Versions.
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
6. Conveying Non-Source Forms.
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
7. Additional Terms.
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
8. Termination.
9. Acceptance Not Required for Having Copies.
10. Automatic Licensing of Downstream Recipients.
11. Patents.
12. No Surrender of Others' Freedom.
13. Use with the GNU Affero General Public License.
14. Revised Versions of this License.
15. Disclaimer of Warranty.
16. Limitation of Liability.
17. Interpretation of Sections 15 and 16.
END OF TERMS AND CONDITIONS