initial checkin
authorClaus Gittinger <cg@exept.de>
Fri, 07 Jun 2002 17:23:46 +0200
changeset 1042 b7160172e039
parent 1041 0a98f63ea04b
child 1043 544a0829a59b
initial checkin
LazyValue.st
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LazyValue.st	Fri Jun 07 17:23:46 2002 +0200
@@ -0,0 +1,329 @@
+"
+ COPYRIGHT (c) 2002 by eXept Software AG
+              All Rights Reserved
+
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice.   This software may not
+ be provided or otherwise made available to, or used by, any
+ other person.  No title to or ownership of the software is
+ hereby transferred.
+"
+
+"{ Package: 'stx:libbasic2' }"
+
+nil subclass:#LazyValue
+	instanceVariableNames:'result block'
+	classVariableNames:'AccessLock'
+	poolDictionaries:''
+	category:'Kernel-Processes'
+!
+
+!LazyValue class methodsFor:'documentation'!
+
+copyright
+"
+ COPYRIGHT (c) 2002 by eXept Software AG
+              All Rights Reserved
+
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice.   This software may not
+ be provided or otherwise made available to, or used by, any
+ other person.  No title to or ownership of the software is
+ hereby transferred.
+"
+!
+
+documentation
+"
+    I represent an expression which might not be needed.
+    Any messages sent to me will force the evaluation (once).
+    The value is remembered.
+
+    Can be used to simulate non-strict programming languages.
+
+    [see also:]
+        Block Future
+
+    [author:]
+        Claus Gittinger
+"
+!
+
+examples
+"
+  listFrom:n - an infinite list of integers starting with n
+                                                        [exBegin]
+    |gen infiniteList|
+
+    gen := [:n |
+                        Cons 
+                            car:n 
+                            cdr:( LazyValue block:[gen value:n+1] )
+                   ].
+
+    infiniteList := gen value:1.
+    1 to:10 do:[:i |
+        Transcript showCR:infiniteList car.
+        infiniteList := infiniteList cdr.
+    ].
+                                                        [exEnd]
+
+  filterOdd:l - an infinite list filtering odd numbers from another list
+                                                        [exBegin]
+    |gen infiniteList genOdd infiniteOdd|
+
+    gen := [:n |
+                        Cons 
+                            car:n 
+                            cdr:( LazyValue block:[gen value:n+1] )
+                   ].
+
+    infiniteList := gen value:1.
+
+    genOdd := [:l |
+                        |lR el|
+
+                        lR := l.
+                        [ el := lR car. lR := lR cdr. el odd ] whileFalse:[].
+                        Cons 
+                            car:el 
+                            cdr:( LazyValue block:[genOdd value:lR] )
+                   ].
+
+    infiniteOdd := genOdd value:infiniteList.
+
+    1 to:10 do:[:i |
+        Transcript showCR:infiniteOdd car.
+        infiniteOdd := infiniteOdd cdr.
+    ].
+                                                        [exEnd]
+
+  powersOf:n - an infinite list of powers of n
+                                                        [exBegin]
+    |genPowersOf infiniteListOfPowers|
+
+    genPowersOf := [:base |
+                   |powersOfBase|
+
+                   powersOfBase :=
+                       [:n |
+                            Cons 
+                                car:n 
+                                cdr:( LazyValue block:[powersOfBase value:n*base] )
+                       ].
+                   powersOfBase value:1.
+                ].
+
+    infiniteListOfPowers := genPowersOf value:2.
+    1 to:10 do:[:i |
+        Transcript showCR:infiniteListOfPowers car.
+        infiniteListOfPowers := infiniteListOfPowers cdr.
+    ].
+                                                        [exEnd]
+
+  merge2:a _:b - merge 2 lists.
+                                                        [exBegin]
+    |genMerge2 l gen infiniteList genOdd infiniteOdd genEven infiniteEven genMerge|
+
+    gen := [:n |
+                        Cons 
+                            car:n 
+                            cdr:( LazyValue block:[gen value:n+1] )
+                   ].
+
+    infiniteList := gen value:1.
+
+    genOdd := [:l |
+                        |lR el|
+
+                        lR := l.
+                        [ el := lR car. lR := lR cdr. el odd ] whileFalse:[].
+                        Cons 
+                            car:el 
+                            cdr:( LazyValue block:[genOdd value:lR] )
+                   ].
+
+    infiniteOdd := genOdd value:infiniteList.
+
+    genEven := [:l |
+                        |lR el|
+
+                        lR := l.
+                        [ el := lR car. lR := lR cdr. el even ] whileFalse:[].
+                        Cons 
+                            car:el 
+                            cdr:( LazyValue block:[genEven value:lR] )
+                   ].
+
+    infiniteEven := genEven value:infiniteList.
+
+    genMerge2 := [:a :b |
+                   |nextA nextB|
+
+                   nextA := a car.
+                   nextB := b car.
+
+                   nextA < nextB ifTrue:[
+                       Cons 
+                           car:nextA 
+                           cdr:( LazyValue block:[genMerge2 value:(a cdr) value:b] )
+                   ] ifFalse:[
+                       Cons 
+                           car:nextB 
+                           cdr:( LazyValue block:[genMerge2 value:a value:(b cdr)] )
+                   ].
+                ].
+
+    l := genMerge2 value:infiniteOdd value:infiniteEven.
+    1 to:10 do:[:i |
+        Transcript showCR:l car.
+        l := l cdr.
+    ].
+                                                        [exEnd]
+
+  genPoly - generate 2^i + 3^j + 5^k for all i,j,k
+  not finished.
+                                                        [exBegin]
+    |genMerge2 l gen genPowersOf infiniteList powersOf2 powersOf3 powersOf5|
+
+    gen := [:n |
+                        Cons 
+                            car:n 
+                            cdr:( LazyValue block:[gen value:n+1] )
+                   ].
+
+    infiniteList := gen value:1.
+
+    genPowersOf := [:base |
+                   |powersOfBase|
+
+                   powersOfBase :=
+                       [:n |
+                            Cons 
+                                car:n 
+                                cdr:( LazyValue block:[powersOfBase value:n*base] )
+                       ].
+                   powersOfBase value:1.
+                ].
+
+    powersOf2 := genPowersOf value:2.
+    powersOf3 := genPowersOf value:3.
+    powersOf5 := genPowersOf value:5.
+
+    genAdd := [:n :l |
+                   |gen|
+
+                   gen := [:l |
+                               Cons 
+                                   car:(car l) * n 
+                                   cdr:( LazyValue block:[gen value:(l cdr)] )
+                          ].
+                   gen value:l
+              ].
+
+    genMerge2 := [:a :b |
+                   |min nextA nextB rA rB|
+
+                   rA := a.
+                   rB := b.
+                   nextA := rA car.
+                   [ (nextB := rB car) = nextA ] whileTrue:[ rB := rB cdr ].
+
+                   nextA < nextB ifTrue:[
+                       'a is smallest'.
+                       min := nextA.
+                       rA := rA cdr.
+                   ] ifFalse:[
+                       'b is smallest'.
+                       min := nextB.
+                       rB := rB cdr.
+                   ].
+
+                   Cons 
+                       car:min 
+                       cdr:( LazyValue block:[genMerge2 value:rA value:rB] )
+                ].
+
+    l := genMerge2 value:powersOf2 value:powersOf3 value:powersOf5.
+    1 to:10 do:[:i |
+        Transcript showCR:l car.
+        l := l cdr.
+    ].
+                                                        [exEnd]
+
+"
+! !
+
+!LazyValue class methodsFor:'initialization'!
+
+initialize
+    AccessLock := RecursionLock forMutualExclusion
+! !
+
+!LazyValue class methodsFor:'instance creation'!
+
+block:aBlock
+    ^ self new block:aBlock
+! !
+
+!LazyValue methodsFor:'error handling'!
+
+doesNotUnderstand:aMessage
+    block notNil ifTrue:[
+        self _evaluate_
+    ].
+    ^ aMessage sendTo:result
+! !
+
+!LazyValue methodsFor:'evaluation'!
+
+_evaluate_
+    block notNil ifTrue:[
+        AccessLock critical:[
+            |b|
+
+            (b := block notNil) ifTrue:[
+                block := nil.
+                result := b value.
+            ].
+        ].
+    ].
+    ^ result
+! !
+
+!LazyValue methodsFor:'printing'!
+
+printOn:aStream
+    aStream nextPutAll:'(lazy)'
+! !
+
+!LazyValue methodsFor:'private access'!
+
+block:aBlock
+    block := aBlock.
+! !
+
+!LazyValue methodsFor:'queries'!
+
+class
+    ^ self _evaluate_ class
+!
+
+isLazyValue
+    ^ block notNil
+! !
+
+!LazyValue methodsFor:'testing'!
+
+isBehavior
+    ^ self _evaluate_ isBehavior
+! !
+
+!LazyValue class methodsFor:'documentation'!
+
+version
+    ^ '$Header: /cvs/stx/stx/libbasic2/LazyValue.st,v 1.1 2002-06-07 15:23:46 cg Exp $'
+! !
+LazyValue initialize!