Up | Next | Prev | PrevTail | Tail |
These functions provide for explicit control sequencing, and the definition of blocks altering the scope of local variables.
The <value>s are evaluated (in an unspecified order), and then the <var>s are bound to these
values. The body, consisting of the <body> forms, is evaluated in a left to right order. The
value returned is the result of the last body form or nil if the body is empty. Note
that the <value>s are evaluated in the outer environment, before the <var>s are
bound.
This function is equivalent to
The let-style is attractive since it places the <var>s close to their binding forms (<value>s),
thereby increasing readability.
There are two shorthand formats for (<var> <value>). One is (< var >) and the other is just
< var >. Both of these mean bind < var > to nil. As a rule of style, you should
use (< var > nil) if you mean to use the value of < var > without assigning it it
first, and just (< var >) or < var > if you do not care what < var > gets bound
to.
The following expression returns the middle element of a vector.
There are restrictions as to where the control functions go and return may be placed. The functions go and return are intended to be used within a prog. This is so that they may have only locally determinable effects. Unfortunately these restrictions are not consistent across compiled and interpreted code. It is recommended that if a non-local exit is required then use catch and throw (see section 8.5).
In interpreted code, upon encountering a return a search is made for the latest instance of an entrance to a prog. If the search is successful then the evaluation of that prog is considered complete, the value returned is the argument to return. If the search for a prog fails then the message
is displayed. The treatment of return is much different when the code is compiled. A return may appear outside the scope of a prog. For example, the compiler will compile the sequence
as if it were were enclosed within a prog.
Upon reaching a go within interpreted code a search is made for the latest entrance to a prog. If this search is successful then a second search is made for a label which matches the argument to go. The failure of either search is an error. If the first search fails then
is printed. The message
is printed if the second search fails. When a prog form is compiled the compiler expects to be able to resolve all label references. Thus every go must appear within a prog otherwise the following error message is printed.
In addition, the argument to a go must refer to a label defined inside the prog which contains that go. The message
is printed to indicate when this second restriction is not met.
A simple for construct is available in the basic PSL system; an extended version is defined in the USEFUL package. The basic PSL for provides only the iterator FROM and the action clause DO. PSL users should use the extended version, described here:
A clause is a list, its first element is an identifier, the remaining elements are arguments. A clause may introduce a local variable, specify a return value, or specify when the iteration should cease.
The first few clauses are used to introduce local variables. Some of these clauses also provide the means to stop loop iteration.
The variable <variable> is set to successive elements of <list>. The argument <function> is optional. If present, it may be either the name of a function or a lambda expression. The function is applied to the extracted element before it is assigned to <variable>. Once the argument <list> is exhausted the iteration will stop. The only argument which will be evaluated is <list>.
The variable <variable> is set to successive cdrs of <list>. The first value assigned to <variable> is <list>. Once the <list> is exhausted the iteration will stop. The only argument which will be evaluated is <list>.
The variable <variable> is set to <initial> for the first iteration of the loop. The value of <variable> will be incremented by <step> before each following iteration. Once the value of <variable> is larger than <final> the iteration will stop. Both <initial> and <step> are optional, the default values for each is 1. The argument <final> is optional, in which case the iteration must be stopped by another clause. Each argument except for <variable> will be evaluated once, before the first iteration. To specify <step> without <initial> and <final>, or <final> with <initial> omitted place nil in the slot to be omitted.
At the outset of the first iteration, the variable <variable> will be set to the evaluation of <initial>. Prior to subsequent iterations, the expression <next> will be evaluated and assigned to <variable>.
Each argument <variable-form> is either <variable> or (<variable> <initial>). The square brackets are used to indicate zero or more occurances of <variable-form>. If the first form is used then the variable will be set to nil prior to the first iteration. With the second form the variable will be set to the value of <initial>.
The square brackets are used to indicate zero or more occurances of <form>. Each expression <form> is evaluated during each iteration. They are evaluated in the order of their appearance. You may use return within a <form>, it will cause an immediate exit from the for.
There are two clauses which allow for the evaluation of expressions before the first iteration, and after the last iteration.
The square brackets are used to indicate zero or more occurances of <form>. Once the iteration variables have been bound to their values each expression <form> will be evaluated. They are evaluated in the order of their appearance.
The square brackets are used to indicate zero or more occurances of <form>. After the final iteration each expression <form> will be evaluated. They are evaluated in the order of their appearance. The use of the clauses always and never (described below), may prevent evaluation of the arguments to this clause. There are clauses which specify a return value, if none of them are used then the value of the last <form> will be the value of the for.
The next few clauses are used to build a value to be returned from for Except for the returns and returning clauses, a second argument is used in these clauses to specify that instead of returning the result it will be stored as the value of this second argument. This means that the second argument should be an identifier, it will not be evaluated.
If more than one return value is implied then an error will result
Prior to returning from the for each <form> is evaluated. The order of evalution is left to right. The value of the last <form> is returned as the value of the for.A synonym for returns is returning.
This clause is used to build a list. During each iteration the value of <form> is added at the end of the list. The use of the optional argument <variable> is described above.
These clauses are similar to collect. The difference is that the value of <form> is only added to the list if it is not already an element. To detemine membership in the list adjoin uses member, adjoinq uses memq. The use of the optional argument <variable> is described above.
These clauses are similar to collect. The difference is that the value of <form> is appended (nonc is used with the conc clause), to the end of the list. The use of the optional argument <variable> is described above.
You should be careful with conc. In the example, if conc were used in place of join the computation would never terminate.
These clauses are used to build a set. During each iteration the union of <form> and the set being constructed is computed. Set membership is determined with equal for union, and eq for unionq. The use of the optional argument <variable> is described above.
These clauses are similar to union and unionq. The difference is that the intersection of sets in constructed instead of the union. The use of the optional argument <variable> is described above.
Returns the number of times <form> evaluates to a nonnil value. The use of the optional argument <variable> is described above.
Returns the sum of each evaluation of <form>. The use of the optional argument <variable> is described above.
Returns the product of each evaluation of <form>. The use of the optional argument <variable> is described above.
Returns the maximum value of <form>. The use of the optional argument <variable> is described above.
Returns the minimum value of <form>. The use of the optional argument <variable> is described above.
These clauses are generalizations of the clauses maximize and minimize. Maximal determines the greatest value of <test> over all of the loop iterations. The corresponding value of <value> is returned. As a particular case it is possible to return the value of an iteration variable for which some function attains a maximum value. The functions used for comparisons are greaterp and lessp. The use of the optional argument <variable> is described above.
The remaining clauses are used to control loop iteration.
The square brackets are used to indicate zero or more occurances of <form>. If there is more than one form then the clause is equivalent to (ALWAYS (and [<form>])). This clause is used to specify a return value, t is returned if each <form> is non-nil during each iteration. If one of the <form>s evaluates to nil then the for is terminated and nil is returned, this means that arguments of any finally clause will not be evaluated.
The square brackets are used to indicate zero or more occurances of <form>. If there is more than one form then the clause is equivalent to (NEVER (or [<form>])). Equivalent to (ALWAYS (not [<form>])).
If the argument <form> evaluates to a non-nil value then the for is terminated, the value of <form> is the return value.
The square brackets are used to indicate zero or more occurances of <form>. If there is more than one form then the clause is equivalent to (WHILE (and [<form>])). Loop iteration stops if any <form> evaluates to nil.
The square brackets are used to indicate zero or more occurances of <form>. If there is more than one form then the clause is equivalent to (UNTIL (or [<form>])). Loop iteration stops if any <form> evaluates to a non nil value.
Jump to the next iteration if the value of <form> is non-nil.
The evaluation of a for expression follows a specific order, irregardless of the order in which you place clauses.
The mapping functions long familiar to LISP programmers are present in PSL. However, we believe that the for construct described above or the simpler foreach described below is generally more useful, since it obviates the usual necessity of constructing a lambda expression, and is often more transparent. Mapping functions with more than two arguments are not currently supported. Note however that several lists may be iterated along with for, and with considerably more generality. For example:
may be expressed more transparently as
To augment the simpler for loop present in basic PSL the following list iterator has been provided:
Possible forms are: Setting x to successive elements of u:
Setting x to successive cdrs of u:
Within the context of for the JOIN is used to append successive values. However, inside foreach successive values are concatenated together.
Note that the nconc happens as the mapping process proceeds, not afterward. Therefore the result is not the same as nconcing the results of a maplist. Consider what would occur if
had been used in the example above. Mapcon would apply its second argument to its first argument giving a partial result of (one two). Notice that the first argument to mapcon is eq to this partial result. Now mapcon applies its second argument to (two), the cdr of its first argument. The partial result becomes (one two two). However, the first argument to mapcon has been modified because nconc was used to build the partial result. The value of the first argument is now (one two two). The computation will never terminate, the length of the first argument to mapcon will continue to grow.
A <var-form> is either an id or a list of the form
There are four basic steps in the evaluation of a do form.
If <next> is omitted, the value of the corresponding <var> is left unchanged during step 4. If both <initial> and <next> are omitted or if the <var-form> is an id then the variable is bound to nil in step 1 and left unchanged during step 4.
The function definition below illustrates the use of do. This function will reverse the order of elements in a list.
If do had been used, evaluation of the <initial> form (first local) would have resulted in an error. Either local would be unbound or the value of local from the surrounding environment would have been used.
This is executed just like the corresponding do, except that after the initial bindings are established, but before the exit test is first evaluated, the prologue forms, consisting of the <first> forms, are evaluated in a left to right order. Note that all of the <first> forms are evaluated exactly once, assuming that none of the <first> forms causes an error.
Up | Next | Prev | PrevTail | Front |