|
Class: LazyValue
ProtoObject
|
+--LazyValue
- Package:
- stx:libbasic2
- Category:
- Kernel-Processes
- Version:
- rev:
1.15
date: 2023/07/15 15:57:46
- user: cg
- file: LazyValue.st directory: libbasic2
- module: stx stc-classLibrary: libbasic2
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.
copyrightCOPYRIGHT (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.
example3an infinite list
example4an infinite list of primes
example5an infinite list of emirps
examples2Attention: for the examples below to work,
you have to enable the Parser's AllowLazyValueExtension
and the parser's AllowFunctionCallSyntaxForBlockEvaluation.
(set the corresponding classVariables in Parser to true).
Parser classVarAt:#AllowSTXSyntaxExtensions put:true.
Parser classVarAt:#AllowLazyValueExtension put:true.
Parser classVarAt:#AllowFunctionCallSyntaxForBlockEvaluation put:true.
notice that this is just syntactic sugar: the 'FOO(arg)' notation is
the same as 'FOO value:arg', and !block is the same as 'LazyValue block:block'.
BTW: the # is the binary Cons-message.
[exBegin]
|x|
x := ![ Transcript flash. 1234 ].
Delay waitForSeconds:4.
Transcript showCR:x printString
[exEnd]
listFrom:n - an infinite list of integers starting with n
[exBegin]
|GEN infiniteList|
GEN := [:n | n # ![ GEN( n+1) ] ].
infiniteList := GEN(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 | n # ![ GEN(n+1) ] ].
infiniteList := GEN(1).
GENOdd := [:l |
|lR el|
lR := l.
[
el := lR car.
lR := lR cdr.
el odd
] whileFalse:[].
el # ![ GENOdd(lR) ]
].
infiniteOdd := GENOdd(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 | n # ![powersOfBase(n*base)]].
powersOfBase(1)
].
infiniteListOfPowers := GENPowersOf(2).
1 to:10 do:[:i |
Transcript showCR:infiniteListOfPowers car.
infiniteListOfPowers := infiniteListOfPowers cdr.
].
[exEnd]
merge2:a _:b - merge 2 lists.
the genODD and genEVEN setup is just for testing.
[exBegin]
|GENMerge2 l GEN infiniteList GENFILTER GENOdd infiniteOdd GENEven infiniteEven GENMerge|
GEN := [:n | n # ![GEN(n+1)] ].
infiniteList := GEN(1).
GENFILTER := [:l :filter|
|lR el|
lR := l.
[ el := lR car. lR := lR cdr. filter(el) ] whileFalse:[].
el # ![ GENFILTER(lR. filter) ]
].
GENOdd := [:l | GENFILTER(l. [:el | el odd])].
infiniteOdd := GENOdd(infiniteList).
GENEven := [:l | GENFILTER(l. [:el | el even])].
infiniteEven := GENEven value:infiniteList.
GENMerge2 := [:a :b |
|nextA nextB|
nextA := a car.
nextB := b car.
nextA < nextB ifTrue:[
nextA # ![ GENMerge2(a cdr . b)]
] ifFalse:[
nextB # ![ GENMerge2(a . b cdr)]
].
].
l := GENMerge2(infiniteOdd .infiniteEven).
1 to:10 do:[:i |
Transcript showCR:l car.
l := l cdr.
].
[exEnd]
powersOf2 - generate 2^i for all i >= 0
[exBegin]
|l GENPowersOf powersOf2|
GENPowersOf := [:base |
|powersOfBase|
powersOfBase := [:n | n # ![powersOfBase value:n*base] ].
powersOfBase value:1.
].
powersOf2 := GENPowersOf value:2.
1 to:10 do:[:i |
Transcript showCR:powersOf2 car.
powersOf2 := powersOf2 cdr.
].
[exEnd]
genPoly - generate 2^i + 3^j + 5^k for all i,j,k
unfinished.
[exBegin]
|GENPowersOf genMerge2 l gen infiniteList powersOf2 powersOf3 powersOf5
genAdd genMerge3|
gen := [:n | Cons car:n cdr:( ![gen value:n+1] ) ].
infiniteList := gen value:1.
GENPowersOf := [:base |
|powersOfBase|
powersOfBase := [:n | n # ![powersOfBase value:n*base] ].
powersOfBase(1).
].
powersOf2 := GENPowersOf(2). '2^i' for all i
powersOf3 := GENPowersOf(3). '3^j' for all j
powersOf5 := GENPowersOf(5). '5^k' for all k
genMerge3 := [:a :b :c|
|min nextA nextB nextC rA rB rC|
nextA := a car.
nextB := b car.
nextC := c 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:![genMerge2 value:rA value:rB]
].
genMerge3 := [:a :b :c|
genMerge2(genMerge2(a . b) . c).
].
l := genMerge3 value:powersOf2 value:powersOf3 value:powersOf5.
1 to:10 do:[:i |
Transcript showCR:l car.
l := l cdr.
].
[exEnd]
instance creation
-
block: aBlock
-
return a new lazyValue, which computes aBlock
printing
-
displayOn: aGCOrStream
-
notice: displayString and displayOn: will not wait for the value (they are for developers and inspectors),
whereas printString and printOn: will wait (they are for the program to print data).
-
displayString
-
notice: displayString and displayOn: will not wait for the value (they are for developers and inspectors),
whereas printString and printOn: will wait (they are for the program to print data).
private access
-
block: aBlock
-
queries
-
class
-
(comment from inherited method)
return the receiver's class
synchronising
-
_evaluate_
-
ensure that block is only executed once
-
doesNotUnderstand: aMessage
-
enable debugging / inspecting without evaluating
-
perform: aSelector withArguments: argArray
-
send the message aSelector with all args taken from argArray
to the receiver.
testing
-
isBehavior
-
(comment from inherited method)
return true, if the receiver is describing another object's behavior.
False is returned here - the method is only redefined in Behavior.
-
isLazyValue
-
true if still lazy; i.e. not yet evaluated
|x|
x := LazyValue block:[ Transcript flash. 1234 ].
Delay waitForSeconds:4.
Transcript showCR:x printString
|
listFrom:n - an infinite list of integers starting with n
|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.
].
|
filterOdd:l - an infinite list filtering odd numbers from another list
|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.
].
|
powersOf:n - an infinite list of powers of n
|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.
].
|
merge2:a _:b - merge 2 lists.
|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.
].
|
|