The Lisp language is characterized by functions, macros, special forms, and lexical forms. These functions, macros, special forms, and lexical forms contain everything from basic control flow operators to language keywords. All of the basic language elements of AIS Lisp are contained in this chapter.
All Lisp macros, special forms, and lexical forms are understood only by the Lisp compiler.
Lisp, heavily influenced by the functional programming paradigm, is a language composed entirely of function calls. Each function call is inclosed in parentheses (function ...agruments...). It is this focus on the parenthetically enclosed function call which gives Lisp its multiplicity of parens.
The best pocket introduction to the essential elements of AIS Lisp is the following table of Lisp essential flow of control language elements.
(ref ... ) | Access statement |
---|---|
(setq ... ) | Assignment statement |
(if ... then ... else ... ) | Conditional statement |
(loop ... ) | Iteration statement |
(while ... ) | Iteration statement |
(cond ... case ... case ... ) | Conditional case statement |
(goto ... ) | Transfer of control statement |
(defclass ... ) | Class (user defined) declaration statement |
(defclone ... ) | Clone (user defined) declaration statement |
(lambda ... ) | Lambda(function) building statement |
(defun ... ) | Lambda(function) declaration statement |
(defchild ... ) | Lambda(function) declaration statement |
(defriend ... ) | Lambda(function) declaration statement |
(deforphan ... ) | Lambda(function) declaration statement |
(defmethod ... ) | Lambda(method) declaration statement |
(defvm ... ) | Lambda(virtual machine) declaration statement |
regs:(...) | Lambda(register) declaration statement |
vars:(...) | Lambda(variable) declaration statement |
svars:(...) | Object(variable) declaration statement |
pvars:(...) | Lambda(variable) declaration statement |
cvars:(...) | Lambda(variable) declaration statement |
The lambda special form creates and returns an instance of an Lambda object. Each Lambda is an executable software object which is storable as a fundamental unit of data in an AIS repository and can be mobile between copies of Analytic Information Server across the Internet. AIS Lisp provides several ways to declare an Lambda. The lambda function supports the creation of unbound-unnamed Lambdas. There are multiple ways of declaring bound-named Lambdas as follows.
defun | Declaration of globally bound and named Lambda. May be declared inside the body of another Lambda declaration. If declared inside another parent Lambda declaration, this Lambda automatically becomes the child of its parent Lambda. The child Lambda will be bound to its name in the Pv persistent storage Structure of the parent Lambda. The child's Pv and Cv persistent storage Structures will be identical (the exact same objects) as its parent Lambda. |
---|---|
defchild | Declaration of a child Lambda to a globally bound and named parent Lambda. Must be declared outside the body of the parent Lambda declaration. The parent Lambda must already have declared a pvars variable of the same name as declared in this child Lambda. The child Lambda will be bound to its name in the Pv persistent storage Structure of the parent Lambda. The child's Pv and Cv persistent storage Structures will be identical (the exact same objects) as its parent Lambda. |
defriend | Declaration of a friend Lambda to a globally bound and named parent Lambda. Must be declared outside the body of the parent Lambda declaration. The parent Lambda must already have declared a pvars variable of the same name as declared in this friend Lambda. The friend Lambda will be bound to its name in the Pv persistent storage Structure of the parent Lambda. The parent's Pv persistent storage Structure will be unknown to the friend Lambda. The friend's Pv persistent storage Structure will be identical to the Cv persistent storage Structure of its parent Lambda. The friend's Cv persistent storage Structure will be unknown to the parent Lambda. |
deforphan | Declaration of an orphan Lambda to a globally bound and named parent Lambda. Must be declared outside the body of the parent Lambda declaration. The parent Lambda must already have declared a pvars variable of the same name as declared in this orphan Lambda. The orphan Lambda will be bound to its name in the Pv persistent storage Structure of the parent Lambda. The parent's Pv and Cv persistent storage Structures will be unknown to the orphan Lambda. The orphan's Pv and Cv persistent storage Structures will be separate and distinct from those of its parent Lambda. |
defmethod | Declaration of a bound and named method Lambda to an owner data type (Object Oriented Programming Paradigm). The owner data type must already have been declared. The method Lambda will be bound to its name in the methods Dictionary associated with its owner data type. |
defmacro | Declaration of globally bound and named Lisp macro Lambda. Will automatically be recognized by the morph and compile functions during compilation. |
defvm | Declaration of a globally bound and named Lambda virtual machine. Can be assigned as the virtual machine of any Lambda, and will be responsible for controling the Lambda's behavior. |
Each Lambda declaration contains the declaration of variables (including argument variables), the declaration of Lambda interfaces, and any Lambda event keywords.
AIS Lisp supports the declaration of local variables. There are five categories of local variables for each Lambda.
The vars, pvars, and cvars local variable allocations may include initialization specifications along with their declarations. The regs local variable allocations may include data type specifications along with their declarations.
(defun foo(n) ;; Variable n is an argument variable.
vars:(x Number:y) ;; y and y are temporary variables.
pvars:((a 20)) ;; Variable a is a persistent variable initialized to type Word with a value of 20.
cvars:(b) ;; Variable b is a persistent variable uninitialized defaulted to Word type.
regs:(Integer:myReg) ;; Variable myReg is a microchip register variable typed as Integer.
true)
An Analytic Information Server Lambda may be defined, with a definite list (fixed) or an indefinite list of arguments. Ellipses (...) at the end of the argument list indicate the function has indefinite arguments. At run time, the Lambda's actual arguments are bound to the specified formal definite arguments respectively. An error is generated if there are too few arguments in the definite argument list. If the number of actual arguments exceeds the number of definite arguments, and the function has been defined as having indefinite arguments, the excess arguments can only be accessed via the argCount and argFetch functions at run time. When called, the Lambda receives its arguments on the stack. The arguments are received and bound to the proper arguments.
AIS Lisp supports the declaration of Lambda interfacesas well as the declaration of event keywords. The keyword faces: declares the interfaces feature Structure of the Lambda. The features are specified as list constants, faces:((name Alice)), the listed feature is initialized to the value specified.
The keyword doomed: declares that the Lambda is to be evaluated, by the garbage collector, when the Lambda is doomed. The Lambda?s EvalWhenDoomed element is set to true. The Lambda is always evaluated, by the garbage collector, with no arguments.
(defun foo() ;; Lambda is declared with no argument variables.
faces:((English true) (French false)) ;; Declaration of English and French interface protocols.
Doomed: ;; This Lambda will be executed just before it is destroyed.
true)
Type: Special Form
Syntax examples
(defun name(arguments) variables interfaces body)
(defchild parent:name(arguments) variables interfaces body)
(defriend parent:name(arguments) variables interfaces body)
(deforphan parent:name(arguments) variables interfaces body)
(defmethod typeSymbol:name(arguments) variables interfaces body)
(defmacro name(arguments) variables interfaces body)
(defvm name(arguments) variables interfaces body)
Arguments
name | The name to which the Lambda is to be bound. |
---|---|
arguments | The list of argument variable declarations. |
variable declarations | The list of local variable declarations. |
body | The Lisp expressions which make up the execution instructions for the Lambda. |
Returns | An executable Lambda object. |
parent | The name of the parent Lambda into which the Lambda is to be bound. |
---|---|
name | The name to which the Lambda is to be bound. |
arguments | The list of argument variable declarations. |
variable declarations | The list of local variable declarations. |
body | The Lisp expressions which make up the execution instructions for the Lambda. |
Returns | An executable Lambda object. |
typeSymbol | The name of the owner data type into whose method list the Lambda is to be bound. |
---|---|
name | The name to which the Lambda is to be bound. |
arguments | The list of argument variable declarations. |
variable declarations | The list of local variable declarations. |
body | The Lisp expressions which make up the execution instructions for the Lambda. |
Returns | An executable Lambda object. |
When To Use
Use the lambda special form and other Lambda declaration forms when an Lambda is to be created for use in your application program.
Example 1
These examples demonstrate some simple properties of the lambda special form. Here the lambda returns a simple Lambda.
(lambda(X) (+ X X))Returns #<Lambda 392>
Here a simple Lambda is declared bound to a global variable.
(defun foo(X) (+ X X))Returns #<Lambda 312>
Here the Lambda is invoked with the argument 4.
(foo 4)Returns 8
Here the Lambda is immediately invoked with the argument 4.
((lambda(X) (+ X X)) 4)Returns 8
Example 2
Here a slightly more complex Lambda which is declared bound to a global variable.
(defun sumNums(X ...)
vars:(Z)
(setq Z X)
(loop for i from 1 to (1+ (argCount)) do
(setq Z (+ Z (argFetch i)))))
Here the Lambda is invoked with the arguments 4 5 and 71.
(sumNums 4 5 71) Returns 80
Example 3
This example defines an Lambda named foo with a child Lambda named sum.
(defun foo(x)
pvars:(y)
(defun sum(x) (+ x y))
(setq y x))
Here we invoke the parent Lambda foo.
(foo 9) Returns 9
Here we invoke the child Lambda sum.
(foo.sum 2) Returns 11
Notes & Hints
The scope of variables in nested Lambdas depends upon the following Lisp compilation rules: Nested Lambdas do not share either their argument or their temporary variables. The argument and the temporary variables are always limited in scope to the immediate Lambda object. A nested Lambda both shares and extends the persistent variables (pvars) of its parents. When a variable reference is encountered, the Lisp compiler first searches the local Lambda's arguments for a match, then the searches the local Lambda's temporary variables (vars) for a match, finally searches the Lambda's extended persistent variables (pvars) and then the (cvars) for a match. A referenced variable, without a match, always refers to the global value of the variable.
All of the built-in AIS functions and objects are available to Lisp programs. Functions such as append, left, avg, sqrt, etc. are all available to Lisp programs. Objects such as Vector, String, Structure, Repository, etc. are all available to Lisp programs. Also available to all Lisp programs is a rich library of native data types. In order to benefit from the full power of the AIS environment, the Lisp programmer should become familiar with the many libraries of functions, macros, and object types available.
The following reference guides may be of some help.
The ref function is the fundamental access statement of Lisp. The ref function supports both direct referencing and indexed referencing of elements within an object. The ref function must always be passed one variable argument; and, can be passed one, two, or three, index arguments. In each case The ref function returns the result of referencing the variable with one, two, or three index arguments.
Type: function
Syntax examples
(ref variable)
(ref variable index1)
(ref variable index1 index2)
(ref variable index1 index2 index3)
Arguments
variable | The target of the reference attempt (the ultimate behavior of ref is dependent upon the data type of the target). |
---|---|
index1 | (Optional) First index argument. |
index2 | (Optional) Second index argument. |
index3 | (Optional) Third index argument. |
When To Use
Use the ref function when indexed referencing of an AIS object is essential to the correct operation of your program.
Example 1
Here are just a few sample object retrievals using the ref function.
(setq x (new Vector:3 45 -6 78)) ;; Set the newly created vector object into the variable x.
(ref x 2) Returns 78
(ref x 0) Returns 45
(setq x (new Structure: A: 45 B: -6 C: 78)) ;; Set the Structure object into the variable x.
(ref x C:) Returns 78
(ref x A:) Returns 45
(ref x 2 1) Returns 78
(setq x "Hello World") ;; Set the string "Hello World" into the variable x.
(ref x 1) Returns #\e
(ref x 6) Returns #\W
Notes & Hints
Refer to the appropriate object data type reference guide to determine the effect of the ref function on that specific type or even what types of indices the ref function can take. For String objects refer to the String Object Reference Guide, For Vector objects refer to the Vector Object Reference Guide, For Dictionary objects refer to the Dictionary Object Reference Guide, etc.
Overview
The setq special form is the fundamental assignment statement of Lisp. The setq special form supports both direct assignment and indexed assignment of elements within an object. The setq special form must always be passed one receiver argument, and one new value argument; and, can be passed one, two, or three, index arguments. In each case The setq special form returns the result of assigning the new value argument to the receiver argument with one, two, or three index arguments.
Type: special form
Syntax examples
(setq receiver newValue)
(setq (ref receiver index1) newValue)
(setq (ref receiver index1 index2) newValue)
(setq (ref receiver index1 index2 index3) newValue)
(set receiver index1 newValue)
(set receiver index1 index2 newValue)
(set receiver index1 index2 index3 newValue)
Arguments
receiver | The target of the assignment attempt (the ultimate behavior of setq is dependent upon the data type of the receiver). |
---|---|
index1 | (Optional) First index argument. |
index2 | (Optional) Second index argument. |
index3 | (Optional) Third index argument. |
newValue | The new value to be assigned to the receiver. |
When To Use
Use the setq special form when indexed assignment of an AIS object is essential to the correct operation of your program.
Example 1
Here are just a few sample object assignments using the setq special form.
(setq x (new Vector:3 45 -6 78)) ;; Set the newly created vector object into the variable x.
(set x 2 20) Returns #(45 -6 20)
(setq (ref x 0) -65) Returns #(-65 -6 20)
(setq x (new Structure: A: 45 B: -6 C: 78)) ;; Set the Structure object into the variable x.
(setq (ref x C:) 22) Returns #{A 45 B -6 C 22}
(set x A: 16) Returns #{A 16 B -6 C 22}
(set x 1 0 X:) Returns #{A 16 X -6 C 22}
(setq x "Hello World") ;; Set the string "Hello World" into the variable x.
(set x 1 #\E) Returns "HEllo World"
(setq (ref x 6) #\w) Returns "HEllo world"
Notes & Hints
Refer to the appropriate object data type reference guide to determine the effect of the setq special form on that specific type or even what types of indices the setq special form can take. For String objects refer to the String Object Reference Guide, For Vector objects refer to the Vector Object Reference Guide, For Dictionary objects refer to the Dictionary Object Reference Guide, etc.
The Bracket Operator [ ] supports both setting and referencing indexed elements within an object in AIS Lisp. The bracket operator, used for reference, is the equivalent of the ref built-in function. The bracket operator, used for assignment, is the equivalent of the setq special form.
Type: Lexical
Syntax examples
variable[index]
(setq variable[index] newValue)
Equivalence
x[5] | is identical to | (ref x 5) |
---|---|---|
(setq x[2] "Hello") | is identical to | (setq (ref x 0) "Hello") |
When To Use
Use the bracket operator when writing out the full equivalent setq or ref expressions would be too cumbersome or would make the Lisp program less readable.
Example 1
Here are just a few sample object retrievals and settings using the bracket operator.
(setq x (new Vector:3 45 -6 78)) ;; Set the newly created vector object into the variable x.
x[2] Returns 78
x[0] Returns 45
(setq x[0] 26) Returns #(26 -6 78)
(setq x "Hello World") ;; Set the string "Hello World" into the variable x.
x[1] Returns #\e
x[6] Returns #\W
(setq x[0] #\h) Returns "hello World"
Notes & Hints
Refer to the appropriate object data type reference guide to determine the effect of the bracket operator on that specific type or even what types of indices the bracket operator can take. For String objects refer to the String Object Reference Guide, For Vector objects refer to the Vector Object Reference Guide, For Dictionary objects refer to the Dictionary Object Reference Guide, etc.
The Dot Operator . supports both setting and referencing indexed elements within an object in AIS Lisp. The dot operator, used for reference, is the equivalent of the ref built-in function. The dot operator, used for assignment, is the equivalent of the setq special form.
Type: Lexical
Syntax examples
variable.indexSymbol
(setq variable.indexSymbol newValue)
Equivalence
x.A | is identical to | (ref x A:) |
---|---|---|
(setq x.C "Hello") | is identical to | (setq (ref x C:) "Hello") |
When To Use
Use the dot operator when writing out the full equivalent setq or ref expressions would be too cumbersome or would make the Lisp program less readable.
Example 1
Here are just a few sample object retrievals and settings using the dot operator.
(setq x (new Structure: A: 45 B: -6 C: 78)) ;; Set the newly created Structure object into the variable x.
x.C Returns 78
x.A Returns 45
(setq x.A 26) Returns #{A 26 B -6 C 78}
(setq x.B 0) Returns #{A 26 B 0 C 78}
Notes & Hints
Refer to the appropriate object data type reference guide to determine the effect of the dot operator on that specific type or even what types of indices the bracket operator can take. For String objects refer to the String Object Reference Guide, For Vector objects refer to the Vector Object Reference Guide, For Dictionary objects refer to the Dictionary Object Reference Guide, etc.
The offset function returns the byte offset, from the start of the specified basis object basis, when computed using the specified constant indices index1, index2, index3. The offset function operates on a number of object types and can accept from one to three indices depending upon the type of basis object. The offset function is an important tool in supporting direct offset addressing using AIS Lisp registers addressing.
The offset function is called automatically, by the compiler, when an AIS Lisp register variable is indexed by a constant offset expression, using the bracket operator such as: register[:integer:], register[basis(name)], register[basis(index1)], register[basis(index1,index2)], or register[basis(index1,index2,index3)]. AIS Lisp treats each register offset expression as a single compound variable name. Therefore, there can be absolutely NO whitespace between any of the parts of the register offset expression. It should also be noted that AIS Lisp only supports register offsets of up to 32,767 bytes.
vars:((employee #{decl| (Name "John Doe") (Number:Salary 23450.00)}))
regs:(NumPointer:ptr)
(setq ptr employee) ;; Loads register ptr with the address of the employee Structure.
(+= ptr[employee(Salary)] 200.0) ;; Adds 200 to Salary, using direct offset addressing from the ptr register.
Type: Function
Syntax examples
(offset basis index1) (offset basis index1 index2) (offset basis index1 index2 index3) register[:integer:] register[basis(name)] register[basis(index1)] register[basis(index1,index2)] register[basis(index1,index2,index3)]
Arguments
basis | The specified basis object to be referenced via direct offset addressing. |
---|---|
name | (Mandatory) The field name from which to compute the direct offset address. |
Returns | The direct offset address, from the start of the basis object, for the indices specified. |
basis | The specified basis object to be referenced via direct offset addressing. |
---|---|
index1 | (Mandatory) The first numeric index from which to compute the direct offset address. |
index2 | (Optional) The second numeric index from which to compute the direct offset address. |
index3 | (Optional) The third numeric index from which to compute the direct offset address. |
Returns | The direct offset address, from the start of the basis object, for the indices specified. |
When To Use
The offset function is an important tool in supporting direct offset addressing using AIS Lisp registers addressing.
The offset function operates on a number of object types and can accept a number of different constant indices, as follows:
Example 1
Here follows a simple example of AIS Lisp offset addressing in action.
vars:((complex #{Real 2134.2 Imagine 23450.00}))
regs:(NumPointer:ptr)
(setq ptr complex) ;; Loads register ptr with the address of the complex Structure.
(+= ptr[complex(Real)] 200.0) ;; Adds 200 to the real part of complex.
(+= ptr[complex(Imagine)] 1540.0) ;; Adds 200 to the imaginary part of complex.
Example 2
Here follows a simple example of AIS Lisp offset addressing for Number Matrices.
vars:((gauss #(NumMat[2 2 2]| 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0)))
regs:(NumPointer:ptr)
(setq ptr gauss) ;; Loads register ptr with the address of the gauss Matrix.
(setq ptr[gauss(1 0 1)] .45) ;; Moves .45 into the [1 0 1]th element of the matrix.
Notes & Hints
The offset function is an important tool for supporting direct register offset addressing in AIS Lisp.
The Circumflex Operator ^ preceding a symbol references a global variable value even in contexts where there are local variable naming conflicts. The AIS Lisp ^ operator uses the getGlobalValue function to return the global value of the specified symbol argument. The circumflex operator ^name is the equivalent of the (getGlobalValue name:) function. Also the circumflex operator ^name has a similar effect as the |Gv:name| symbolic form.
Type: Lexical
Syntax examples
^variable
|Gv:variable|
Equivalence
^name | is identical to | (getGlobalValue name:) |
---|---|---|
^name | has a similar effect as | |Gv:name| |
When To Use
Use the circumflex operator when writing out the full equivalent (getGlobalValue name:) expression would be too cumbersome or would make the Lisp program less readable, or use the |Gv:name| symbolic form to achieve the same effect without a function call.
Example
Here are just a few sample globals retrievals using the circumflex operator.
(setq x (new Structure: A: 45 B: -6 C: 78)) ;; Set the Structure object into the global variable x.
((lambda(x) ^x) 2) Returns #{A 45 B -6 C 78}
((lambda(x) |Gv:x|) 2) Returns #{A 45 B -6 C 78}
((lambda(x) x) 2) Returns 2
Notes & Hints
Use the circumflex operator only as shorthand notation for the (getGlobalValue name) function, or use the |Gv:name| symbolic form to achieve the same effect without a function call.
The Quote Operator ' preceding a list or symbol converts the list or symbol into a list or symbol constant. The AIS Lisp ' is the short hand equivalent of the quote special form.
Type: Lexical
Syntax examples
'symbol
'(...list...)
Equivalence
'thing | is identical to | (quote thing) |
---|
When To Use
Use the quote operator when writing out the full equivalent quote expression would be too cumbersome or would make the Lisp program less readable.
Example 1
Here are just a few examples of the quote operator in action.
(defun foo(x) (length x)) Returns #<Lambda 291>
(setq x (new Vector: 3 1 2 3)) Returns #(1 2 3)
x Returns #(1 2 3)
'x Returns x
(foo x) Returns 3
(foo 'x) Returns 1
'(foo x) Returns (foo x)
Notes & Hints
Use the quote operator only as shorthand notation for the quote special form.
The Colon Operator : suffixing a symbol always converts the symbol into a symbolic constant. Also symbols enclosed in vertical bars |I am a compound symbol|: can be converted into symbolic constants using the colon operator. The AIS Lisp name: is the short hand equivalent of the (quote name) special form.
Using the colon operator on a symbol at the head of a list can be used as short hand to send a message to a class instance. The AIS Lisp (msg: self) is the short hand equivalent of the (send msg: self) method invocation.
Type: Lexical
Syntax examples
name:
|I am a compound symbol|:
(msg: self)
Equivalence
name: | is identical to | (quote name) |
---|---|---|
(msg: self) | is identical to | (send msg: self) |
When To Use
Use the colon operator when writing out the full equivalent (quote name) or (send msg: self) expressions would be too cumbersome or would make the Lisp program less readable.
Example
Here are some examples of the colon operator in action.
(defclass foo() svars:(Number:x Vector:y) (defun new(self) (setq y (new Vector: 3 1 2 3))) true)
(defmethod foo:len(self) (length y))
(setq x (new foo))
(len: x) Returns 3
x: Returns x
(length x) Returns 2
(length x:) Returns 1
Notes & Hints
Use the colon operator as shorthand notation for the (quote name) special form, or use the colon operator as shorthand notation sending a message to a class instance.
The At Operator @ infixing a compound name, converts the compound name into a member macro invocation. The AIS Lisp parent@name is the short hand equivalent of the (refmacro parent name) special form. Using the @ Operator on a symbol at the head of a list can be used to invoke a member macro during compilation.
Type: Lexical
Syntax examples
(parent@name)
(parent.child@name)
(parent.child[2]@name)
Equivalence
parent@name | is identical to | (refmacro parent name) |
---|
When To Use
Use the @ operator when writing out the full equivalent (refmacro parent name) expression would be too cumbersome or would make the Lisp program less readable.
Example
Here is an example of the colon operator in action.
(defun foo(x) pvars:(v len) (setq v x))
(defmacro foo:len(self) (macroReplace self '(length %1)))
(setq x (new Vector: 3 1 2 3))
(foo@len x) Returns 3
The Math Operators + - * / support the basic arithmetic operations of add (+), subtract (-), multiply (*), and divide (/). Each operator is treated as a function call (as is everything else in Lisp). Each math operator must have one argument, and may have up to nineteen (19) optional additional arguments.
The add (+) operator returns to total of all its numeric arguments. The subtract (-) operator returns the negative of the first argument (if only one argument was passed), and the difference between the first argument and the total of all remaining arguments (if more than one argument was passed). The multiply (*) operator returns the product of all its numeric arguments. The divide (/) operator returns the inverse of the first argument (if only one argument was passed), and the quotient of the first argument and the product of all remaining arguments (if more than one argument was passed).
Type: Function
Syntax examples
(+ number ... )
(- number ... )
(* number ... )
(/ number ... )
Arguments
number | (Mandatory) the first number to be operated upon |
---|---|
number | (Optional) up to nineteen (19) additional numbers to be operated upon |
When To Use
Use the math operators when artithmetic computations are essential to the success of your program.
Example 1
Here are just a few sample arithmetic computations using the math operators.
(setq x (+ 10 20))Returns 30
(setq x (/ x 15))Returns 2
(setq x (- (* 15 x) 5 4 3 2 1))Returns 0
(setq x (* 5 4 3 2 1))Returns 120
Notes & Hints
Use the math operators to return the results of arithmetic calculations.
The Math Operators + - * / support the basic arithmetic operations of add (+), subtract (-), multiply (*), and divide (/). Each operator is treated as a function call (as is everything else in Lisp). Each math operator must have one argument, and may have up to nineteen (19) optional additional arguments.
The add (+) operator returns to total of all its numeric arguments. The subtract (-) operator returns the negative of the first argument (if only one argument was passed), and the difference between the first argument and the total of all remaining arguments (if more than one argument was passed). The multiply (*) operator returns the product of all its numeric arguments. The divide (/) operator returns the inverse of the first argument (if only one argument was passed), and the quotient of the first argument and the product of all remaining arguments (if more than one argument was passed).
Type: Function
Syntax examples
(+ number ... )
(- number ... )
(* number ... )
(/ number ... )
Arguments
number | (Mandatory) the first number to be operated upon |
---|---|
number | (Optional) up to nineteen (19) additional numbers to be operated upon |
When To Use
Use the math operators when artithmetic computations are essential to the success of your program.
Example 1
Here are just a few sample arithmetic computations using the math operators.
(setq x (+ 10 20))Returns 30
(setq x (/ x 15))Returns 2
(setq x (- (* 15 x) 5 4 3 2 1))Returns 0
(setq x (* 5 4 3 2 1))Returns 120
Notes & Hints
Use the math operators to return the results of arithmetic calculations.
The Math Assignors += -= *= /= support the basic arithmetic operations of add (+), subtract (-), multiply (*), and divide (/). Each operator is treated as a function call (as is everything else in Lisp). Each math assignor must have exactly two arguments. The first argument must be a variable which is the target assignor of the operation, and the second argument must be a numeric value which is the assignee.
The add (+=) assignor assigns the total of the target and the argument back into the target. The subtract (-=) assignor assigns the difference of the target and the argument back into the target. The multiply (*=) assignor assigns the product of the target and the argument back into the target. The divide (/=) assignor assigns the quotient of the target and the argument back into the target.
Type: Macro
Syntax examples
(+= variable number)
(-= variable number)
(*= variable number)
(/= variable number)
Arguments
variable | The target to be assigned with the final result. |
---|---|
number | The numeric argument to be added to, subtracted from, multiplied by, or divided into the target. |
When To Use
Use the math assignors when artithmetic computations are essential to the success of your program, and the long hand equivalent setq special forms would be to cumbersome or would make your program difficult to read.
Example 1
Here are just a few sample arithmetic computations using the math assignors.
(setq x (+ 10 20))Returns 30
(+= x 15)Returns 45
(-= x (+ 5 4 3 2 1))Returns 30
(*= x 2)Returns 60
(/= x 2)Returns 60
Notes & Hints
The math assignors are all equivalent to standard (setq ...) special forms. For instance, (+= n 20) is equivalent to (setq n (+ n 20))
The Math Incrementors ++ -- support the basic arithmetic operations of increment (++), and decrement (--). Each operator is treated as a function call (as is everything else in Lisp). Each math incrementor must have exactly one argument, a variable which is the target assignor of the moperation. The increment (++) incrementor assigns the total of the target and the number 1 back into the target. The decrement (--) incrementor assigns the difference of the target and the number 1 back into the target.
Type: Macro
Syntax examples
(++ variable)
(-- variable)
Arguments
variable | The target to be incremented or decremented. |
---|
When To Use
Use the math incrementors when artithmetic computations are essential to the success of your program, and the long hand equivalent setq special forms would be to cumbersome or would make your program difficult to read.
Example 1
Here are just a few sample arithmetic computations using the math incrementors.
(setq x (+ 10 20))Returns 30
(++ x)Returns 31
(-- x)Returns 30
Notes & Hints
The math incrementors are all equivalent to standard (setq ...) special forms. For instance, (++ n) is equivalent to (setq n (+ n 1))
The Relational Operators < <= = == <> >= > support the basic comparison operations of less than (<), less than or equal (<=), equal (=), isIdentical (==), not equal (<>), greater than or equal (>=), and greater than (>). Each comparison operator is treated as a function call (as is everything else in Lisp). Each comparison operator must have two arguments.
The less than (<) operator returns true if arg1 is less than arg2. The less than or equal (<=) operator returns true if arg1 is less than or equal to arg2. The equal (=) operator returns true if arg1 is equal to arg2. The isIdentical (==) operator returns true if arg1 is identical to arg2. The not equal (<>) operator returns true if arg1 is not equal to arg2. The greater than or equal (>=) operator returns true if arg1 is greater than or equal to arg2. The greater than (>) operator returns true if arg1 is greater than arg2.
Type: Function
Syntax examples
(< value1 value2)
(<= value1 value2)
(= value1 value2)
(== value1 value2)
(<> value1 value2)
(>= value1 value2)
(> value1 value2)
Arguments
value1 | The first value to be compared |
---|---|
value2 | The second value to be compared. |
When To Use
Use the relational operators when comparisons are essential to the success of your program.
Example 1
Here are just a few sample relational operations using the a range of values.
(setq x (+ 10 20))Returns 30
(< x 15)Returns true
(<= x -1)Returns false
(= x 30.0)Returns true
(= x "30")Returns false
(setq x "Hello World")Returns "Hello World"
(<> x "Hello World")Returns false
(= x[6] #\W)Returns true
(setq y #(#\H #\W #\O)Returns #(#\H #\W #\O)
(= x[6] y[1])Returns true
Notes & Hints
Use the relational operators to return the results of value comparisons.
The Comparison Operators LT LE EQ NE GE GT support the basic comparison operation (compare), as well as the basic comparison operations of less than (compareGT), less than or equal (compareGE), not equal (compareNE), equal (compareEQ), greater than or equal (compareGE), and greater than (compareGT). Each comparison operator is treated as a function call (as is everything else in Lisp). Each comparison operator must have two arguments.
The comparison operator (compare) returns -1 if arg1 is less then arg2, returns 0 if arg1 is equal to arg2, and returns 1 if arg1 is greater then arg2. The less than (compareLT) operator returns true if arg1 is less than arg2. The less than or equal (compareLE) operator returns true if arg1 is less than or equal to arg2. The not equal (compareNE) operator returns true if arg1 is not equal to arg2. The equal (compareEQ) operator returns true if arg1 is equal to arg2. The greater than or equal (compareGE) operator returns true if arg1 is greater than or equal to arg2. The greater than (compareGT) operator returns true if arg1 is greater than arg2.
The comparison operators may optionally be prefixed with a strong typing indicator, which causes the appropriate memory to memory strongly typed comparison operators to be invoked. The values of the optional strong typing indicators t are as follows.
Type: Function
Syntax examples
(compare value1 value2)
(compareCC value1 value2)
(tcompareCC value1 value2)
Arguments
value1 | The first value to be compared |
---|---|
value2 | The second value to be compared. |
When To Use
Use the comparison operators when comparisons are essential to the success of your program.
Example 1
Here are just a few sample comparison operations using the a range of values.
(setq x (+ 10 20))Returns 30
(icompareLT x 15)Returns true
(compareLE x -1)Returns false
(ncompareEQ x 30.0)Returns true
(compareEQ x "30")Returns false
(setq x "Hello World")Returns "Hello World"
(compareNE x "Hello World")Returns false
(ccompareEQ x[6] #\W)Returns true
(setq y #(#\H #\W #\O)Returns #(#\H #\W #\O)
(compareEQ x[6] y[1])Returns true
Notes & Hints
Use the comparison operators to return the results of value comparisons.
Overview
The lambda special form creates a new Lambda object and returns it to the caller.
Type: Special From
Syntax: (lambda(args...) faces:(var...) svars:(var...) vars:(var...) pvars:(var...) cvars:(var...) regs:(var...) exp...)
The lambda special form creates a new executable Lambda object. When called, the Lambda extends its environment to include the specified argument variables {arg}, the arguments are received and bound to the proper variables {arg}, the expressions {exp} are evaluated from left to right, and the value of the final expression is returned. The new Lambda object may be either a root Lambda or it will be a child Lambda of any Lambda within which it is declared. Child lambda Lambdas are always registered in the pvars:() of their parent Lambda. The new Lambda may be called directly when the arguments specified in its argument list.
Operating alone, Lambdas are of limited capability and value. Operating in communities, Lambdas have immense value and capabilities. AIS Lisp allows individual Lambdas to be formed together into large Lambda communities of complex architecture. Lambdas can work together as classes, methods, children, friends, orphans, macros, all in increasing layers of complexity. A community of Lambdas brought together to accomplish a specific set of tasks AND which can be used as a mobile TOOL is called an Lambda library. The precise qualities which cause an Lambda community to evolve from a simple hodpodge into a useful library are qualitative. However useful Lambda libraries come in two distinctive flavors: Lambda oriented Libraries (AOP), and Object Oriented Libraries (OOP). Lambda oriented library tools present their users with a functional interface wherein data is passed to functional Lambda-objects which causes work to be performed. Object oriented library tools present their users with a data interface wherein messages are passed to data-objects which causes work to be performed. AIS Lisp allows Lambda libraries of either flavor to be created and mixed together in arbitrary layers of complexity.
An AIS Lambda may be defined, with a definite list (fixed) or an indefinite list of arguments (variable). The ellipses at the end of the argument list indicate the function has indefinite arguments. At run time, the Lambda's actual arguments are bound to the specified formal definite arguments respectively. An error is generated if there are too few arguments in the definite argument list. If the number of actual arguments exceed the number of definite arguments, and the function has been defined as having indefinite arguments, the excess arguments can only be accessed during via the argCount and argFetch functions at run time.
The keyword faces:(var...) declares the interfaces feature Structure of the Lambda. The features are specified as lists, faces:((english true) (french false)), the listed feature is initialized to the value specified.
The keyword svars:(var...) declares the class variables of the Lambda. The variables are specified as follows svars:(X Y...). If any one of the variables is specified as a list, vars:((X 0) Y), the listed variable is initialized to the constant value specified (The variable X is initialized to the constant 0). Unlike the setq or define special forms, the svars special form always evaluates the initialization value as a constant. A variable may be strongly typed if a type preceeds the variable, svars:((Number:X 0.0) String:Y). If no type is specified, the variable defaults to type Word.
The keyword vars:(var...) declares the temporary variables of the Lambda. The variables are specified as follows vars:(X Y...). If any one of the variables is specified as a list, vars:((X 0) Y...), the listed variable is initialized to the constant value specified (The variable X is initialized to the constant 0). Unlike the setq or define special forms, the vars special form always evaluates the initialization value as a constant. A variable may be strongly typed if a type preceeds the variable, vars:((Number:X 0.0) String:Y). If no type is specified, the variable defaults to type Word.
The keyword pvars:(var...) declares the persistent variables of the Lambda. The variables are specified as a list pvars:(X Y...). If any one of the variables is specified as a list, pvars:((X 0) Y...), the listed variable is initialized to the constant value specified (The variable X is initialized to the constant 0). Unlike the setq or define special forms, the pvars special form always evaluates the initialization value as a constant. A variable may be strongly typed if a type preceeds the variable, pvars:((Integer:X 0) Vector:Y). If no type is specified, the variable defaults to type Word.
The keyword cvars:(var...) declares the constant variables of the Lambda. The variables are specified as a list cvars:(X Y...). If any one of the variables is specified as a list, pvars:((X 0) Y...), the listed variable is initialized to the constant value specified (The variable X is initialized to the constant 0). Unlike the setq or define special forms, the cvars special form always evaluates the initialization value as a constant. A variable may be strongly typed if a type preceeds the variable, cvars:((Boolean:X 0) Number:Y). If no type is specified, the variable defaults to type Word.
The keyword regs:(var...) declares the register variables of the Lambda. The variables are specified as a list regs: (X Y...). If any one of the variables is specified as a list, regs:((X 0) Y...), the listed variable is initialized to the constant value specified (The variable X is initialized to the constant 0). Up to fifty register variables are allowed. Unlike the setq or define special forms, the regs special form always evaluates the initialization value as a constant. A variable may be strongly typed if a type preceeds the variable, regs:((Integer:X 0) CharPointer:Y). If no type is specified, the variable defaults to type Integer.
The body of the Lambda is a sequence of Lisp expressions {exp}. At run time, each of the expressions is evaluated, in the extended environment, from left to right. The Lambda returns the value of the final expression in the sequence.
When To Use
Use this special form when a new Lambda must be declared in Lisp.
Arguments
(arg...) | Zero or more argument variable declarations. |
---|---|
faces:(var...) | (Optional)The Lambda interfaces declarations. |
svars:(var...) | (Optional)The Lambda class variable declarations. |
pvars:(var...) | (Optional)The Lambda persistant variable declarations. |
cvars:(var...) | (Optional)The Lambda constant variable declarations. |
vars:(var...) | (Optional)The Lambda temporary variable declarations. |
regs:(var...) | (Optional)The Lambda register variable declarations. |
expression... | (Mandatory)One or more Lisp expressions defining the body of the Lambda. |
Returns | The new Lambda object. |
Example 1
Here the Lambda expressed as a lambda expressed is immediately invoked with the argument 4.
((lambda(X) (+ X X)) 4) ==> 8
Note: The lambda special form returns a new Lambda object, which is immediately executed. This newly minted Lambda is passed a numeric argument and a numeric result is returned.
Example 2
Here a slightly more complex Lambda is assigned to a global variable.
(define sumNums (lambda(X ...)
vars:(Z)
(setq Z X)
(loop for i from 1 to (-1+ (argCount)) do (setq Z (+ Z (argFetch i))))
Z ))
(sumNums 4 5 71) ==> 80
Note: The lambda special form returns a new Lambda object, which assigned to the specified global variable name. This newly minted Lambda is passed a series of numeric arguments and a numeric result is returned.
Overview
The defclass special form creates a new Class Lambda and assigns it to the specified global variable name.
Type: Special From
Syntax: (defclass libarary:parent:name(args...) svars:(var...) faces:(var...) vars:(var...) pvars:(var...) cvars:(var...) regs:(var...) exp...)
The new class Lambda creates a new class of object and may be either a root class or it may inherit from an existing class or class library. The class Lambda may be called directly when the class itself is to be initialized. The class Lambda may be specified as the argument to the new function when an object of the specified class is to be created. An object of the specified class contains the variables as declared in the svars:() plus any variables which may have been inherited from the parent and/or library classes. The keyword self is used in the class argument lists to denote the current instance of the class object. Whenever the keyword self is declared as the first argument to any method of the class, the Sv register is automatically used for addressing. Whenever the variables declared in the svars:() are referenced on their own, it is assumed that the intended reference is self.
The class Lambda may contain a new method which will be invoked whenever the class Lambda is specified as the argument to the new function. The new function is invoked when an object of the specified class is to be created. The new method must declare the self variable as its first argument and should always return self as its result.
After compilation, the class Lambda will contain a methods list in its Interfaces section named classMethods. Also, the class Lambda will contain a class names list in its Interfaces section named classNames. Plus the parent and library properties in the Interfaces section will be set appropriately, and class property in the Interfaces section will be set true. When the new function is invoked to create an object of the specified class, the new object is linked to the class methods list. Through this manner, the methods list of each class can be separate and distinct while still benefiting from inheritance.
Child classes, which inherit from other classes, will always be friend Lambdas of their parent class Lambda. After compilation, child class Lambdas are linked to their parent classes and to their library classes via the classNames, parent, and library properties of the class Lambda Interfaces sections. Normally, friend Lambdas of a class Lambda are NOT added to the class names list.
Operating alone, Lambdas are of limited capability and value. Operating in communities, Lambdas have immense value and capabilities. AIS Lisp allows individual Lambdas to be formed together into large Lambda communities of complex architecture. Lambdas can work together as classes, methods, children, friends, orphans, all in increasing layers of complexity. A community of Lambdas brought together to accomplish a specific set of tasks AND which can be used as a mobile TOOL is called an Lambda library. The precise qualities which cause an Lambda community to evolve from a simple hodpodge into a useful library are qualitative. However useful Lambda libraries come in two distinctive flavors: Lambda oriented Libraries (AOP), and Object Oriented Libraries (OOP). Lambda oriented library tools present their users with a functional interface wherein data is passed to functional Lambda-objects which causes work to be performed. Object oriented library tools present their users with a data interface wherein messages are passed to data-objects which causes work to be performed. AIS Lisp allows Lambda libraries of either flavor to be created and mixed together in arbitrary layers of complexity.
WARNING: All class names, within a single class library, must be unique!
Note: See also the lambda special form for additional information on creating Lambdas objects.
When To Use
Use this special form when a new class Lambda must be declared in Lisp.
Arguments
library | (Optional)The symbolic name of the class library from which the new class is to inherit (must be a Symbol). |
---|---|
parent | (Optional)The symbolic name of the immediate parent class from which the new class is to inherit (must be a Symbol). |
name | The symbolic name for the new class (must be a Symbol). |
(arg...) | Zero or more argument variable declarations. |
svars:(var...) | (Mandatory)The class variable declarations. |
faces:(var...) | (Optional)The class interfaces declarations. |
pvars:(var...) | (Optional)The class persistant variable declarations. |
cvars:(var...) | (Optional)The class constant variable declarations. |
vars:(var...) | (Optional)The class temporary variable declarations. |
regs:(var...) | (Optional)The class register variable declarations. |
expression... | (Mandatory)One or more Lisp expressions defining the body of the class Lambda. |
Returns | The new Class Lambda. |
Example 1
Creating and initializing a new class of object.
(defclass employee()
svars:(String:Name (Number:Salary 0.0))
(defun new(self String:name Number:salary)
(setq Name name)
(setq Salary salary)
self) ;; end of new method
true) ;; end of employee class
(setq x (new employee "John Doe" 24000.0))
x.Name ==> "John Doe"
x.Salary ==> 24000.0
Note: The new function creates a new copy of the class object, containing all of the variables as declared in the svars:(). This newly minted copy of the class object is passed to the new method as the argument self. The Sv register is automatically set to address the self argument so any reference to the svars:() variables will effect the self object.
One of the most important events occurs at the end of an class's life span, just before the class Lambda is destroyed. When an class Lambda object is no longer referenced, the garbage collector may choose to destroy the Lambda. Before final destruction takes place, the class Lambda will be sent a doomed message.
Each Lambda's EvalWhenDoomed property is initially set to false. Normally, garbage collecting an Lambda, causes nothing to happen (other than the destruction of the Lambda); however, if the class Lambda's EvalWhenDoomed property is set to true, then the doomed Lambda is evaluated by the garbage collector BEFORE final destruction.
For instance, the following class opens a log file and performs operations on the open log file during the life span of the class. When the class Lambda is destroyed, we do not wish the log file to be left open. The class Lambda has the task of responding to the doomed event and closing the file before final destruction.
Example 2
This example shows how the class Lambda can open a log file at class initialization time, keep it open during the life of the class, and close the log file before the class is destroyed.
(defclass myClass(fileName)
svars:(String:WidgetName Integer:Widget)
pvars:(logFileHandle)
(defun closeLog() (setq logFileHandle (fileClose logFileHandle)))
(defun writeLog(record) (fileWrite logFileHandle record))
ClassInitialization::
(setq logFileHandle (fileOpen fileName))
(setq closeLog.EvalWhenDoomed true)
logFileHandle)
Overview
The defclone special form creates a new clone Lambda and assigns it to the specified global variable name. The clone Lambda is a partial copy of the parent Lambda
Type: Special From
Syntax: (defclone libarary:parent:name(args...) svars:(var...) faces:(var...) vars:(var...) pvars:(var...) cvars:(var...) regs:(var...) exp...)
The new clone Lambda creates a partial copy of the parent Lambda and assigns it to the specified global variable name. The clone Lambda contains a copy of the variables as declared in the parent's svars:(), the variables as declared in the parent's pvars:(), and the variables as declared in the parent's cvars:(). The new clone Lambda does NOT share the variables as declared in the parent's faces:().
Operating alone, Lambdas are of limited capability and value. Operating in communities, Lambdas have immense value and capabilities. AIS Lisp allows individual Lambdas to be formed together into large Lambda communities of complex architecture. Lambdas can work together as classes, methods, children, friends, orphans, all in increasing layers of complexity. A community of Lambdas brought together to accomplish a specific set of tasks AND which can be used as a mobile TOOL is called an Lambda library. The precise qualities which cause an Lambda community to evolve from a simple hodpodge into a useful library are qualitative. However useful Lambda libraries come in two distinctive flavors: Lambda oriented Libraries (AOP), and Object Oriented Libraries (OOP). Lambda oriented library tools present their users with a functional interface wherein data is passed to functional Lambda-objects which causes work to be performed. Object oriented library tools present their users with a data interface wherein messages are passed to data-objects which causes work to be performed. AIS Lisp allows Lambda libraries of either flavor to be created and mixed together in arbitrary layers of complexity.
WARNING: All class names, within a single class library, must be unique!
Note: See also the lambda special form for additional information on creating Lambdas objects.
When To Use
Use this special form when a new class Lambda must be declared in Lisp.
Arguments
library | (Optional)The symbolic name of the class library from which the new class is to inherit (must be a Symbol). |
---|---|
parent | (Optional)The symbolic name of the immediate parent class from which the new class is to inherit (must be a Symbol). |
name | The symbolic name for the new class (must be a Symbol). |
(arg...) | Zero or more argument variable declarations. |
svars:(var...) | (Mandatory)The class variable declarations. |
faces:(var...) | (Optional)The class interfaces declarations. |
pvars:(var...) | (Optional)The class persistant variable declarations. |
cvars:(var...) | (Optional)The class constant variable declarations. |
vars:(var...) | (Optional)The class temporary variable declarations. |
regs:(var...) | (Optional)The class register variable declarations. |
expression... | (Mandatory)One or more Lisp expressions defining the body of the class Lambda. |
Returns | The new Class Lambda. |
Example
Creating and initializing a new class of object.
(defun foo(x)
pvars:((Number:Salary 1.0))
(+ Salary x) ;; end of foo
(defclone foo:moo(x)
pvars:((Number:Salary 10.0))
(+ Salary x) ;; end of moo
(foo 24000.0)) ==> "24001.0"
(moo 24000.0)) ==> "24010.0"
Overview
The defun special form creates a new Lambda and assigns it to the specified global variable name.
Type: Special From
Syntax: (defun name(args...) faces:(var...) vars:(var...) pvars:(var...) cvars:(var...) regs:(var...) exp...)
The defun special form creates a new executable object which is assigned to the specified global name. The new Lambda object may be either a root Lambda or it will be a child Lambda of any Lambda within which it is declared. Child defun Lambdas are always registered in the pvars:() of their parent Lambda. The new Lambda may be called directly when the arguments specified in its argument list.
Operating alone, Lambdas are of limited capability and value. Operating in communities, Lambdas have immense value and capabilities. AIS Lisp allows individual Lambdas to be formed together into large Lambda communities of complex architecture. Lambdas can work together as classes, methods, children, friends, orphans, all in increasing layers of complexity. A community of Lambdas brought together to accomplish a specific set of tasks AND which can be used as a mobile TOOL is called an Lambda library. The precise qualities which cause an Lambda community to evolve from a simple hodpodge into a useful library are qualitative. However useful Lambda libraries come in two distinctive flavors: Lambda oriented Libraries (AOP), and Object Oriented Libraries (OOP). Lambda oriented library tools present their users with a functional interface wherein data is passed to functional Lambda-objects which causes work to be performed. Object oriented library tools present their users with a data interface wherein messages are passed to data-objects which causes work to be performed. AIS Lisp allows Lambda libraries of either flavor to be created and mixed together in arbitrary layers of complexity.
WARNING: All child Lambda names, within a single Lambda library, must be unique!
Note: See also the lambda special form for additional information on creating Lambdas objects.
When To Use
Use this special form when a new Lambda must be declared in Lisp.
Arguments
name | The symbolic name for the new Lambda (must be a Symbol). |
---|---|
(arg...) | Zero or more argument variable declarations. |
faces:(var...) | (Optional)The Lambda interfaces declarations. |
pvars:(var...) | (Optional)The Lambda persistant variable declarations. |
cvars:(var...) | (Optional)The Lambda constant variable declarations. |
vars:(var...) | (Optional)The Lambda temporary variable declarations. |
regs:(var...) | (Optional)The Lambda register variable declarations. |
expression... | (Mandatory)One or more Lisp expressions defining the body of the Lambda. |
Returns | The new Lambda object. |
Example 1
This example shows that the defun special form is equivalent to a version of the define special form. This first form:
(defun times(X)
vars:((Z 5))
pvars:((Y 10))
(* X Y Z))
is equivalent to this second form:
(define times
(lambda(X)
vars:((Z 5))
pvars:((Y 10))
(* X Y Z)))
(times 2) ==> 100
Note: The defun special form creates a new Lambda object, containing all of the variables as declared in the pvars:() and vars:(). This newly minted Lambda is passed a numeric argument and a numeric result is returned.
One of the most important events occurs at the end of an Lambda's life span, just before the Lambda is destroyed. When an Lambda object is no longer referenced, the garbage collector may choose to destroy the Lambda. Before final destruction takes place, the Lambda will be sent a doomed message.
Each Lambda's EvalWhenDoomed property is initially set to false. Normally, garbage collecting an Lambda, causes nothing to happen (other than the destruction of the Lambda); however, if the Lambda's EvalWhenDoomed property is set to true, then the doomed Lambda is evaluated by the garbage collector BEFORE final destruction.
For instance, the following Lambda library opens a log file and performs operations on the open log file during the life span of the library. When the Lambda is destroyed, we do not wish the log file to be left open. The Lambda has the task of responding to the doomed event and closing the file before final destruction.
Example 2
This example shows how an Lambda library can open a log file at initialization time, keep it open during the life of the Lambda library, and close the log file before the library is destroyed.
(defun myLambda(fileName)
pvars:(String:WidgetName Integer:Widget)
pvars:(logFileHandle)
(defun closeLog() (setq logFileHandle (fileClose logFileHandle)))
(defun writeLog(record) (fileWrite logFileHandle record))
Initialization::
(setq logFileHandle (fileOpen fileName))
(setq closeLog.EvalWhenDoomed true)
logFileHandle)
Example 3
This example shows how an Lambda library can create and share a user-defined Structure template containing strongly-typed variable declarations.
(defun myLambda(fileName)
pvars:((Structure:Thing #{decl| String:Name Number:Salary Integer:ID}))
vars:(Structure:{Thing}x)
(defun raise(Structure:{Thing}y Number:amount) (+= y.Salary amount))
Initialization::
(setq x (new Thing))
(raise x 20000.00)
x)
Overview
The defchild special form creates a new child Lambda and assigns it to the specified parent Lambda. The new child Lambda object is always assigned to the pvars:() of the specified parent Lambda. The defchild special form always returns the newly created child Lambda object.
Type: Special From
Syntax: (defchild parent:name(args...) faces:(var...) vars:(var...) pvars:(var...) cvars:(var...) regs:(var...) exp...)
(defchild parent name(args...) faces:(var...) vars:(var...) pvars:(var...) cvars:(var...) regs:(var...) exp...)
(defchild parent.member name(args...) faces:(var...) vars:(var...) pvars:(var...) cvars:(var...) regs:(var...) exp...)
The defchild special form creates a new executable object which is assigned to the specified parent name. The new Lambda object will be a child Lambda of the parent Lambda to which it is declared. Child Lambdas are always registered in the pvars:() of their parent Lambda, and child Lambdas always have their pvars:() as the pvars:() of their parent. Child Lambdas always have their cvars:() as the cvars:() of their parent. The new Lambda may be called directly with the arguments specified in its argument list.
Operating alone, Lambdas are of limited capability and value. Operating in communities, Lambdas have immense value and capabilities. AIS Lisp allows individual Lambdas to be formed together into large Lambda communities of complex architecture. Lambdas can work together as classes, methods, children, friends, orphans, all in increasing layers of complexity. A community of Lambdas brought together to accomplish a specific set of tasks AND which can be used as a mobile TOOL is called an Lambda library. The precise qualities which cause an Lambda community to evolve from a simple hodpodge into a useful library are qualitative. However useful Lambda libraries come in two distinctive flavors: Lambda oriented Libraries (AOP), and Object Oriented Libraries (OOP). Lambda oriented library tools present their users with a functional interface wherein data is passed to functional Lambda-objects which causes work to be performed. Object oriented library tools present their users with a data interface wherein messages are passed to data-objects which causes work to be performed. AIS Lisp allows Lambda libraries of either flavor to be created and mixed together in arbitrary layers of complexity.
WARNING: All child Lambda names, within a single Lambda library, must be unique!
Note: See also the lambda special form for additional information on creating Lambdas objects.
When To Use
Use this special form when a new child Lambda must be declared in Lisp.
Arguments
parent | The parent Lambda of the new child Lambda (must be a Symbol or an Lambda). |
---|---|
name | The symbolic name for the new Lambda (must be a Symbol). |
(arg...) | Zero or more argument variable declarations. |
faces:(var...) | (Optional)The Lambda interfaces declarations. |
pvars:(var...) | (Optional)The Lambda persistant variable declarations. |
cvars:(var...) | (Optional)The Lambda constant variable declarations. |
vars:(var...) | (Optional)The Lambda temporary variable declarations. |
regs:(var...) | (Optional)The Lambda register variable declarations. |
expression... | (Mandatory)One or more Lisp expressions defining the body of the Lambda. |
Returns | The new Lambda object. |
Example 1
This example shows how child Lambdas can be defined in separate source files from their parent. For instance, the following two separate forms
(defun foo(x) pvars:(y) (setq y x))
(defchild foo:sum(x) (+ x y))
are equivalent to the following single form
(defun foo(x)
pvars:(y)
(defun sum(x) (+ x y))
(setq y x))
(foo 10) ==> 10
(foo.sum 3) ==> 13
Note: Note: A child Lambda DOES share the same pvars:() and cvars:() variables as its parent Lambda. A friend Lambda has a different pvars:() structure from its parent Lambda, but the cvars:() structure of a friend Lambda is the pvars:() structure of its parent Lambda.
Overview
The defined special form assigns a value to the specified variable name at compile time. The specified name will either be bound to a global symbol or to the pvars:() of the parent Lambda depending on whether the define special form is invoked outside of or inside another Lambda. The major difference between the define nd the setq special forms is that the form makes its assignment once at compile time.
Type: Special From
Syntax: (define name expression)
(define (name args...) faces:(var...) vars:(var...) pvars:(var...) cvars:(var...) regs:(var...) exp...)
(define macro: (name arg...) faces:(var?) vars:(var...) pvars:(var...) cvars:(var...) regs:(var...) exp...)
(define vm: (name arg...) faces:(var?) vars:(var...) pvars:(var...) cvars:(var...) regs:(var...) exp...)
The (define (name args...) special form provides support for a Scheme-like version of defun. Review the defun special form in this document. We will provide further documentation there.
The (define macro: (name args...) special form provides support for a Scheme-like version of defmacro. Review the defmacro special form in this document. We will provide further documentation there.
The (define vm: (name args...) special form provides support for a Scheme-like version of defvm. Review the defvm special form in this document. We will provide further documentation there.
When To Use
Use this special form when a variable must be initialized in Lisp.
Arguments
name | The symbolic name for the variable to be initialized at compile time (must be a Symbol). |
---|---|
expression | (Mandatory)One Lisp expression to be assigned to the specified variable name at compile time. |
Returns | The value of the assigned expression. |
Example 1
This example shows how variables may be initialized in Lisp.
(define y 33)
(defun foo(x) (define y 22) (+= y x))
y ==> 33
foo.y ==> 22
(foo 10) ==> 32
foo.y ==> 32
(foo 10) ==> 42
foo.y ==> 42
Note: Note: The define special form assigns to global variables when it is invoked with global scope. However, if defined within an Lambda, the define special form assigns to the pvars:() of the parent Lambda. Note that the define special form assigns only once a compile time not every time the Lambda is executed.
Overview
The defmacro special form creates a new Macro Lambda object, assigns it to the specified variable name and returns the newly created Macro Lambda object. The new Macro Lambda will be invoked by the compile function during the macro substitution phase of compilation (see the compile, and morph functions).
Type: Special From
Syntax: (defmacro name(args...) faces:(var...) vars:(var...) pvars:(var...) cvars:(var...) regs:(var...) exp...)
(defmacro parent:name(args...) faces:(var...) vars:(var...) pvars:(var...) cvars:(var...) regs:(var...) exp...)
(defmacro parent name(args...) faces:(var...) vars:(var...) pvars:(var...) cvars:(var...) regs:(var...) exp...)
(defmacro parent.member name(args...) faces:(var...) vars:(var...) pvars:(var...) cvars:(var...) regs:(var...) exp...)
The defmacro special form creates a new executable object which is assigned to the specified global name. The new macro Lambda object will always be registered in the global name space, and may be invoked directly in any Lisp expression. Macro Lambdas can be used to enhance any class or Lambda library. It is an AIS Lisp traditional to name all macros, in a library, after the global name of the class or Lambda library with an extending dash "_" symbol. For instance, if our class library has the name ourClassLibrary, then traditionally the enhancing macros for our class library would be named ourClassLibrary_Macro1, ourClassLibrary_Macro2, etc.
Operating alone, Lambdas are of limited capability and value. Operating in communities, Lambdas have immense value and capabilities. AIS Lisp allows individual Lambdas to be formed together into large Lambda communities of complex architecture. Lambdas can work together as classes, methods, children, friends, orphans, macros, all in increasing layers of complexity. A community of Lambdas brought together to accomplish a specific set of tasks AND which can be used as a mobile TOOL is called an Lambda library. The precise qualities which cause an Lambda community to evolve from a simple hodpodge into a useful library are qualitative. However useful Lambda libraries come in two distinctive flavors: Lambda oriented Libraries (AOP), and Object Oriented Libraries (OOP). Lambda oriented library tools present their users with a functional interface wherein data is passed to functional Lambda-objects which causes work to be performed. Object oriented library tools present their users with a data interface wherein messages are passed to data-objects which causes work to be performed. AIS Lisp allows Lambda libraries of either flavor to be created and mixed together in arbitrary layers of complexity.
WARNING: All macro Lambda names must be unique within the global name space!
Note: See also the lambda special form for additional information on creating Lambdas objects.
When To Use
Use this special form when creating a new in-line macro, which expands its arguments, rather than invoking a function call.
Arguments
parent | The parent Lambda of the new macro Lambda (must be a Symbol or an Lambda). |
---|---|
name | The symbolic name for the new Macro Lambda (must be a Symbol). |
(arg...) | Zero or more argument variable declarations. |
faces:(var...) | (Optional)The Lambda interfaces declarations. |
pvars:(var...) | (Optional)The Lambda persistant variable declarations. |
cvars:(var...) | (Optional)The Lambda constant variable declarations. |
vars:(var...) | (Optional)The Lambda temporary variable declarations. |
regs:(var...) | (Optional)The Lambda register variable declarations. |
expression... | (Mandatory)One or more Lisp expressions defining the body of the Lambda. |
Returns | The new list for additional compilation. |
Example 1
In this example, we demonstrate how macros can be used to reduce complex expressions to simpler forms at compile time. The plus macro is defined as follows:
(defmacro plus(x y)
(if (or (isSymbol x) (isSymbol y))
(list |+|: x y)
(+ x y)))
The following form:
(plus 10 20)
is replaced, in-line, with the number
30
but this more complex form:
(plus x 34)
is replaced, in-line, with this form
(+ x 34)
Note: Note: In the language of compilers, the plus macro performs constant folding.
Example 2
This square macro expands its arguments in-line rather than calling a function.
(defmacro square(x) (list |*|: x x))
By invoking the macro below
(square 23)
we generate in-line code as follows:
(* 23 23)
Note: Note: The defmacro special form allows complete control of the macro substitution process during compilation. The macro Lambda may be as complex as required, including macro Lambdas which are complex Lambda libraries.
One of the most important features of AIS Lisp macros is the complete control offered over the macro substitution process. In cases where very simple manipulation of the macro substitution process is required, the defmacro special form can be used with the macroReplace function to provide simple argument substitution similar to the macros in the C language.
Example 3
In this example, we demonstrate how Lisp macros can be used, together with the macroReplace function, to provide simple argument substitution similar to the macros in the C language. The plus macro can also be defined as follows:
(defmacro plus(%1 %2) (macroReplace %1 %2 '(+ %1 %2)))
The following form:
(plus (mod 2 3) 4)
is replaced, in-line, with this form:
(+ (mod 2 3) 4)
Note: Note: The macroReplace function may take any number of arguments. Each argument must be named %nn (where nn is a sequential argument number). The last argument must be a source string of any size (either enclosed in braces or double quotes). Each instance of an argument notation %nn in the source string will be replaced, in the source string, by the appropriate argument. The final argument will be converted into a List and returned as the final form for compilation.
Overview
The defmethod macro creates a new method Lambda for the specified Class Lambda and adds it to the classMethods in the Interfaces section of the specified class Lambda.
Type: Special From
Syntax: (defmethod library:class:msgName(self args...) faces:(var...) vars:(var...) pvars:(var...) cvars:(var...) regs:(var...) exp...)
(defmethod typeName:msgName(self args...) faces:(var...) vars:(var...) pvars:(var...) cvars:(var...) regs:(var...) exp...)
If a typeName is specified, the defmethod special form constructs an Lambda with at least one argument (which by convention is named self). The first argument, declared for the new method Lambda, must be of the specified type typeName. The new method Lambda is added to the Methods Structure of the specified type typeName. After adding the Lambda to the Methods Structure of the specified type, the type will respond to the message named msgName by invoking the new methods Lambda. The defmethod and defstruct special forms support the development of user defined types in AIS Lisp (for those applications where an object oriented type-paradigm is warranted).
If a class is specified, the new method Lambda adds a new function or capability to the specified Lambda class library and may be a root method or may override an existing method of the class library. The method Lambda may be called directly or it may be invoked by sending a message to any object instance of the specified class. The method Lambda must declare self as its first argument followed by any number of additional arguments. Any object of the specified class contains the variables as declared in the class svars:() which always includes all additional svars:() variables inherited from the parent and library classes. The keyword self is used in the method argument lists to denote the current instance of the class object. Whenever the keyword self is declared as the first argument to any method of the class, the Sv register is automatically used for addressing. Whenever the variables declared in the svars:() are referenced on their own, it is assumed that the intended reference is self.
The specified class Lambda will contain a methods list in its Interfaces section named classMethods After compilation, the new method Lambda will be added to the methods list in the specified class Lambda. When the new function is invoked to create an object of the specified class, the new object is linked to the class methods list. Through this manner, a message sent to the object will invoke the corresponding method Lambda.
The method Lambda always shares the svars:() pvars:() and cvars:() variables of the specified class Lambda. The new method Lambda is always a child Lambda of the class Lambda. The only difference between a simple child Lambda and a method Lambda is the method Lambda is added to the classMethods Structure in the Interfaces section of the class Lambda. Normally child, friend, and orphan Lambdas are NOT added to the methods list of the class Lambda. Declare as methods only those functions which are to be publicly available via messages to objects of the specified class.
WARNING: All method Lambda names, within a single class Lambda, must be unique!
Note: See also the lambda special form for additional information on creating Lambdas objects.
When To Use
Use this macro when a class Lambda must be extended with new functionality.
Arguments
library | (Optional)The symbolic name of the class library to which the new method is to belong (must be a Symbol). |
---|---|
class or typeName | The symbolic name of the Lambda class or type to which the new method is to belong (must be a Symbol). |
msgName | The symbolic name of the new method (must be a Symbol). |
(self arg...) | The mandatory self argument plus zero or more argument variable declarations. |
faces:(var...) | (Optional)The method Lambda interfaces declarations. |
pvars:(var...) | (Optional)The class Lambda persistant variable declarations. |
cvars:(var...) | (Optional)The class Lambda constant variable declarations. |
vars:(var...) | (Optional)The method Lambda temporary variable declarations. |
regs:(var...) | (Optional)The method Lambda register variable declarations. |
expression... | (Mandatory)One or more Lisp expressions defining the body of the method Lambda. |
Returns | The programmer defined results of the method invocation. |
Example 1
Creating and enhancing a new class of object with a new method function.
(defclass employee()
svars:((String:Name "John Doe") (Number:Salary 0.0))
true) ;; end of employee class
(defmethod employee:raise(self Number:amount)
(+= Salary amount)
Salary) ;; end of raise method
(setq x (new employee))
(raise:x 22000) ==> 22000
Note: The new function creates a new object of the class, containing all of the variables as declared in the svars:(). In other words, self is an object containing members self.Name and self.Salary (see the svars:() declarations in the class Lambda). This newly minted copy of the class object is sent the "raise" message which invokes the raise method Lambda. In the raise method, the reference to Salary is assumed to be equivalent to a reference to self.Salary. The Sv register is automatically set to address the self argument. Therefore all references to the svars:() variables effect the self object.
One of the most important properties of class library construction is inheritance between class Lambdas. Through inheritance a newly declared class may automatically obtain many of the properties of its parent and library class Lambdas. For instance, the following class declarations show how properties of a parent class can be inherited by a child class.
Example 2
This example shows how the manager class Lambda inherits the properties of its parent class.
(defclass employee() svars:((String:Name "John Doe") (Number:Salary 0.0)) true)
(defmethod employee:raise(self Number:amount) (+= Salary amount) Salary)
(defclass employee:manager() svars:((String:Dept "Sales Division")) true)
(setq x (new employee.manager))
(raise:x 22000) ==> 22000
Note: The new function creates a new object of the class "manager" (from the employee class library), containing all of the variables as declared in the svars:() of the manager class and all those variables svars:() variables declared in the parent class employee. In other words, self is an object containing members self.Name, self.Salary, and self.Dept (see the svars:() declarations in both employee and manager class Lambdas). This newly minted copy of the manager object is sent the "raise" message which invokes the raise method Lambda. The raise method does not have to be defined again because the manager class inherits it from the employee class. In the raise method, the reference to Salary is assumed to be equivalent to a reference to self.Salary. The Sv register is automatically set to address the self argument. Therefore all references to the svars:() variables effect the self object.
Example 3
This example shows how the manager class Lambda may override an inherited properties of its parent class.
(defclass employee() svars:((String:Name "John Doe") (Number:Salary 0.0)) true)
(defmethod employee:raise(self Number:amount) (+= Salary amount) Salary)
(defclass employee:manager() svars:((String:Dept "Sales Division")) true)
(defmethod employee:manager:raise(self Number:amount) (+= Salary (* 1.2 amount)) Salary)
(setq x (new employee.manager))
(raise:x 20000) ==> 24000
Note: The new function creates a new object of the class "manager" (from the employee class library), containing all of the variables as declared in the svars:() of the manager class and all those variables svars:() variables declared in the parent class employee. In other words, self is an object containing members self.Name, self.Salary, and self.Dept (see the svars:() declarations in both employee and manager class Lambdas). This newly minted copy of the manager object is sent the "raise" message which invokes the manager's raise method Lambda. The raise method declared for the manager class overrides the raise method inherited from the parent employee class. The raise method does not have to be defined again because the manager class inherits it from the employee class. In the raise method, the reference to Salary is assumed to be equivalent to a reference to self.Salary. The Sv register is automatically set to address the self argument. Therefore all references to the svars:() variables effect the self object.
Overview
The defriend special form creates a new friend Lambda and assigns it to the specified parent Lambda. The new friend Lambda object is always assigned to the pvars:() of the specified parent Lambda. The defriend special form always returns the newly created friend Lambda object.
Type: Special From
Syntax: (defriend parent:name(args...) faces:(var...) vars:(var...) pvars:(var...) cvars:(var...) regs:(var...) exp...)
(defriend parent name(args...) faces:(var...) vars:(var...) pvars:(var...) cvars:(var...) regs:(var...) exp...)
(defriend parent.member name(args...) faces:(var...) vars:(var...) pvars:(var...) cvars:(var...) regs:(var...) exp...)
The defriend special form creates a new executable object which is assigned to the specified parent name. The new Lambda object will be a friend Lambda of the parent Lambda to which it is declared. Friend Lambdas are always registered in the pvars:() of their parent Lambda, and friend Lambdas always have their pvars:() new an separate from the pvars:() of their parent. Friend Lambdas always have their cvars:() shared as the pvars:() of their parent. Friend Lambdas cannot see the cvars:() of their parent, and parents cannot see the pvars:() of their friend Lambdas. The new Lambda may be called directly with the arguments specified in its argument list.
Operating alone, Lambdas are of limited capability and value. Operating in communities, Lambdas have immense value and capabilities. AIS Lisp allows individual Lambdas to be formed together into large Lambda communities of complex architecture. Lambdas can work together as classes, methods, children, friends, orphans, all in increasing layers of complexity. A community of Lambdas brought together to accomplish a specific set of tasks AND which can be used as a mobile TOOL is called an Lambda library. The precise qualities which cause an Lambda community to evolve from a simple hodpodge into a useful library are qualitative. However useful Lambda libraries come in two distinctive flavors: Lambda oriented Libraries (AOP), and Object Oriented Libraries (OOP). Lambda oriented library tools present their users with a functional interface wherein data is passed to functional Lambda-objects which causes work to be performed. Object oriented library tools present their users with a data interface wherein messages are passed to data-objects which causes work to be performed. AIS Lisp allows Lambda libraries of either flavor to be created and mixed together in arbitrary layers of complexity.
WARNING: All friend Lambda names, within a single Lambda library, must be unique!
Note: See also the lambda special form for additional information on creating Lambdas objects.
When To Use
Use this special form when a new friend Lambda must be declared in Lisp.
Arguments
parent | The parent Lambda of the new friend Lambda (must be a Symbol or an Lambda). |
---|---|
name | The symbolic name for the new Lambda (must be a Symbol). |
(arg...) | Zero or more argument variable declarations. |
faces:(var...) | (Optional)The Lambda interfaces declarations. |
pvars:(var...) | (Optional)The Lambda persistant variable declarations. |
cvars:(var...) | (Optional)The Lambda constant variable declarations. |
vars:(var...) | (Optional)The Lambda temporary variable declarations. |
regs:(var...) | (Optional)The Lambda register variable declarations. |
expression... | (Mandatory)One or more Lisp expressions defining the body of the Lambda. |
Returns | The new Lambda object. |
Example 1
This example shows how friend Lambdas can be defined in separate source files from their parent. For instance, the following two separate forms
(defun foo(x) pvars:(y) (setq y x))
(defriend foo:sum(x) (+ x y))
(foo 10) ==> 10
(foo.sum 3) ==> 13
foo.Pv.y ==> 10
foo.sum.Cv.y ==> 10
Note: Note: A friend Lambda does not share the same pvars:() variables with its parent; however, the cvars:() structure of a friend Lambda is the pvars:() structure of its parent Lambda.
Overview
The deforphan special form creates a new orphan Lambda and assigns it to the specified parent Lambda. The new orphan Lambda object is always assigned to the pvars:() of the specified parent Lambda. The deforphan special form always returns the newly created orphan Lambda object.
Type: Special From
Syntax: (deforphan parent:name(args...) faces:(var...) vars:(var...) pvars:(var...) cvars:(var...) regs:(var...) exp...)
(deforphan parent name(args...) faces:(var...) vars:(var...) pvars:(var...) cvars:(var...) regs:(var...) exp...)
(deforphan parent.member name(args...) faces:(var...) vars:(var...) pvars:(var...) cvars:(var...) regs:(var...) exp...)
The deforphan special form creates a new executable object which is assigned to the specified parent name. The new Lambda object will be an orphan Lambda of the parent Lambda to which it is declared. Orphan Lambdas are always registered in the pvars:() of their parent Lambda, and Orphan Lambdas always have their pvars:() new an separate from the pvars:() of their parent. Orphan Lambdas always have their cvars:() new an separate from the cvars:() of their parent. Orphan Lambdas cannot see the pvars:() of their parent, and orphan Lambdas cannot see the cvars:() of their parent. Orphan Lambdas cannot see their parent. The new Lambda may be called directly with the arguments specified in its argument list.
Operating alone, Lambdas are of limited capability and value. Operating in communities, Lambdas have immense value and capabilities. AIS Lisp allows individual Lambdas to be formed together into large Lambda communities of complex architecture. Lambdas can work together as classes, methods, children, friends, orphans, all in increasing layers of complexity. A community of Lambdas brought together to accomplish a specific set of tasks AND which can be used as a mobile TOOL is called an Lambda library. The precise qualities which cause an Lambda community to evolve from a simple hodpodge into a useful library are qualitative. However useful Lambda libraries come in two distinctive flavors: Lambda oriented Libraries (AOP), and Object Oriented Libraries (OOP). Lambda oriented library tools present their users with a functional interface wherein data is passed to functional Lambda-objects which causes work to be performed. Object oriented library tools present their users with a data interface wherein messages are passed to data-objects which causes work to be performed. AIS Lisp allows Lambda libraries of either flavor to be created and mixed together in arbitrary layers of complexity.
WARNING: All orphan Lambda names, within a single Lambda library, must be unique!
Note: See also the lambda special form for additional information on creating Lambdas objects.
When To Use
Use this special form when a new orphan Lambda must be declared in Lisp.
Arguments
parent | The parent Lambda of the new orphan Lambda (must be a Symbol or an Lambda). |
---|---|
name | The symbolic name for the new Lambda (must be a Symbol). |
(arg...) | Zero or more argument variable declarations. |
faces:(var...) | (Optional)The Lambda interfaces declarations. |
pvars:(var...) | (Optional)The Lambda persistant variable declarations. |
cvars:(var...) | (Optional)The Lambda constant variable declarations. |
vars:(var...) | (Optional)The Lambda temporary variable declarations. |
regs:(var...) | (Optional)The Lambda register variable declarations. |
expression... | (Mandatory)One or more Lisp expressions defining the body of the Lambda. |
Returns | The new Lambda object. |
Example 1
This example shows how orphan Lambdas can be defined in separate source files from their parent. For instance, the following two separate forms
(defun foo(x) pvars:(y) (setq y x))
(deforphan foo:sum(x) pvars:((y 20)) (+ x y))
(foo 10) ==> 10
(foo.sum 3) ==> 23
foo.Pv.y ==> 10
foo.sum.Pv.y ==> 20
Note: Note: An orphan Lambda does not share the same pvars:() variables with its parent; and, an orphan Lambda does not share the same cvars:() variables with its parent;
Overview
The defstruct special form creates and initializes a new Structure type {newType} with the specified field names {fieldnames}. There may be one or more field names. The new Structure type created by defstruct can inherit from another Structure by specifying the include: keyword and the name of the parent object {parentName}.
The defstruct special form results in the following substitution:
(defineStructure newType: include: parentName fieldnames....)
The defstruct special form is a mechanism for adding user-defined Structure types to the Analytic Information Server context. The defstruct special form brings the conventional object-oriented paradigm to the Analytic Information Server tool set. The special form describes a template for the new Structure type. The object is not instantiated until the constructor function is invoked. The new Structure type can inherit field names (analogous to OOP properties or members) and methods by using the include: syntax.
Type: Special From
Syntax: (defstruct newType: fieldnames....)
(defstruct newType: include: parentName fieldnames....)
Arguments
newType | The symbolic name for the new Structure type. |
---|---|
include: | An optional keyword. If present, it must be followed by an existing Structure type. |
parentName | If the include: keyword is present, it must be followed by an existing Structure type name. |
fieldName... | One or more symbolic field name declarations. |
Returns | The new Structure type. |
When To Use
Use the defstruct special form whenever the creation of additional Structure types is appropriate.
Example 1
Here we create a new Structure type to represent employees.
(defstruct Employee: Name: Address: Salary:)
(defmethod Employee:raise(self amount) (+= self.Salary amount))
(setq self (new Employee: Name: "John Doe" Address: "Las Vegas, Nevada" Salary: $20000.00))
(raise: self $3000.00) Returns $23000.00
Overview
The defvm macro creates an Lambda Virtual Machine object, assigns it to the specified global variable name in the global environment, and returns the newly created Lambda Virtual Machine object. The new Virtual Machine Lambda object is assigned to the specified global variable name, and can be used to control the behavior of any other Lambda to which it is assigned.
Every AIS Lambda object must be assigned a virtual machine, which controls the behavior of the Lambda object when it is invoked. Normally, the compile function assigns the drmVirtualMachine to each Lambda object which it compiles. The drmVirtualMachine controls Lambda object behavior using a Dynamically typed word Register Machine model, and contains both an emulation mode and a Just-In-Time compiler. The defvm macro allows the creation of additional Lambda Virtual Machines. These additional virtual machines can be used to implement alternative machine models or to provide profiling and debugging information.
Type: Special From
Syntax: (defvm name(arg...) faces:(vars?) regs:(var...) vars:(var...) pvars:(var...) cvars:(var...) exp...)
Operating alone, Lambdas are of limited capability and value. Operating in communities, Lambdas have immense value and capabilities. AIS Lisp allows individual Lambdas to be formed together into large Lambda communities of complex architecture. Lambdas can work together as classes, methods, children, friends, orphans, all in increasing layers of complexity. A community of Lambdas brought together to accomplish a specific set of tasks AND which can be used as a mobile TOOL is called an Lambda library. The precise qualities which cause an Lambda community to evolve from a simple hodpodge into a useful library are qualitative. However useful Lambda libraries come in two distinctive flavors: Lambda oriented Libraries (AOP), and Object Oriented Libraries (OOP). Lambda oriented library tools present their users with a functional interface wherein data is passed to functional Lambda-objects which causes work to be performed. Object oriented library tools present their users with a data interface wherein messages are passed to data-objects which causes work to be performed. AIS Lisp allows Lambda libraries of either flavor to be created and mixed together in arbitrary layers of complexity.
WARNING: All orphan Lambda names, within a single Lambda library, must be unique!
Note: See also the lambda special form for additional information on creating Lambdas objects.
When To Use
Use this special form when a new virtual machine Lambda must be declared in Lisp.
Arguments
name | The symbolic name for the new virtual machine Lambda (must be a Symbol). |
---|---|
(arg...) | Zero or more argument variable declarations. |
faces:(var...) | (Optional)The Lambda interfaces declarations. |
pvars:(var...) | (Optional)The Lambda persistant variable declarations. |
cvars:(var...) | (Optional)The Lambda constant variable declarations. |
vars:(var...) | (Optional)The Lambda temporary variable declarations. |
regs:(var...) | (Optional)The Lambda register variable declarations. |
expression... | (Mandatory)One or more Lisp expressions defining the body of the Lambda. |
Returns | The new Lambda object. |
When To Use
Use the defvm special form whenever the creation of additional Lambda Virtual Machines is appropriate. Additional Lambda Virtual Machines can be used to implement alternative machine models or to provide profiling and debugging information.
Example 1
Here we create an Lambda Virtual Machine whose job is to keep a count of the number of times each of its client Lambdas is invoked.
(defvm countVM(...)
regs:(n)
vars:(client x result)
pvars:(clientList)
;; Retrieve my client (who will always be the last argument)
(setq client (argFetch (sub1 (argCount))))
;; Initialize my client list (if necessary)
(if (= clientList #void) (setq new clientList (new Dictionary:)))
;; Initialize this client count history (only on the first invocation)
(if (= clientList[client] #void)
(begin
(setq n 0)
(setq x (copy client)) ;; Make a copy of my client
(setq x.Vm drmVirtualMachine:) ;; The copy will run on the standard DRM
(vmregSaveTail n x) ;; Use the tail of the client to keep its count
(setq clientList[client] x)
)) ; end if
(setq x clientList[client])
(vmregLoadTail x n) ;; Use the tail of the client to keep its count
(++ n)
(vmregSaveTail n x)
(setq clientList[client] x)
(vmapply -1 x result)) ;; Invoke the client passing the original arguments
Notes & Hints
The defvm macro must define an Lambda Virtual Machine whose last argument is always the Lambda whose behavior is to be controlled.
The and special form evaluates each expression from left to right. As soon as any expression evaluates to False, the and special form will return False. If all expressions evaluate to True, the value True is returned. If no expressions are specified, the value True is returned.
Type: Special Form
Syntax examples
(and exp ...)
Arguments
exp ? | Any number of expressions to be evaluated |
---|---|
Returns | If All expressions evaluate to True, True is returned. If one expression evaluate to False, False is returned. If no expressions are specified, True is returned. |
When To Use
[...under construction...]
Example 1
Here are but a few examples of the and special form.
(and (= 12 12) (> 2 1))Returns true
(and (= 24 24) (< 1 1))Returns false
(and 1 2 3 4 5)Returns false
(and) Returns true
Notes & Hints
[...under construction...]
The argCount special form is the only method to return the number of arguments that was passed to the current Lambda. The current Lambda has been defined with an indefinite number of arguments using the ellipsis syntax form. The number of arguments is only known at runtime.
Type: Special Form
Syntax examples
(argCount)
Arguments
Returns | The number of arguments for the current Lambda. |
---|
When To Use
The argCount special form is the only method to return the number of arguments that was passed to the current Lambda. The current Lambda has been defined with an indefinite number of arguments using the ellipsis syntax form. The number of arguments is only known at runtime.
Example 1
Here is an example of the argCount special form in use.
(define SumNums
(lambda (X ...) vars:(Z)
(setq Z X)
(loop for i from 1 until (argCount) do
(setq Z (+ Z (argFetch i))))
Z))
(SumNums 4 5 71) Returns 80
Notes & Hints
An Analytic Information Server Lambda may be defined, with a definite list (fixed) or an indefinite list of arguments (variable) The ellipses at the end of the argument list indicates the function has indefinite arguments. At run time, the Lambda's arguments are bound to the specified definite arguments respectively. The Lisp compiler can detect and generate an error message when there are too few arguments in the definite argument list. If the number of arguments exceed the number of definite arguments, the excess arguments can only be accessed during runtime via the argCount and argFetch functions. (see the lambda special form).
The argFetch special form is used to access arguments in Lambdas which have been sent an indefinite number of arguments using the ellipses syntax form. The number of arguments are only known at runtime.
Type: Special Form
Syntax examples
(argFetch index)
Arguments
index | The index of the argument to be fetched. |
---|---|
Returns | The value of the indexed argument. |
When To Use
The argFetch special form is used to access arguments in Lambdas which have been sent an indefinite number of arguments using the ellipses syntax form. The number of arguments are only known at runtime.
Example 1
Here is an example of the argCount special form in use.
(define SumNums
(lambda (X ...) vars:(Z)
(setq Z X)
(loop for i from 1 until (argCount) do
(setq Z (+ Z (argFetch i))))
Z))
(SumNums 4 5 71) Returns 80
Notes & Hints
An Analytic Information Server Lambda may be defined, with a definite list (fixed) or an indefinite list of arguments (variable) The ellipses at the end of the argument list indicates the function has indefinite arguments. At run time, the Lambda's arguments are bound to the specified definite arguments respectively. The Lisp compiler can detect and generate an error message when there are too few arguments in the definite argument list. If the number of arguments exceed the number of definite arguments, the excess arguments can only be accessed during runtime via the argCount and argFetch functions. (see the lambda special form).
The begin Special Form evaluates a sequence of expressions, and returns the value of the last expression. If no expressions are specified, the empty list () is returned.
Type: Special Form
Syntax examples
(begin expression ...)
Arguments
expression ... | Any number of expressions to be evaluated. |
---|---|
Returns | The value of the last expression evaluated is returned. |
When To Use
The begin Special Form marks the beginning of a group of expressions that logically form a compound expression.
Example 1
Here is an example of the begin special form in action.
(define Y (begin (+ 1 2) (+ 3 4))) Returns 7
Notes & Hints
[...under construction...]
The case Special Form selects one of a series of clauses to evaluate based upon the value of a selector expression. (similar to the switch statement in the C programming language). Each clause is a list (matchexp resultexp) which contains a match expression followed by a result expression. Each match expression is an atom, a list of atoms, or the keyword else.
First the selector clause (selectorClause) expression is evaluated, and the result value is compared with the match expression from each match clause (matchClause) until the comparison returns true or until a match with the keyword else is encountered. The selector value is compared to each match expression using the isMember function, if the (matchClause) is a list, and the isEqual function, if (matchClause) is not a list. If no selector matches, the case special form returns the value False. If a clause is selected, the expression in the clause is evaluated. If no match occurred, and the else keyword is present, the expression following the else keyword will be evaluated.
Type: Special Form
Syntax examples
(case selectorClause (matchClause) ? )
(case selectorClause (matchClause) ? (elseClause))
Arguments
selectorClause | An expression to be evaluated. |
---|---|
(matchClause)'s | Any number of matchClauses can be present. Each match clause is a list (matchexp resultexp) which contains a match expression followed by a result expression. Each match expression is an atom, a list of atoms. |
(elseClause) | (Optional) If present there can only be one else clause. Each else clause is a list (else resultexp). The head of the list is the keyword else followed by a result expression. |
Returns | The selectorClause is compared to each matchClause. If the match clause is a list the comparison implements isMember function to determine if the selector matches an element in the list. If the match clause is not a list, the isEqual function will be used to determine if the selector clause matches the match clause. If no selector matches, the case special form returns the value False. If a clause is selected, the expression in the clause is evaluated. If no match occurred, and the else keyword is present, the expression following the else keyword will be evaluated. |
When To Use
[...under construction...]
Example 1
(case (* 2 3)
((2 3 5 7) 'PRIME)
((1 4 6 8 9) 'COMPOSITE)) Returns 'COMPOSITE
Example 2
(case (+ 4 -2)
(1 '(DO-THIS))
(2 '(DO-THAT))
(else '(DO-THE-OTHER))) Returns '(DO-THAT)
Example 3
(case 2
(1 (+ 8 9))
(2 (begin (+ 1 2) (* 4 5)))
(else (/ 5 6))) Returns 20
Notes & Hints
[...under construction...]
The compile function compiles the Analytic Information Server generic parse tree (parseTree) argument (normally the output from lisp) and returns an Lambda object. If the optional (anLambda) argument is passed, it becomes the target of the compilation and is returned; otherwise, a new Lambda object is returned. If the optional true argument is passed, the compilation always inherits the persistent variables of the optional (anLambda) argument.
Type: Function
Syntax examples
(compile parseTree)
(compile parseTree anLambda)
(compile parseTree anLambda true)
Arguments
parseTree | An Analytic Information Server generic parse tree (normally output from lisp) |
---|---|
anLambda | Optional Argument. If present, it specifies the target (Lambda) of the compilation. If not present, a new Lambda object is returned. |
true | Optional Argument. If present, the compilation will inherit the persistent variables of the {anLambda} argument. |
Returns | An executable Lambda object. |
When To Use
Use the compile function when producing an Lambda from a parse tree is required. Normally, a two step process will compile Lisp source: lisp, followed by compile.
Example 1
We can create Lambdas from Lisp source by using the compile function.
(compile (lisp "(lambda(x) (+ x x))"))) Returns #<Lambda 291>
Notes & Hints
We can create Lambda objects by using the makeLambda function (without resorting to using compile). For instance, an Lambda to execute the following Lisp code.
(lambda (n) #void)
Can be created from the following Lisp code.
(makeLambda
Av: #{n: 0}
Pv: #{__C0 10}
Pc: #(pcd| 0))
The same result can be obtained from the following Lisp expression.
(compile '(lambda (n) #void))
The cond Special Form selects one of a series of clauses to evaluate based upon the value of their guard expressions. Each guard expression is a list (guardexp resultexp). The head of the list is a guardexp which is a test expression that results in a Boolean value and the resultexp is any Lisp expression. From left to right each guard expression, is evaluated. If the result is True, the result expression is evaluated and the cond Special Form terminates. If the result is False, the following guard expressions are evaluated until a true is encountered or until the keyword else is encountered. If no guard expression is True or no else is present, the cond Special Form returns the Boolean value False.
Type: Special Form
Syntax examples
(cond ((guardexp) resultexp) ?)
(cond ((guardexp) resultexp) ? (else resultexp))
Arguments
guardexp | An expression to be evaluated. |
---|---|
((guardexp) resultexp)'s | Any number of ((guardexp) resultexp) clauses can be present. Each guardexp is a Lisp expression which, if it returns true, will cause its (resultexp) to be evaluated. Only the resultexp, paired with the first true guardexp, is evaluated. All remaining ((guardexp) resultexp) clauses are skipped. If no guardexp ever returns true, then the optional else clause is evaluated (if present). |
(else resultExp) | (Optional) If present there can only be one else clause. Each else clause is a list (else resultexp). The head of the list is the keyword else followed by a result expression. |
Returns | Each guardexp is evaluated. If no guardexp returns true, the cond special form returns the value False. If a guardexp return true, the resultexp in the clause is evaluated and the value of that resultexp is returned. If no guardexp returns true, and the else keyword is present, the expression following the else keyword will be evaluated. |
When To Use
The cond Special Form behaves like a series of Lisp if - else special forms. Use the cond special form when the use of multiple if - else forms would make the program less readable.
Example 1
(cond ((> 3 2) 'GREATER)
((< 3 2) 'LESS-THAN)) Returns 'GREATER
Example 2
(cond ((> 3 3) 'GREATER)
((< 3 1) 'LESS-THAN)
(else 'EQUAL)) Returns 'EQUAL
Example 3
(cond ((> 3 3) 'GREATER)
((< 3 1) 'LESS-THAN) Returns false
Notes & Hints
[...under construction...]
The eval Function evaluates the argument {exp} and returns the resulting value. When the input to eval is a List, invoking eval is equivalent to invoking compile, and eval. If the eval Function is passed a string as an argument, invoking eval is equivalent to invoking lisp, compile, and eval. If the eval Function is passed an Lambda as an argument, invoking eval is equivalent to invoking the Lambda with no arguments.
Type: Function
Syntax examples
(eval string)
(eval list)
(eval Lambda)
Arguments
string | A string containing a Lisp language expression to be compiled and evaluated. |
---|---|
Returns | Always returns the result of (eval (compile (lisp string))). |
list | A list containing a parse tree expression to be compiled and evaluated. |
---|---|
Returns | Always returns the result of (eval (compile list)). |
Lambda | An Lambda to be invoked with no arguments. |
---|---|
Returns | Always returns the result of (Lambda). |
When To Use
Use the eval function whenever a lisp expression or an Lambda needs to be evaluated.
Example 1
Here follows an example of the eval function in action.
(eval {(lambda() "Hello world")}) Returns "Hello World"
Notes & Hints
The eval Function should only be passed Lambdas of zero arguments.
The goto special form allows Lisp Lambdas to transfer control to goto labels within an Lambda. The goto label is a symbol that is suffixed with the :: character pair when it is defined, and with the : character when it is referenced in the goto expression.
Type: Special Form
Syntax examples
(goto label:)
(goto register)
Arguments
label | The label of the location where execution control is to be transferred. |
---|---|
Returns | The program will start executing at the position specified by the label:: and the goto special form returns True. |
register | The name of a register containing the location where execution control is to be transferred. |
---|---|
Returns | The program will start executing at the position specified by the label:: and the goto special form returns True. |
When To Use
The goto special form is used to handle unconditional branches within an Lambda.
Example 1
Here follow just a few examples of goto forms in action.
(defun foo(X)
(goto TWO:)
ONE::
(writeln "ONE " X)
(goto EXIT:)
TWO::
(writeln "TWO" )
(goto ONE:)
EXIT::
(writeln "foo EXIT" )) Returns #<Lambda 2195>
The invocation of foo produces the following console output.
(foo 1) Returns true
console ==> TWO
console ==> ONE 1
console ==> foo EXIT
Notes & Hints
[...under construction...]
The conditional goto gotoCCt special form allows Lisp Lambdas to conditionally branch to goto labels within an Lambda. The expressions {exp1} and {exp2} are evaluated and {exp2} is compared with {exp1}. If the specified condition CC of the gotoCC conditional goto is true, then the program will start executing at the location specified by the (LabelName:). The conditional goto label is a symbol that is suffixed with the :: character pair when it is defined, and with the : character when it is referenced in the conditional goto expression. The values of the goto contitionals CC are as follows.
An optional strong typing indicator gotoCCt may be appended, which causes the generation of the appropriate memory to memory strongly typed comparison. The values of the optional strong typing indicators t are as follows.
Type: Function
Syntax examples
(gotoCC exp1 exp2 LabelName:)
(gotoCCt exp1 exp2 LabelName:)
Arguments
exp1 | The first expression to be compared. |
---|---|
exp2 | The second expression to be compared. |
LabelName | The label of the location where execution control is to conditionally be transferred. |
Returns | The program will conditionally start executing at the position specified by the label:: and the conditional goto special form returns True. |
When To Use
The conditional goto Special Form is used whenever it is necessary to test for a condition before branching to a location (label) in an Lambda.
Example 1
Here follow just a few examples of conditional goto forms in action.
(defun foo(X)
(gotoGTi (* X 2) 0 TWO:)
ONE::
(writeln "ONE " X)
(gotoEQ X 1 EXIT:)
TWO::
(writeln "TWO" )
(goto ONE:)
EXIT::
(writeln "foo EXIT" )) Returns #<Lambda 2195>
The invocation of foo produces the following console output.
(foo 1) Returns true
console ==> TWO
console ==> ONE 1
console ==> foo EXIT
Notes & Hints
[...under construction...]
The if special form selects one of two expressions to evaluate based upon the value of a (testClause) expression. If the (testClause) evaluates to true, then the (thenClause) expression is evaluated; otherwise, the (elseClause) expression is evaluated. The (testClause) and (thenClause) expressions are mandatory. The (elseClause) expression is optional. The (thenClause) and (elseClause) expressions may be preceded by optional then and else keywords for readability.
Type: Function
Syntax examples
(if (testClause) then (thenClause) else (elseClause)) ; Generates efficient code
(if (testClause) (thenClause) (elseClause)) ; Generates efficient code
(if (testClause) then (thenClause)) ; Generates efficient code
(if (testClause) (thenClause)); Returns false when testClause fails
Arguments
(testClause) | An expression that returns a Boolean value. |
---|---|
then | Optional Keyword. |
(thenClause) | The expression to be executed if the test clause returns true. |
else | Optional Keyword. |
(elseClause) | The expression to be executed if the test clause does NOT returns true. |
Returns | Returns the value of the expression evaluated. |
When To Use
Use the if special form when conditional execution of expressions is essential for your application program.
Use the if special form with the then keyword to generate efficient code without returning false when the test clause fails.
Example 1
Here are just a few examples of the if special form in action.
(if (> 3 2) then 'YES else 'NO) Returns 'YES
(if (> 2 2) then 'YES else (+ 1 2)) Returns 3
(if (> 2 3) 'YES) Returns false
(if (> 2 3) then 'YES) Returns ...undefined...
(if (and (icompareLT 2 3) (icompareGT 3 2)) 'YES 'NO) Returns 'YES
(if (compareGT 2 3) 'YES (+ 3 4)) Returns 7
Notes & Hints
The if special form is similar to the cond special form, except the cond special form supports more than two choices of clauses.
The let special form extends the current environment and evaluates the expressions (exp...) in the extended environment. The let special form evaluates the initial expressions (init). The current environment is then extended to include the specified variables (var). The initial expressions (init) are then bound to the proper variables (var). The expressions (exp) are evaluated from left to right, and the value of the final expression is returned.
Type: Special Form
Syntax examples
(let ((var init)... ) exp...)
Arguments
var | Variable name |
---|---|
init | Constant expression with which to initialize the variable. |
exp | One or more Lisp expressions. |
Returns | The expressions are evaluated from left to right and the value of the final expression is returned. |
When To Use
Use the let form when a series of expressions need to be extended with additional local variables.
Example 1
Here are just a few examples of the let special form in action.
(let ((X 2) (Y 3)) (* X Y)) Returns 6
X Returns 6
(let ((X 2) (Y 3))
(let ((foo(lambda(Z) (+ X Y Z))) (X 7)) Returns #<Lambda 281>
(foo 4) Returns 9
X Returns 6
Notes & Hints
The let special form always extends either the global environment or the persistent environment of the enclosed lambda expression. For instance:
(let ((X 2)) (lambda() true))
Is the equivalent of the following.
(lambda() pvars:((X 2)) true)
The lisp function performs normal Analytic Information Server lexical analysis on the (inputString) argument. The input argument must be a string containing a valid simple or compound Lisp expression. The output of the lisp function is an Analytic Information Server parse tree List containing Lisp lexical and semantic tokens. Normal Lisp strings are passed to the lisp function, whose output is passed to the compile function. The final result, which is produced by compile, is an executable Lambda Object ready to perform its assigned tasks.
This two-step process allows the use of plug-n-play parsers, thus permitting Analytic Information Server to operate with alternate programming languages. The lisp function looks for any directive such as #name# in the very first character positions of the input string. The presence of such a directive will cause the lisp parser to pass control to the global variable name on the assumption that this is an alternate parser. Alternate AIS parser must produce an AIS parse tree list like the lisp function does
If the optional Lambda argument (anLambda), is present, the input source string is converted into a Token Vector and stored in the Sc property of the Lambda (see the disassemble Function). This allows the original source to be stored with the Lambda after compilation.
Normal Lisp lexical analyzers recognize tokens separated by white space.
(lisp ?1 + 2?) Returns three tokens: '(1 + 2)
(lisp ?1+2?) Returns one token: '1+2
If the optional arithmetic: argument is passed, it causes the normal Lisp names to be separated by the arithmetic operators + - * / < > =.
(lisp ?1 + 2?) Returns three tokens: '(1 + 2)
(lisp ?1+2?) Returns three tokens: '(1 + 2)
If the optional extended: argument is passed, the normal Lisp lexical analysis is altered as follows:
(lisp ?(1 + 2)? extended:) Returns five tokens: '(|(| 1 + 2 |)|)
(lisp ?1+2?) Returns three tokens: '(1 + 2)
Type: Function
Syntax examples
(lisp inputString)
(lisp inputString anLambda)
(lisp inputString extended:)
(lisp inputString anLambda extended:)
(lisp inputString arithmetic:)
(lisp inputString anLambda arithmetic:)
Arguments
inputString | Must be a valid Lisp string. If the string begins with #LambdaName# where LambdaName is predefined Lambda, the entire input string will be passed to the Lambda which will perform the lexical analysis. |
---|---|
anLambda | (Optional) The name of the Lambda that will be associated with the result of the lexical analysis. |
extended: | (Optional) Converts the lisp function into a lexical analyzer for simple expressions. |
arithmetic: | (Optional) Causes the normal Lisp names to be separated by the arithmetic operators + - * / < > = . |
Returns | An executable Lambda object. |
When To Use
Use the lisp function when parsing a Lisp string is required. This function will perform full Lisp parsing or even elementary lexical parsing
Example 1
Here is an example of the lisp function in action.
((compile (lisp ?(lambda(x) (+ x 2))?) 10) Returns 12
(lisp ?(1 + 2)?) Returns three tokens: '(1 + 2)
((compile (lisp ?#javaScript#function(x) {return(x + 2);}?) 10) Returns 12
Notes & Hints
The lisp function can be used as an AIS Lisp parser or as a redirector to any number of other user defined languages.
The loop Special Form performs fast numeric iteration. The specified variable (var) is the index of the iteration. The (init) expression forms the initial value for (var) at the start of the iteration. The (step) expression forms the value that is added to the (var) at the start of the next iteration
The (final) expression is compared to the (var) at the start of each iteration. If the to keyword is used, then the iterations will continue as long as (var) is less than or equal to (final). If the until keyword is used, then the iterations will continue as long as (var) is less than (final). During each iteration, each (stmt) is evaluated in order. Next, the (step) value is added to the (var)
If the (step) value is positive, iteration stops when the var is greater than (final). If the (step) is negative, iteration stops when the (var) is less than (final). If the (step) is omitted, the step value is assumed to be 1, and iteration stops when the (var) is greater than (final).
Type: Special Form
Syntax examples
(loop for var from init to final by step do stmt...)
(loop for var from init until final by step do stmt...)
(loop for var from init to final do stmt...)
(loop for var from init until final do stmt...)
Arguments
var | Index Variable. |
---|---|
from | Mandatory keyword. |
init | Initial value of the index variable (must be an Integer). |
to/until | Mandatory keyword (must be either to or until. |
final | Max value of the index variable. Must be an Integer. |
by | Optional keyword. |
step | The step value added to the index variable after an iteration (must be an Integer). |
do | Optional keyword. |
stmt | Multiple Lisp expressions (must be at least one statement). |
Returns | The final value of the (var) variable after exiting from the loop. |
When To Use
Use the loop special form when sequential integer iteration is advisable for your application program.
Example 1
Here are two examples of the loop form in action.
(loop for n from 1 to 10 by 1 do (display " " n)) Returns 11
Console ==> 1 2 3 4 5 6 7 8 9 10
(loop for n from 1 until 10 by 1 do (display " " n)) Returns 10
Console ==> 1 2 3 4 5 6 7 8 9
Notes & Hints
For correct operation, the loop special form's control variables: var, init, final, and step must be integer variables. The loop special form uses fast integer virtual machine instructions to update its control operations: initializing the var (loop index variable), incrementing the var, (adding step to var), and comparing the values of var and final (the termination value).
The morph Function performs normal Analytic Information Server macro substitution on the input argument, (input). The input argument (input) may be any Lisp form or forms enclosed in a list. Often the morph function receives the output of the lisp function. The output of the morph function is a list, which has been transformed by macro substitution. Often the output of morph is input to the compile function; however, the morph function is also used to perform rule-based transformations on list objects.
The second argument (altRule), called the alternative rule function, is optional. If the (altRule) function is specified, this function will perform the macro substitution in place of normal AIS macro substitution rules. The (altRule) function must be a function of one argument. The morph function will repeatedly send the (altRule) function every sub-list within the original input. If the (altRule) function wishes to pass a sub-list without macro substitution, it should return the Boolean value false. If the (altRule) function wishes to perform macro substitution on a sub-list, it should return the transformation to be substituted in place of the original sub-list.
If the optional third argument (altFailure), is present, it may be any legal AIS value. If not present, it defaults to a Boolean value of False.
Type: Function
Syntax examples
(morph input)
(morph input altRule)
(morph input altRule altFailure)
Arguments
input | A list within a list to be transformed with macro or rule-based substitution. |
---|---|
altRule | (Optional) must be a function expecting a single argument, and it will replace the normal AIS macro substitution rules. |
altFailure | (Optional) The value to be recognized by morph that the substitution will not take place. If the altRule function returns the altFailure value, the morph function will not substitute. If the altRule function returns a value other than the altFailure value, morph will perform the substitution. If the alfFailure argument is not present, morph will assume that the failure value is the Boolean value False |
Returns | A list which has been transformed by macro substitutions. |
When To Use
Use the morph function when macro transformation of a list is essential to your application program.
Example 1
Simple Macro substitution using morph.
(morph '((++ x))) Returns '(setq x (+ x 1)) ;; Note that the ++ is a built-in macro
(morph 1) Returns 1
(morph '(1)) Returns 1
(morph '((*= x y))) Returns '(setq x (* x y)) ;; Note that the *= is a built-in macro
Example 2
Macro substitution using an alternative rule function (altRule) and alternative failure (altFailure) options.
(defun foo(x)
(cond
((and (= (length x) 2) (= x[0] add1:) (isNumber x[1])) (+ x[1] 1))
((and (= (length x) 3) (= x[0] +:) (isNumber x[1]) (isNumber x[2])) (+ x[1] x[2]))
(else _failure:))) Returns #<Lambda 729>
(morph '(divi (+ (add1 34) 5) n) foo _failure:) Returns (divi 40 n)
What happens
First morph sends the innermost proper sublist to foo = > (foo '(add1 34)).
The result of (foo ?(add1 34)) => 35, is not the altFailure value _failure, so morph substitutes.
After substitution, the list appears as follows: '(divi (+ 35 5) n).
Next morph sends the next innermost proper sublist to foo = > (foo ?(+ 35 5)).
The result of (foo ?(+ 35 5) => 40, is not the altFailure value _failure, so morph substitutes.
After substitution, the list appears as follows: '(divi 40 n).
Next morph sends the next innermost proper sublist to foo = > (foo '(divi 40 n)).
The result of (foo '(divi 40 n) => _failure:, is the altFailure value _failure.
There are no more proper sublists, so the final morphed list appears as follows: '(divi 40 n).
Notes & Hints
The morph function can be used to built a rule-based list transforming forward production engine (see rulesLib).
The myself Special Form returns the currently evaluating Lambda object.
Type: Special Form
Syntax examples
(myself)
Arguments
Returns | The evaluating executable Lambda object itself. |
---|
When To Use
Use the myself special form when the identity of the current Lambda object is required.
Example 1
Here is an example of the myself special form in action.
(defun foo() (myself)) Returns #<Lambda 888>
(foo) Returns #<Lambda 888>
Notes & Hints
The myself special form is necessary for an executing Lambda to gain access to its own object identity.
The not function returns the Boolean complement of the argument. For all arguments, the not function returns false if and only if the argument (arg) is true. If the argument (arg) is false, the not function returns true.
Type: Function
Syntax examples
(not arg)
Arguments
arg | A boolean expression to be complemented. |
---|
When To Use
Use the not function when complementing a boolean expression is required for your application program.
Example 1
Here are just a few examples of the not function in action.
(not false) Returns true
(not (= 2 2)) Returns false
(not (+ 2 2)) Returns true
Notes & Hints
The not function is very useful in the succint implementation of many if special form conditions.
The onError Special Form assigns an error event handler function (anLambda). The scope of the onError special form is limited to the scope of the current executing Lambda. Any error events, occurring during the scope of the current executing Lambda, will result in the specified error event handler Lambda being invoked.
The specified error event handler Lambda (anLambda), must be a function of one argument. The error event is converted into a text object and passed to the error event handler function.
Type: Special Form
Syntax examples
(onError anLambda)
Arguments
anLambda | The specified error event handler Lambda (anLambda) must be a function of one argument. |
---|---|
Returns | true |
When To Use
Use the onError Special Form to define an error handler function for your program.
Example 1
Here follows a simple example of the onError special form in action.
(defun foo()
(defun errHandler(err) (append "foo got the following error: " err))
(onError errHandler)
(error "badFoo")) Returns #<Lambda 194>
(foo) Returns "foo got the following error: badFoo"
Notes & Hints
The onError special form is an important tool for error recovery in executable Lambda objects.
The or Special Form evaluates each expression from left to right, returning the value true at the first expression that is true. Any remaining expressions are not evaluated. If no expression returns true, the value false is returned. If no expressions are specified, the value false is returned.
Type: Special Form
Syntax examples
(or exp...)
Arguments
exp... | Any Number of boolean expressions. |
---|---|
Returns | Returns the value true at the first expression that is true. Any remaining expressions are not evaluated. If no expression returns true, the value false is returned. If no expressions are specified, the value false is returned. |
When To Use
Use the or Special Form to evaluate a group of expressions, and determine if any one expression in the aggregate is true.
Example 1
Here are just a few examples of the or special form in action.
(or (= 12 12) (> 2 1)) Returns true
(or (= 24 24) (= 1 1)) Returns true
(or 1 2 3 4 5) Returns false
(or) Returns false
Notes & Hints
The or special form is an important tool in succinctly expression if conditionals.
The parse function converts a string value into a numeric, date, vector, or other value. The parse function converts the string according to the built-in Lisp parsing rules. If the string cannot be recognized, by one of the built-in Lisp parsing rules, the original string, without change, is returned.
Type: Function
Syntax examples
(parse string)
Arguments
string | The converted value of the string. If the string cannot be correctly parsed, the original string argument is returned. |
---|---|
Returns | Returns the converted value of the string . If the string cannot be correctly parsed, the original string argument is returned. |
When To Use
Use the parse function when a Lisp constant is to be recognized from an input string.
Example 1
These examples show how a string may be parsed, using the built-in Lisp parsing rules. Each of the examples is parsed and converted, except the last example. It cannot be recognized, and the original string is returned.
(parse "3.141592") Returns 3.141592
(parse "#Jan,19,1993") Returns #Jan,19,1993
(parse "#(1 2 3)") Returns #<Vector 2194>
(parse "23Hello") Returns "23Hello"
Notes & Hints
The parse function allows Lisp constants to be quickly recognized from strings.
The quote Special Form expands its arguments without evaluation of symbols, numbers, constants, or lists. The quote special form returns a list constructed from the specified argument expressions. The newly constructed list is always returned. The quote special form returns its argument expressions unevaluated as constants.
Type: Special Form
Syntax examples
(quote expression...)
Arguments
expressions... | One or more Lisp expressions. |
---|---|
Returns | The unevaluated expressions returned as constants. |
When To Use
Use the quote special form whenever a list is to be interpreted as constant.
Example 1
Here are just a few examples of the quote special form in action.
(defun foo(x) (length x)) Returns #<Lambda 291>
(setq x (new Vector: 3 1 2 3)) Returns #(1 2 3)
x Returns #(1 2 3)
(quote x) Returns x
(foo x) Returns 3
(foo (quote x)) Returns 1
(quote (foo x)) Returns (foo x)
Notes & Hints
The quote special form has an equivalent short hand form in the ' operator.
The refmacro special form invokes a member macro (macroName) from its parent Lambda. The macro invocation may include 0 or more arguments. The refmacro special form can only be used on a macro that has been installed in the parent Lambda and is only invoked during compile time.
Type: Special Form
Syntax examples
((refmacro name macroName) args...)
(name@macroName args...)
Arguments
name | The name of the parent Lambda (must be a Symbol). |
---|---|
macroName | The name of the child macro to be invoked (must be a Symbol). |
arg1... | (Optional) Up to twenty arguments to be sent along with the message. |
Returns | The result of invoking the child macro Lambda on the specified arguments. |
When To Use
Use the refmaco special form when a child macro Lambda is to be invoked during compilation.
Example 1
Here are just a few examples of the colon operator in action.
(defun foo(x) pvars:(v len) (setq v x)) Returns #<Lambda 291>
(defmacro foo:len(self) pvars:(v len) (macroReplace self '(length (ref |Gv:foo| v))))
(setq x (new Vector: 3 1 2 3))
(foo x)
x(foo@len foo) Returns 3
The return Special Form immediately returns the specified argument (exp) to the caller. The current Lambda gives up control and returns to its caller.
Type: Function
Syntax examples
(return exp)
Arguments
exp | Any Lisp expression. |
---|---|
Returns | Immediately evaluates the expression, returns the value and resumes execution of the caller function. |
When To Use
Use the special form
Example 1
[...under construction...]
(begin (return 1) 2) Returns 1
(begin (return (+ 2 3)) 2) Returns 5
Notes & Hints
The return special form allows premature return from an Lambda.
The send special form sends a message (msgName) to an object and causes the corresponding message Lambda to be invoked. The Lambda invocation may include 0 or more arguments. The send special form can only be used on a method that has been installed in the Methods Dictionary for an object via the defmethod macro or the addMethod function. The Methods Dictionary for any Analytic Information Server native type or object contains an arbitrary number of method bindings, i.e. message name and Lambda name pairs. The send special form causes a lookup of the message name argument in the Methods Dictionary specific object argument. If the message name is found, the corresponding message Lambda attached to the message name will be invoked.
Type: Special Form
Syntax examples
(send msgName object)
(send msgName object arg1 arg2 ?)
(msgName:object)
(msgName:object arg1 arg2 ?)
Arguments
msgName | The message to be sent (must be a Symbol). |
---|---|
object | The target object (the object that responds to the message). |
arg1... | (Optional) Up to twenty arguments to be sent along with the message. |
Returns | The result of invoking the message Lambda on the specified object. |
When To Use
Use the send special form when a message is to be sent to an object.
Example 1
Here are several examples of the send special form in action.
(defmethod Lambda: square: (self x) (* x x)) Returns #<Dictionary 1234>
(defun foo(x) pvars:(p1) (setq p1 x)) Returns #<Lambda 634>
(foo 10) Returns 10
(send square: foo foo.p1) Returns 100
(square:foo foo.p1) Returns 100
Notes & Hints
Dissecting the send special form involves understanding the Methods Dictionary of any Analytic Information Server type. The send special form is translated as a reference into the Methods Dictionary. The translation is as follows.
(msgName:object args...) is Identical to ((ref (methodsOf (type object)) msgName) args?)
(square:aNumLambda 10) is Identical to ((ref (methodsOf (type aNumLambda )) square: ) aNumLambda 10)
(square:aNumLambda aNumLambda.p1) Returns 100
(type aNumLambda) Returns Lambda:
(methodsOf (type aNumLambda)) Returns #<Dictionary 194>
(ref (methodsOf (type aNumLambda)) square: ) Returns #<Lambda 164>
((ref (methodsOf (type aNumLambda )) square: ) aNumLambda aNumLambda.p1) Returns 100
The setq special form is a short hand form for the (set) function which assigns new values to variables. A simple set function results in a simple assignment and is completely uncomplicated. However, the set function can also be used to set a new value into a target object with indexing. When indexing is used, the results of the set function depend upon the type of target object being indexed. The result of a set function, with indexing, are complicated because we need to know the type of target object and the types of the indices. In all cases the setq special form converts easily into a longer set function call.
Type: Special Form
Syntax examples
(setq target newValue)
(setq (ref target index1) newValue)
(setq (ref target index1 index2) newValue)
(setq (ref target index1 index2 index3) newValue)
Arguments
target | The target variable to be assigned. |
---|---|
index1 | (Optional) A target variable index. |
index2 | (Optional) A target variable index. |
index3 | (Optional) A target variable index. |
newValue | The new value to be assigned to the target variable. |
Returns | The result of setq depends upon the type of object in the target variable. |
When To Use
Use the setq special form when a longer set function is too cumbersome.
Equivalence Examples
Here are several examples of the setq special form and set function equivalences.
(setq target newValue) Same As (set 'target newValue)
(setq target newValue) Same As (set target: newValue)
(setq target newValue) Same As (vmmove newValue target)
(setq (ref target index1) newValue) Same As (set target index1 newValue)
(setq target[index1] newValue) Same As (set target index1 newValue)
(setq target.index1 newValue) Same As (set target index1 newValue)
(setq (ref target index1 index2) newValue) Same As (set target index1 index2 newValue)
(setq target[index1 index2] newValue) Same As (set target index1 index2 newValue)
(setq (ref target index1 index2 index3) newValue) Same As (set target index1 index2 index3 newValue)
(setq target[index1 index2 index3] newValue) Same As (set target index1 index2 index3 newValue)
The super Special Form supports symbolic messaging with any number of arguments. The message argument must be an element of type Symbol, and there must be at least one argument. The action taken by the symbolic message is dependent upon the type of the first argument. The message symbol is looked up in the Methods Dictionary attached to the type's Parent type (see the defmethod Macro). If the message symbol is found, the associated Lambda is invoked against the whole argument list. If the message symbol is not found, an error condition results.
Type: Special Form
Syntax examples
(super message object args...)
Arguments
message | The symbolic name of the message to be sent. |
---|---|
object | The object whose parent message Lambda is to be invoked. |
args... | (Optional) Up to twenty arguments. |
Returns | The result of invoking the parent message Lambda with the specified arguments. |
When To Use
The super Special Form can only be used on a type that has been defined that is a child of a parent type. The message {message} in the argument list must that have been installed in the Methods Dictionary for the parent type via the defmethod macro or the addMethod function. The Methods Dictionary for any Analytic Information Server native type or object contains an arbitrary number of method bindings, i.e. message name and Lambda name pairs. The super command causes a lookup of the message name argument in the Methods Dictionary for the parent type. If the message name is found, the Lambda attached to the name will be invoked.
Example 1
This example demonstrates normal object oriented messaging in Analytic Information Server. First, we define two types of objects: employees and managers. Managers inherit from employees. Each type is taught how to talk.
(defclass employee: 'name 'job 'salary)
(defmethod employee:talk(me) "I am an employee.")
(talk:(new employee:)) Returns "I am an employee."
(defclass manager: include: employee: 'department)
(defmethod manager:talk(me) "I am a manager.")
(talk:(new manager:)) Returns "I am a manager."
(super talk:(new manager:)) Returns "I am an employee."
Notes & Hints
The super special form can be used to send messages to the parent class of an object.
The while Special Form repeatedly evaluates the expression {exp...} while the test clause {test} evaluates to True. When the test clause evaluates to something other than True execution halts and this value is returned. An optional do keyword may precede the {exp...}.
Type: Special Form
Syntax examples
(while test exp...)
(while test do exp...)
Arguments
test | An expression returning a Boolean: true or false. |
---|---|
exp... | One or more Lisp expressions to be executed while the test expression is true. |
Returns | Always returns the final result of the test expression. |
When To Use
Use the while special form to iterate an expression or set of expressions while a test condition is True. The test clause is always evaluated first.
Example 1
Here are just a few examples of the while special form in action.
(setq Y 10) Returns 10
(while (> Y 0) do (setq Y (- Y 1))) Returns false
Notes & Hints
The while special form is used to iterate an expression or set of expressions while a test condition is True. The test clause is always evaluated first.