362 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			HTML
		
	
	
			
		
		
	
	
			362 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			HTML
		
	
	
| <html>
 | |
|   <head>
 | |
|     <title>Lazy Evaluation</title>
 | |
|     <link rel="stylesheet" type="text/css" href="style.css">
 | |
|       </head>
 | |
|   <body>
 | |
|     <h1>Lazy Evaluation</h1>
 | |
| <p>The 'lazy' vocabulary adds lazy lists to Factor. This provides the
 | |
|     ability to describe infinite structures, and to delay execution of
 | |
|     expressions until they are actually used.</p>
 | |
| <p>Lazy lists, like normal lists, are composed of a head and tail. In
 | |
|     a lazy list the head and tail are something called a 'promise'. 
 | |
|     To convert a
 | |
|     'promise' into its actual value a word called 'force' is used. To
 | |
|     convert a value into a 'promise' the word to use is 'delay'.</p>
 | |
| <table border="1">
 | |
| <tr><td><a href="#delay">delay</a></td></tr>
 | |
| <tr><td><a href="#force">force</a></td></tr>
 | |
| </table>
 | |
| 
 | |
| <p>Many of the lazy list words are named similar to the standard list
 | |
|     words but with an 'l' suffixed to it. Here are the commonly used
 | |
|     words and their equivalent list operation:</p>
 | |
| <table border="1">
 | |
| <tr><th>Lazy List</th><th>Normal List</th></tr>
 | |
| <tr><td><a href="#lnil">lnil</a></td><td>[ ]</td></tr>
 | |
| <tr><td><a href="#lnilp">lnil?</a></td><td>Test for nil value</td></tr>
 | |
| <tr><td><a href="#lcons">lcons</a></td><td>cons</td></tr>
 | |
| <tr><td><a href="#lunit">lunit</a></td><td>unit</td></tr>
 | |
| <tr><td><a href="#lcar">lcar</a></td><td>car</td></tr>
 | |
| <tr><td><a href="#lcdr">lcdr</a></td><td>cdr</td></tr>
 | |
| <tr><td><a href="#lnth">lnth</a></td><td>nth</td></tr>
 | |
| <tr><td><a href="#luncons">luncons</a></td><td>uncons</td></tr>
 | |
| <tr><td><a href="#lmap">lmap</a></td><td>map</td></tr>
 | |
| <tr><td><a href="#lsubset">lsubset</a></td><td>subset</td></tr>
 | |
| <tr><td><a href="#leach">leach</a></td><td>each</td></tr>
 | |
| <tr><td><a href="#lappend">lappend</a></td><td>append</td></tr>
 | |
| </table>
 | |
| <p>A few additional words specific to lazy lists are:</p>
 | |
| <table border="1">
 | |
| <tr><td><a href="#ltake">ltake</a></td><td>Returns a normal list containing a specified
 | |
| number of items from the lazy list.</td></tr>
 | |
| <tr><td><a href="#lappendstar">lappend*</a></td><td>Given a lazy list of lazy lists,
 | |
| concatenate them together in a lazy manner, returning a single lazy
 | |
| list.</td></tr>
 | |
| <tr><td><a href="#list>llist">list>llist</a></td><td>Given a normal list, return a lazy list
 | |
| that contains the same elements as the normal list.</td></tr>
 | |
| </table>
 | |
| <h2>Reference</h2>
 | |
| <!-- delay description -->
 | |
| <a name="delay">
 | |
| <h3>delay ( quot -- <promise> )</h3>
 | |
| <p>'delay' is used to convert a value or expression into a promise.
 | |
|    The word 'force' is used to convert that promise back to its
 | |
|    value, or to force evaluation of the expression to return a value.
 | |
| </p>
 | |
| <p>The value on the stack that 'delay' expects must be quoted. This is
 | |
|    a requirement to prevent it from being evaluated.
 | |
| </p>
 | |
| <pre class="code">
 | |
|   ( 1 ) [ 42 ] <a href="#delay">delay</a> dup .
 | |
|        => << promise [ ] [ 42 ] [ ] [ ] >>
 | |
|   ( 2 ) <a href="#force">force</a> .
 | |
|        => 42
 | |
| </pre>
 | |
| 
 | |
| <!-- force description -->
 | |
| <a name="force">
 | |
| <h3>force ( <promise> -- value )</h3>
 | |
| <p>'force' will evaluate a promises original expression
 | |
|    and leave the value of that expression on the stack.
 | |
| </p>
 | |
| <p>A promise can be forced multiple times but the expression
 | |
|    is only evaluated once. Future calls of 'force' on the promise
 | |
|    will returned the cached value of the original force. If the
 | |
|    expression contains side effects, such as i/o, then that i/o
 | |
|    will only occur on the first 'force'. See below for an example
 | |
|    (steps 3-5).
 | |
| </p>
 | |
| <p>If a promise is itself delayed, a force will evaluate all promises
 | |
|    until a value is returned. Due to this behaviour it is generally not
 | |
|    possible to delay a promise. The example below shows what happens
 | |
|    in this case.
 | |
| </p>
 | |
| <pre class="code">       
 | |
|   ( 1 ) [ 42 ] <a href="#delay">delay</a> dup .
 | |
|        => << promise [ ] [ 42 ] [ ] [ ] >>
 | |
|   ( 2 ) <a href="#force">force</a> .
 | |
|        => 42
 | |
|        
 | |
|         #! Multiple forces on a promise returns cached value
 | |
|   ( 3 ) [ "hello" print 42 ] <a href="#delay">delay</a> dup .
 | |
|        => << promise [ ] [ "hello" print 42 ] [ ] [ ] >>
 | |
|   ( 4 ) dup <a href="#force">force</a> .
 | |
|        => hello
 | |
|           42
 | |
|   ( 5 ) <a href="#force">force</a> .
 | |
|        => 42
 | |
| 
 | |
|         #! Forcing a delayed promise cascades up to return
 | |
|         #! original value, rather than the promise.
 | |
|   ( 6 ) [ [ 42 ] <a href="#delay">delay</a> ] <a href="#delay">delay</a> dup .
 | |
|        => << promise [ ] [ [ 42 ] delay ] [ ] [ ] >>
 | |
|   ( 7 ) <a href="#force">force</a> .
 | |
|        => 42
 | |
| </pre>
 | |
| 
 | |
| <!-- lnil description -->
 | |
| <a name="lnil">
 | |
| <h3>lnil ( -- lcons )</h3>
 | |
| <p>Returns a value representing the empty lazy list.</p>
 | |
| <pre class="code">
 | |
|   ( 1 ) <a href="#lnil">lnil</a> .
 | |
|        => << promise [ ] [ [ ] ] t [ ] >>
 | |
| </pre>
 | |
| 
 | |
| <!-- lnil description -->
 | |
| <a name="lnilp">
 | |
| <h3>lnil? ( lcons -- bool )</h3>
 | |
| <p>Returns true if the given lazy cons is the value representing 
 | |
|    the empty lazy list.</p>
 | |
| <pre class="code">
 | |
|   ( 1 ) <a href="#lnil">lnil</a> <a href="#lnilp">lnil?</a> .
 | |
|        => t
 | |
|   ( 2 ) [ 1 ] <a href="#list2llist">list>llist</a> dup <a href="#lnilp">lnil?</a> .
 | |
|        => [ ]
 | |
|   ( 3 ) <a href="#lcdr">lcdr</a> <a href="#lnilp">lnil?</a> .
 | |
|        => t
 | |
| </pre>
 | |
| 
 | |
| <!-- lcons description -->
 | |
| <a name="lcons">
 | |
| <h3>lcons ( car-promise cdr-promise -- lcons )</h3>
 | |
| <p>Provides the same effect as 'cons' does for normal lists. 
 | |
|    Both values provided must be promises (ie. expressions that have
 | |
|    had <a href="#delay">delay</a> called on them).
 | |
| </p>
 | |
| <p>As the car and cdr passed on the stack are promises, they are not
 | |
|    evaluated until <a href="#lcar">lcar</a> or <a href="#lcdr">lcdr</a>
 | |
|    are called on the lazy cons.</p>
 | |
| <pre class="code">
 | |
|   ( 1 ) [ "car" ] <a href="#delay">delay</a> [ "cdr" ] <a href="#delay">delay</a> <a href="#lcons">lcons</a> dup .
 | |
|        => << promise ... >>
 | |
|   ( 2 ) dup <a href="#lcar">lcar</a> .
 | |
|        => "car"
 | |
|   ( 3 ) dup <a href="#lcdr">lcdr</a> .
 | |
|        => "cdr"
 | |
| </pre>
 | |
|   
 | |
| <!-- lunit description -->
 | |
| <a name="lunit">
 | |
| <h3>lunit ( value-promise -- llist )</h3>
 | |
| <p>Provides the same effect as 'unit' does for normal lists. It
 | |
| creates a lazy list where the first element is the value given.</p>
 | |
| <p>Like <a href="#lcons">lcons</a>, the value on the stack must be
 | |
|    a promise and is not evaluated until the <a href="#lcar">lcar</a>
 | |
|    of the list is requested.</a>
 | |
| <pre class="code">
 | |
|   ( 1 ) [ 42 ] <a href="#delay">delay</a> <a href="#lunit">lunit</a> dup .
 | |
|        => << promise ... >>
 | |
|   ( 2 ) dup <a href="#lcar">lcar</a> .
 | |
|        => 42
 | |
|   ( 3 ) dup <a href="#lcdr">lcdr</a> <a href="#lnilp">lnil?</a> .
 | |
|        => t
 | |
|   ( 4 ) [ . ] <a href="#leach">leach</a>
 | |
|        => 42
 | |
| </pre>
 | |
| 
 | |
| <!-- lcar description -->
 | |
| <a name="lcar">
 | |
| <h3>lcar ( lcons -- value )</h3>
 | |
| <p>Provides the same effect as 'car' does for normal lists. It
 | |
| returns the first element in a lazy cons cell. This will force
 | |
| the evaluation of that element.</p>
 | |
| <pre class="code">
 | |
|   ( 1 ) [ 42 ] <a href="#delay">delay</a> <a href="#lunit">lunit</a> dup .
 | |
|        => << promise ... >>
 | |
|   ( 2 ) <a href="#lcar">lcar</a> .
 | |
|        => 42
 | |
| </pre>
 | |
| 
 | |
| <!-- lcdr description -->
 | |
| <a name="lcdr">
 | |
| <h3>lcdr ( lcons -- value )</h3>
 | |
| <p>Provides the same effect as 'cdr' does for normal lists. It
 | |
| returns the second element in a lazy cons cell and forces it. This
 | |
| causes that element to be evaluated immediately.</p>
 | |
| <pre class="code">
 | |
|   ( 1 ) [ 1 ] <a href="#delay">delay</a> [ 5 6 + ] <a href="#delay">delay</a> <a href="#lcons">lcons</a> dup .
 | |
|        => << promise ... >>
 | |
|   ( 2 ) <a href="#lcdr">lcdr</a> .
 | |
|        => 11
 | |
| </pre>
 | |
| 
 | |
| <pre class="code">
 | |
|   ( 1 ) 5 <a href="#lfrom">lfrom</a> dup .
 | |
|        => << promise ... >>
 | |
|   ( 2 ) <a href="#lcdr">lcdr</a> dup <a href="#lcar">lcar</a> .
 | |
|        => 6
 | |
|   ( 3 ) <a href="#lcdr">lcdr</a> dup <a href="#lcar">lcar</a> .
 | |
|        => 7
 | |
|   ( 4 ) <a href="#lcdr">lcdr</a> dup <a href="#lcar">lcar</a> .
 | |
|        => 8
 | |
| </pre>
 | |
| 
 | |
| <!-- lnth description -->
 | |
| <a name="lnth">
 | |
| <h3>lnth ( n llist -- value )</h3>
 | |
| <p>Provides the same effect as 'nth' does for normal lists. It
 | |
| returns the nth value in the lazy list. It causes all the values up to
 | |
| 'n' to be evaluated.</p>
 | |
| <pre class="code">
 | |
|   ( 1 ) 1 <a href="#lfrom">lfrom</a> dup .
 | |
|        => << promise ... >>
 | |
|   ( 2 ) 5 swap <a href="#lnth">lnth</a> .
 | |
|        => 6
 | |
| </pre>
 | |
| 
 | |
| <!-- luncons description -->
 | |
| <a name="luncons">
 | |
| <h3>luncons ( lcons -- car cdr )</h3>
 | |
| <p>Provides the same effect as 'uncons' does for normal lists. It
 | |
| returns the car and cdr of the lazy list.</p>
 | |
| <pre class="code">
 | |
|   ( 1 ) [ 5 ] <a href="#delay">delay</a> [ 6 ] <a  href="#delay">delay</a> <a href="#lcons">lcons</a> dup .
 | |
|        => << promise ... >>
 | |
|   ( 2 ) <a href="#luncons">luncons</a> . .
 | |
|        => 6
 | |
|           5
 | |
| </pre>
 | |
| 
 | |
| <!-- lmap description -->
 | |
| <a name="lmap">
 | |
| <h3>lmap ( llist quot -- llist )</h3>
 | |
| <p>Lazily maps over a lazy list applying the quotation to each element.
 | |
| A new lazy list is returned which contains the results of the
 | |
| quotation.</p>
 | |
| <p>When intially called nothing in the original lazy list is
 | |
| evaluated. Only when <a href="#lcar">lcar</a> is called will the item
 | |
| in the list be evaluated and applied to the quotation. Ditto with <a
 | |
| href="#lcdr">lcdr</a>, thus allowing infinite lists to be mapped over.</p>
 | |
| <pre class="code">
 | |
|   ( 1 ) 1 <a href="#lfrom">lfrom</a>
 | |
|        => < infinite list of incrementing numbers >
 | |
|   ( 2 ) [ 2 * ] <a href="#lmap">lmap</a>
 | |
|        => < infinite list of numbers incrementing by 2 >
 | |
|   ( 3 ) 5 swap <a href="#ltake">ltake</a> <a  href="#llist2list">llist>list</a> .
 | |
|        => [ 2 4 6 8 10 ]
 | |
| </pre>
 | |
| 
 | |
| <!-- lsubset description -->
 | |
| <a name="lsubset">
 | |
| <h3>lsubset ( llist pred -- llist )</h3>
 | |
| <p>Provides the same effect as 'subset' does for normal lists. It
 | |
| lazily iterates over a lazy list applying the predicate quotation to each
 | |
| element. If that quotation returns true, the element will be included
 | |
| in the resulting lazy list. If it is false, the element will be skipped.
 | |
| A new lazy list is returned which contains  all elements where the
 | |
| predicate returned true.</p>
 | |
| <p>Like <a href="#lmap">lmap</a>, when initially called no evaluation
 | |
| will occur. A lazy list is returned that when values are retrieved
 | |
| from in then items are evaluated and checked against the predicate.</p>
 | |
| <pre class="code">
 | |
|   ( 1 ) 1 <a href="#lfrom">lfrom</a>
 | |
|        => < infinite list of incrementing numbers >
 | |
|   ( 2 ) [ <a href="#primep">prime?</a> ] <a href="#lsubset">lsubset</a>
 | |
|        => < infinite list of prime numbers >
 | |
|   ( 3 ) 5 swap <a href="#ltake">ltake</a> <a  href="#llist2list">llist>list</a> .
 | |
|        => [ 2 3 5 7 11 ]
 | |
| </pre>
 | |
| 
 | |
| <!-- leach description -->
 | |
| <a name="leach">
 | |
| <h3>leach ( llist quot --  )</h3>
 | |
| <p>Provides the same effect as 'each' does for normal lists. It
 | |
| lazily iterates over a lazy list applying the quotation to each
 | |
| element. If this operation is applied to an infinite list it will
 | |
| never return unless the quotation escapes out by calling a continuation.</p>
 | |
| <pre class="code">
 | |
|   ( 1 ) 1 <a href="#lfrom">lfrom</a>
 | |
|        => < infinite list of incrementing numbers >
 | |
|   ( 2 ) [ 2 mod 1 = ] <a href="#lsubset">lsubset</a>
 | |
|        => < infinite list of odd numbers >
 | |
|   ( 3 ) [ . ] <a href="#leach">leach</a> 
 | |
|        => 1
 | |
|           3
 | |
|           5
 | |
|           7
 | |
|           ... for ever ...
 | |
| </pre>
 | |
| 
 | |
| <!-- ltake description -->
 | |
| <a name="ltake">
 | |
| <h3>ltake ( n llist -- llist )</h3>
 | |
| <p>Iterates over the lazy list 'n' times, appending each element to a
 | |
| lazy list. This provides a convenient way of getting elements out of
 | |
| an infinite lazy list.</p>
 | |
| <pre class="code">
 | |
|   ( 1 ) : ones [ 1 ] delay [ ones ] delay <a href="#lcons">lcons</a> ;
 | |
|   ( 2 ) 5 ones <a href="#ltake">ltake</a> <a  href="#llist2list">llist>list</a> .
 | |
|        => [ 1 1 1 1 1  ]
 | |
| </pre>
 | |
| 
 | |
| <!-- lappend description -->
 | |
| <a name="lappend">
 | |
| <h3>lappend ( llist1 llist2 -- llist )</h3>
 | |
| <p>Lazily appends two lists together. The actual appending is done
 | |
| lazily on iteration rather than immediately so it works very fast no
 | |
| matter how large the list.</p>
 | |
| <pre class="code">
 | |
|   ( 1 ) [ 1 2 3 ] <a href="#list2llist">list>llist</a> [ 4 5 6 ] <a href="#list2llist">list>llist</a> <a href="#lappend">lappend</a>
 | |
|   ( 2 ) [ . ] <a href="#leach">leach</a>
 | |
|        => 1
 | |
|           2
 | |
|           3
 | |
|           4
 | |
|           5
 | |
|           6
 | |
| </pre>
 | |
| 
 | |
| <!-- lappend* description -->
 | |
| <a name="lappendstar">
 | |
| <h3>lappend* ( llists -- llist )</h3>
 | |
| <p>Given a lazy list of lazy lists, concatenate them together in a
 | |
| lazy fashion. The actual appending is done lazily on iteration rather
 | |
| than immediately so it works very fast no matter how large the lists.</p>
 | |
| <pre class="code">
 | |
|   ( 1 ) [ 1 2 3 ] <a href="#list2>llist">list>llist</a> 
 | |
|   ( 2 ) [ 4 5 6 ] <a href="#list2llist">list>llist</a> 
 | |
|   ( 3 ) [ 7 8 9 ] <a href="#list2llist">list>llist</a>
 | |
|   ( 4 ) 3list <a href="#list2llist">list>llist</a> <a href="#lappendstar">lappend*</a>
 | |
|   ( 5 ) [ . ] <a href="#leach">leach</a>
 | |
|        => 1
 | |
|           2
 | |
|           3
 | |
|           4
 | |
|           5
 | |
|           6
 | |
|           7
 | |
|           8
 | |
|           9
 | |
| </pre>
 | |
| 
 | |
| <!-- list>llist description -->
 | |
| <a name="list2llist">
 | |
| <h3>list>llist ( list  -- llist )</h3>
 | |
| <p>Converts a normal list into a lazy list. This is done lazily so the
 | |
| initial list is not iterated through immediately.</p>
 | |
| <pre class="code">
 | |
|   ( 1 ) [ 1 2 3 ] <a href="#list2llist">list>llist</a> 
 | |
|   ( 2 ) [ . ] <a href="#leach">leach</a>
 | |
|        => 1
 | |
|           2
 | |
|           3
 | |
| </pre>
 | |
| 
 | |
| <p class="footer">
 | |
| News and updates to this software can be obtained from the authors
 | |
| weblog: <a href="http://radio.weblogs.com/0102385">Chris Double</a>.</p>
 | |
| <p id="copyright">Copyright (c) 2004, Chris Double. All Rights Reserved.</p>
 | |
| </body> </html>
 |