eXept Software AG Logo

Smalltalk/X Webserver

Documentation of class 'LazyValue':

Home

Documentation
www.exept.de
Everywhere
for:
[back]

Class: LazyValue


Inheritance:

   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

Description:


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.

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.

example3

an infinite list

example4

an infinite list of primes

example5

an infinite list of emirps

examples2

Attention: 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]

Class protocol:

instance creation
o  block: aBlock
return a new lazyValue, which computes aBlock


Instance protocol:

printing
o  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).

o  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
o  block: aBlock

queries
o  class
(comment from inherited method)
return the receiver's class

synchronising
o  _evaluate_
ensure that block is only executed once

o  doesNotUnderstand: aMessage
enable debugging / inspecting without evaluating

o  perform: aSelector withArguments: argArray
send the message aSelector with all args taken from argArray
to the receiver.

testing
o  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.

o  isLazyValue
true if still lazy; i.e. not yet evaluated


Examples:


    |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.
    ].


ST/X 7.7.0.0; WebServer 1.702 at 20f6060372b9.unknown:8081; Sat, 27 Jul 2024 06:18:04 GMT