256 lines
75 KiB
Plaintext
256 lines
75 KiB
Plaintext
Copyright (c) 1986 Xerox Corporation. All rights reserved.
|
||
|
||
2
|
||
|
||
11.6 Possibilities Lists
|
||
1
|
||
|
||
A possibilities list is the interface between a generator and a consumer. The possibilities list is initialized by a call to POSSIBILITIES, and elements are obtained from it by using TRYNEXT. By using the spaghetti stack to maintain separate environments, this package allows a regime in which a generator can put a few items in a possibilities list, suspend itself until they have been consumed, and be subsequently aroused and generate some more.
|
||
(POSSIBILITIES FORM) [NLambda Function]
|
||
1
|
||
|
||
This nlambda function is used for the initial creation of a possibilities list. FORM will be evaluated to create the list. It should use the functions NOTE and AU-REVOIR described below to generate possibilities. Normally, one would set some variable to the possibilities list which is returned, so it can be used later, e.g.:
|
||
(SETQ PLIST (POSSIBILITIES (GENERFN V1 V2))).
|
||
POSSIBILITIES compiles open.
|
||
1
|
||
|
||
(NOTE VAL LSTFLG) [Function]
|
||
1
|
||
|
||
Used within a generator to put items on the possibilities list being generated. If LSTFLG is equal to NIL, VAL is treated as a single item. If LSTFLG is non-NIL, then the list VAL is NCONCed on the end of the possibilities list. Note that it is perfectly reasonable to create a possibilities list using a second generator, and NOTE that list as possibilities for the current generator with LSTFLG equal to T. The lower generator will be resumed at the appropriate point.
|
||
1
|
||
|
||
(AU-REVOIR VAL) [NoSpread Function]
|
||
1
|
||
|
||
Puts VAL on the possibilities list if it is given, and then suspends the generator and returns to the consumer in such a fashion that control will return to the generator at the AU-REVOIR if the consumer exhausts the possibilities list.
|
||
Note: NIL is not put on the possibilities list unless it is explicitly given as an argument to AU-REVOIR, i.e., (AU-REVOIR) and (AU-REVOIR NIL) are not the same. AU-REVOIR and ADIEU are lambda nospreads to enable them to distinguish these two cases.
|
||
1
|
||
|
||
(ADIEU VAL) [NoSpread Function]
|
||
1
|
||
|
||
Like AU-REVOIR except releases the generator instead of suspending it.
|
||
1
|
||
|
||
(TRYNEXT PLST ENDFORM VAL) [NLambda Function]
|
||
1
|
||
|
||
This nlambda function allows a consumer to use a possibilities list. It removes the first item from the possibilities list named by PLST (i.e. PLST must be an atom whose value is a possiblities list), and returns that item, provided it is not a generator handle. If a generator handle is encountered, the generator is reawakened. When it returns a possibilities list, this list is added to the front of the current list. When a call to TRYNEXT causes a generator to be awakened, VAL is returned as the value of the AU-REVOIR which put that generator to sleep. If PLST is empty, it evaluates ENDFORM in the caller's environment.
|
||
TRYNEXT compiles open.
|
||
1
|
||
|
||
(CLEANPOSLST PLST) [Function]
|
||
1
|
||
|
||
This function is provided to release any stack pointers which may be left in the PLST which was not used to exhaustion.
|
||
1
|
||
|
||
For example, FIB is a generator for fibonnaci numbers. It starts out by NOTEing its two arguments, then suspends itself. Thereafter, on being re-awakened, it will NOTE two more terms in the series and suspends again. PRINTFIB uses FIB to print the first N fibonacci numbers.
|
||
(DEFINEQ (FIB (F1 F2)
|
||
(do (NOTE F1)
|
||
(NOTE F2)
|
||
(SETQ F1 (IPLUS F1 F2))
|
||
(SETQ F2 (IPLUS F1 F2))
|
||
(AU-REVOIR)]
|
||
Note that this AU-REVOIR just suspends the generator and adds nothing to the possibilities list except the generator.
|
||
(DEFINEQ (PRINTFIB (N)
|
||
(PROG ((FL (POSSIBILITIES (FIB 0 1))))
|
||
(RPTQ N (PRINT (TRYNEXT FL)))
|
||
(CLEANPOSLST FL)]
|
||
Note that FIB itself will never terminate.
|
||
|