BlockClosure

for VisualWorks 7.7 with Jun780

インスタンス

| aBlock |
aBlock := [3 + 4].
^aBlock
==> BlockClosure [] in UndefinedObject>>unboundMethod
| aString anObject aBlock |
aString := '[self + 4]'.
anObject := 3.
aBlock := Kernel.Compiler evaluate: aString for: anObject logged: false.
^aBlock
==> BlockClosure [] in SmallInteger>>unboundMethod
| aString anObject aContext aNamespace aMethod aBlock |
aString := '[self + 4]'.
anObject := 3.
aContext := thisContext.
aNamespace := Smalltalk.Core.
aMethod := Kernel.Compiler new
            compile: aString
            in: aContext
            allowReceiver: true
            class: anObject class
            environment: aNamespace
            noPattern: true
            notifying: nil
            ifFail: [^nil].
aBlock := anObject performMethod: aMethod with: aContext.
^aBlock
==> BlockClosure [] in SmallInteger>>unboundMethodwith:

評価(引数無しの実行)

| aBlock |
aBlock := [3 + 4].
^aBlock value
==> 7
| aString anObject aBlock |
aString := '[self + 4]'.
anObject := 3.
aBlock := Kernel.Compiler evaluate: aString for: anObject logged: false.
^aBlock value
==> 7
| aString anObject aContext aNamespace aMethod aBlock |
aString := '[self + 4]'.
anObject := 3.
aContext := thisContext.
aNamespace := Smalltalk.Core.
aMethod := Kernel.Compiler new
            compile: aString
            in: aContext
            allowReceiver: true
            class: anObject class
            environment: aNamespace
            noPattern: true
            notifying: nil
            ifFail: [^nil].
aBlock := anObject performMethod: aMethod with: aContext.
^aBlock value
==> 7

評価(引数付きの実行)

[:a | 3 + a] value: 4
==> 7
[:x :y | x @ y] value: 3 value: 4
==> 3 @ 4
[:red :green :blue | Graphics.ColorValue red: red green: green blue: blue]
    value: 0.5
    value: 0.5
    value: 1.0
==> ColorValue royalBlue
[:a | 3 + a] valueWithArguments: (Core.Array with: 4)
==> 7
[:x :y | x @ y] valueWithArguments: (Core.Array with: 3 with: 4)
==> 3 @ 4
[:red :green :blue | Graphics.ColorValue red: red green: green blue: blue]
    valueWithArguments: (Core.Array with: 0.5 with: 0.5 with: 1.0)
==> ColorValue royalBlue

評価(引数の間引き実行)

[Core.Transcript
    clear;
    flush] cull: Core.Date today cull: Core.Time now
 
[:date |
Core.Transcript
    clear;
    nextPutAll: date printString;
    flush] cull: Core.Date today cull: Core.Time now
June 29, 2009
[:date :time |
Core.Transcript
    clear;
    nextPutAll: date printString;
    space;
    nextPutAll: time printString;
    flush] cull: Core.Date today cull: Core.Time now
June 29, 2009 7:19:44 pm
[Core.Transcript
    clear;
    flush]
        cullWithArguments: (Core.Array with: Core.Date today with: Core.Time now)
 
[:date |
Core.Transcript
    clear;
    nextPutAll: date printString;
    flush]
        cullWithArguments: (Core.Array with: Core.Date today with: Core.Time now)
June 29, 2009
[:date :time |
Core.Transcript
    clear;
    nextPutAll: date printString;
    space;
    nextPutAll: time printString;
    flush]
        cullWithArguments: (Core.Array with: Core.Date today with: Core.Time now)
June 29, 2009 7:19:44 pm
(Core.Time dateAndTimeNow detect: [:each | each isKindOf: Core.Time] ifNone: [nil])
    ifNotNil: 
        [:it |
        Core.Transcript
            clear;
            nextPutAll: it printString;
            flush]
7:19:44 pm

ブロック内でのリターン

| redBlock greenBlock blueBlock mainBlock |
redBlock :=
        [Core.Transcript
            show: 'red';
            cr].
greenBlock :=
        [Core.Transcript
            show: 'green';
            cr].
blueBlock :=
        [Core.Transcript
            show: 'blue';
            cr].
mainBlock :=
        [Core.Transcript clear.
        redBlock value.
        greenBlock value.
        blueBlock value].
mainBlock value
red
green
blue
| redBlock greenBlock blueBlock mainBlock |
redBlock :=
        [Core.Transcript
            show: 'red';
            cr.
        ^nil].
greenBlock :=
        [Core.Transcript
            show: 'green';
            cr].
blueBlock :=
        [Core.Transcript
            show: 'blue';
            cr].
mainBlock :=
        [Core.Transcript clear.
        redBlock value.
        greenBlock value.
        blueBlock value].
mainBlock value
red
[[[[[3] value + 4] value + 5] value + 6] value + 7] value
==> 25
[[[[[^3] value + 4] value + 5] value + 6] value + 7] value
==> 3
[[[[^[3] value + 4] value + 5] value + 6] value + 7] value
==> 7
[[[^[[3] value + 4] value + 5] value + 6] value + 7] value
==> 12
[[^[[[3] value + 4] value + 5] value + 6] value + 7] value
==> 18
[^[[[[3] value + 4] value + 5] value + 6] value + 7] value
==> 25
^[[[[[3] value + 4] value + 5] value + 6] value + 7] value
==> 25
| aBlock |
Core.Transcript clear.
aBlock :=
        [| endTime |
        endTime := Core.Time fromSeconds: Core.Time now asSeconds + 5.
        [| currentTime |
        currentTime := Core.Time now.
        currentTime >= endTime ifTrue: [^nil].
        Core.Transcript
            show: currentTime printString;
            cr.
        (Core.Delay forSeconds: 1) wait] repeat].
aBlock value.
Core.Transcript
    show: Core.Date today printString;
    cr
7:38:59 pm
7:39:00 pm
7:39:01 pm
7:39:02 pm
7:39:03 pm
| aBlock |
Core.Transcript clear.
aBlock :=
        [| endTime currentTime |
        endTime := Core.Time fromSeconds: Core.Time now asSeconds + 5.
        [currentTime := Core.Time now.
        currentTime >= endTime] whileFalse: 
                    [Core.Transcript
                        show: currentTime printString;
                        cr.
                    (Core.Delay forSeconds: 1) wait]].
aBlock value.
Core.Transcript
    show: Core.Date today printString;
    cr
7:39:44 pm
7:39:45 pm
7:39:46 pm
7:39:47 pm
7:39:48 pm
June 29, 2009
| aBlock |
Core.Transcript clear.
aBlock :=
        [:exit |
        | endTime |
        endTime := Core.Time fromSeconds: Core.Time now asSeconds + 5.
        [| currentTime |
        currentTime := Core.Time now.
        currentTime >= endTime ifTrue: [exit value].
        Core.Transcript
            show: currentTime printString;
            cr.
        (Core.Delay forSeconds: 1) wait] repeat].
aBlock valueWithExit.
Core.Transcript
    show: Core.Date today printString;
    cr
7:40:13 pm
7:40:14 pm
7:40:15 pm
7:40:16 pm
7:40:17 pm
June 29, 2009
| aSignal aBlock |
Core.Transcript clear.
aSignal := Core.Signal new.
aBlock :=
        [| endTime |
        endTime := Core.Time fromSeconds: Core.Time now asSeconds + 5.
        [| currentTime |
        currentTime := Core.Time now.
        currentTime >= endTime ifTrue: [aSignal raise].
        Core.Transcript
            show: currentTime printString;
            cr.
        (Core.Delay forSeconds: 1) wait] repeat].
aBlock on: aSignal do: [:exception | ].
Core.Transcript
    show: Core.Date today printString;
    cr
7:40:36 pm
7:40:37 pm
7:40:38 pm
7:40:39 pm
7:40:40 pm
June 29, 2009

プログラム制御構造

分岐

anObject ifNil: ["不定のときの処理"]
| anObject |
Core.Transcript clear.
(anObject := nil)
    ifNil: [Core.Transcript nextPutAll: anObject printString].
Core.Transcript flush
anObject ifNotNil: ["不定ではないときの処理"]
| anObject |
Core.Transcript clear.
(anObject := 123)
    ifNotNil: [Core.Transcript nextPutAll: anObject printString].
Core.Transcript flush
anObject ifNotNil: [:it | "不定ではないときの処理"]
Core.Transcript clear.
123 ifNotNil: [:it | Core.Transcript nextPutAll: it printString].
Core.Transcript flush
anObject ifNil: ["不定のときの処理"] ifNotNil: ["不定ではないときの処理"]
| anObject |
Core.Transcript clear.
(anObject := 123)
    ifNil: [Core.Transcript nextPutAll: anObject printString]
    ifNotNil: [Core.Transcript nextPutAll: anObject printString].
Core.Transcript flush
anObject ifNil: ["不定のときの処理"] ifNotNil: [:it | "不定ではないときの処理"]
| anObject |
Core.Transcript clear.
(anObject := 123)
    ifNil: [Core.Transcript nextPutAll: anObject printString]
    ifNotNil: [:it | Core.Transcript nextPutAll: it printString].
Core.Transcript flush
aBoolean ifTrue: ["真のときの処理"]
Core.Transcript clear.
(Dialog confirm: 'Are you happy?')
    ifTrue: [Core.Transcript nextPutAll: 'good'].
Core.Transcript flush
aBoolean ifFalse: ["偽のときの処理"]
Core.Transcript clear.
(Dialog confirm: 'Are you happy?')
    ifFalse: [Core.Transcript nextPutAll: 'poor'].
Core.Transcript flush
aBoolean ifTrue: ["真のときの処理"] ifFalse: ["偽のときの処理"]
Core.Transcript clear.
(Dialog confirm: 'Are you happy?')
    ifTrue: [Core.Transcript nextPutAll: 'good']
    ifFalse: [Core.Transcript nextPutAll: 'poor'].
Core.Transcript flush
aBoolean and: ["真のときの処理"]
Core.Transcript clear.
(Dialog confirm: 'Are you happy?') and: 
        [Core.Transcript nextPutAll: 'good'.
        true yourself].
Core.Transcript flush
aBoolean or: ["偽のときの処理"]
Core.Transcript clear.
(Dialog confirm: 'Are you happy?') or: 
        [Core.Transcript nextPutAll: 'poor'.
        false yourself].
Core.Transcript flush

繰り返し

anInteger timesRepeat: ["繰り返し処理"]
Core.Transcript clear.
5 timesRepeat: 
        [Core.Transcript
            nextPutAll: Core.Time now printString;
            cr.
        (Core.Delay
            untilMilliseconds: (Core.Time millisecondClockValue + 1000 truncateTo: 1000))
                wait].
Core.Transcript flush
anInterval do: [:each | "繰り返し処理"]
Core.Transcript clear.
(1 to: 10 by: 2) do: 
        [:each |
        Core.Transcript
            nextPutAll: each printString;
            cr].
Core.Transcript flush
aCollection do: [:each | "繰り返し処理"]
Core.Transcript clear.
#(11 22 33 44 55) do: 
        [:each |
        Core.Transcript
            nextPutAll: each printString;
            cr].
Core.Transcript flush
aCollection select: [:each | "繰り返し処理(選択条件)"]
Core.Transcript clear.
((1 to: 10 by: 1) select: [:each | each even])
    do: 
        [:each |
        Core.Transcript
            nextPutAll: each printString;
            cr].
Core.Transcript flush
aCollection reject: [:each | "繰り返し処理(排除条件)"]
Core.Transcript clear.
((1 to: 10 by: 1) reject: [:each | each even])
    do: 
        [:each |
        Core.Transcript
            nextPutAll: each printString;
            cr].
Core.Transcript flush
aCollection collect: [:each | "繰り返し処理(収集処理)"]
Core.Transcript clear.
((1 to: 10 by: 2) collect: [:each | each * 100])
    do: 
        [:each |
        Core.Transcript
            nextPutAll: each printString;
            cr].
Core.Transcript flush
aCollection detect: [:each | "繰り返し処理(検出条件)"]
[| aValue |
Core.Transcript clear.
aValue := (1 to: 10) detect: [:each | each factorial = 120].
Core.Transcript
    nextPutAll: aValue printString;
    cr.
Core.Transcript flush]
        value
aCollection detect: [:each | "繰り返し処理(検出条件)"] ifNone: ["検出されなかった時の処理"]
[| aValue |
Core.Transcript clear.
aValue := (1 to: 10) detect: [:each | each factorial = 120] ifNone: [nil].
Core.Transcript
    nextPutAll: aValue printString;
    cr;
    flush]
        value
aCollection findFirst: [:each | "繰り返し処理(検出条件)"]
[| anIndex |
Core.Transcript clear.
anIndex := (10 to: 100 by: 10)
            findFirst: [:each | 44 <= each and: [each <= 66]].
Core.Transcript
    nextPutAll: anIndex printString;
    cr;
    flush]
        value
aCollection findLast: [:each | "繰り返し処理(検出条件)"]
[| anIndex |
Core.Transcript clear.
anIndex := (10 to: 100 by: 10)
            findLast: [:each | 44 <= each and: [each <= 66]].
Core.Transcript
    nextPutAll: anIndex printString;
    cr;
    flush]
        value
aCollection inject: anObject into: [:object :each | "繰り返し処理(注入処理)"]
[| aValue |
Core.Transcript clear.
aValue := (1 to: 10) inject: 0 into: [:total :each | total + each].
Core.Transcript
    nextPutAll: aValue printString;
    cr;
    flush]
        value
firstCollection with: secondCollection do: [:first :second | "繰り返し処理(並び替え条件)"]
[| anArray |
Core.Transcript clear.
anArray := #(111 222 333 444 555).
(1 to: anArray size) with: anArray
    do: 
        [:index :each |
        Core.Transcript
            nextPutAll: index printString;
            nextPutAll: ': ';
            nextPutAll: each printString;
            cr].
Core.Transcript flush]
        value
["繰り返し条件"] whileTrue
[| expiredTime currentTime |
Core.Transcript clear.
expiredTime := Core.Time millisecondClockValue + 5000.
[| aBoolean |
(aBoolean := (currentTime := Core.Time millisecondClockValue) < expiredTime)
    ifTrue: 
        [Core.Transcript
            nextPutAll: Core.Time now printString;
            cr.
        (Core.Delay untilMilliseconds: (currentTime + 1000 truncateTo: 1000)) wait].
aBoolean yourself]
        whileTrue.
Core.Transcript flush]
        value
["繰り返し条件"] whileTrue: ["繰り返し処理"]
[| expiredTime currentTime |
Core.Transcript clear.
expiredTime := Core.Time millisecondClockValue + 5000.
[(currentTime := Core.Time millisecondClockValue) < expiredTime] whileTrue: 
        [Core.Transcript
            nextPutAll: Core.Time now printString;
            cr.
        (Core.Delay untilMilliseconds: (currentTime + 1000 truncateTo: 1000)) wait].
Core.Transcript flush]
        value
["繰り返し条件"] whileFalse
[| expiredTime currentTime |
Core.Transcript clear.
expiredTime := Core.Time millisecondClockValue + 5000.
[| aBoolean |
(aBoolean := (currentTime := Core.Time millisecondClockValue) >= expiredTime)
    ifFalse: 
        [Core.Transcript
            nextPutAll: Core.Time now printString;
            cr.
        (Core.Delay untilMilliseconds: (currentTime + 1000 truncateTo: 1000)) wait].
aBoolean yourself]
        whileFalse.
Core.Transcript flush]
        value
["繰り返し条件"] whileFalse: ["繰り返し処理"]
[| expiredTime currentTime |
Core.Transcript clear.
expiredTime := Core.Time millisecondClockValue + 5000.
[(currentTime := Core.Time millisecondClockValue) >= expiredTime] whileFalse: 
        [Core.Transcript
            nextPutAll: Core.Time now printString;
            cr.
        (Core.Delay untilMilliseconds: (currentTime + 1000 truncateTo: 1000)) wait].
Core.Transcript flush]
        value
aCollection do: [:each | "繰り返し処理"] separatedBy: ["繰り返しの間の処理"]
Core.Transcript
    clear;
    nextPutAll: '<'.
#(111 222 333 444 555)
    do: [:each | Core.Transcript nextPutAll: each printString]
    separatedBy: [Core.Transcript space].
Core.Transcript
    nextPutAll: '>';
    cr;
    flush

再帰

| aBlock |
aBlock := ["前処理"
           aBlock value. "再帰処理"
           "後処理"].
aBlock value
| aBlock |
aBlock := [:n | n <= 0 ifTrue: [0] ifFalse: [n + (aBlock value: n - 1)]].
aBlock value: 10

巻き戻し

["本処理"] ensure: ["後処理"]
| anImage aFilename aStream |
anImage := JunImageUtility fromDisplay: (0 @ 0 extent: 800 @ 600).
aFilename := 'zzz.jpg' asFilename.
aStream := JunJpegImageStream on: aFilename writeStream.
[Cursor write showWhile: [aStream nextPutImage: anImage]]
    ensure: [aStream close]
JunControlUtility assert: ["前処理"] do: ["本処理"] ensure: ["後処理"]
| aFilename anImage |
aFilename := 'zzz.jpg' asFilename.
JunControlUtility
    assert: [JunJpegImageStream on: aFilename readStream]
    do: [:aStream | Cursor write showWhile: [anImage := aStream nextImage]]
    ensure: [:aStream | aStream close].
JunImageDisplayModel show: anImage

例外

aSignal handle: [:exception | "例外処理"] do: ["本処理"]
Object errorSignal
    handle: 
        [:exception |
        Core.Transcript
            clear;
            nextPutAll: exception messageText asString;
            cr;
            flush]
    do:
        [3 seconds wait.
        self error: 'Unexpected error']
["本処理"] on: aSignal do: ["例外処理"]
[3 seconds wait.
self error: 'Unexpected error']
    on: Object errorSignal
    do: 
        [:exception |
        Core.Transcript
            clear;
            nextPutAll: exception messageText asString;
            cr;
            flush]

並行

"親処理"
["子処理"] fork.
"親と子が並行に動作"
| aBlock |
aBlock :=
        [:aString |
        | expiredTime currentTime |
        expiredTime := Core.Time millisecondClockValue + 5000.
        [(currentTime := Core.Time millisecondClockValue) < expiredTime] whileTrue: 
                [Core.Transcript
                    nextPutAll: aString;
                    nextPutAll: Core.Time now printString;
                    cr;
                    flush.
                (Core.Delay untilMilliseconds: (currentTime + 1000 truncateTo: 1000)) wait]].
Core.Transcript clear.
[aBlock value: 'child: '] fork.
[aBlock value: 'parent: '] value
| aProcess |
"親処理"
aProcess := ["子処理"] newProcess.
aProcess resume.
"親と子が並行に動作"
| aBlock aProcess |
aBlock :=
        [:aString |
        | expiredTime currentTime |
        expiredTime := Core.Time millisecondClockValue + 5000.
        [(currentTime := Core.Time millisecondClockValue) < expiredTime] whileTrue: 
                [Core.Transcript
                    nextPutAll: aString;
                    nextPutAll: Core.Time now printString;
                    cr;
                    flush.
                (Core.Delay untilMilliseconds: (currentTime + 1000 truncateTo: 1000)) wait]].
Core.Transcript clear.
aProcess := [aBlock value: 'child: '] newProcess.
aProcess resume.
[aBlock value: 'parent: '] value

約束

"親処理"
["子処理"] promise.
"親と子が並行に動作"
| aBlock |
aBlock :=
        [:aString |
        | expiredTime currentTime |
        expiredTime := Core.Time millisecondClockValue + 5000.
        [(currentTime := Core.Time millisecondClockValue) < expiredTime] whileTrue: 
                [Core.Transcript
                    nextPutAll: aString;
                    nextPutAll: Core.Time now printString;
                    cr;
                    flush.
                (Core.Delay untilMilliseconds: (currentTime + 1000 truncateTo: 1000)) wait]].
Core.Transcript clear.
[aBlock value: 'child: '] promise.
[aBlock value: 'parent: '] value
| aPromise |
"親処理"
aPromise := ["子処理"] promise.
"親と子が並行に動作"
aPromise value "親が子を待ち合わせ"
| aPromise aBlock |
aPromise := nil.
aBlock :=
        [:aString |
        | expiredTime limitTime currentTime |
        expiredTime := Core.Time millisecondClockValue + 5000.
        limitTime := expiredTime - 3000.
        [(currentTime := Core.Time millisecondClockValue) < expiredTime] whileTrue: 
                [currentTime > limitTime ifTrue: [aPromise ifNotNil: [:it | it value: nil]].
                Core.Transcript
                    nextPutAll: aString;
                    nextPutAll: Core.Time now printString;
                    cr;
                    flush.
                (Core.Delay untilMilliseconds: (currentTime + 1000 truncateTo: 1000)) wait]].
Core.Transcript clear.
aPromise := [aBlock value: 'child: '] promise.
aPromise value.
[aBlock value: 'parent: '] value

継続

反復:IS (Iteration Style)
| factorial |
factorial :=
        [:n |
        | a |
        (n isInteger not or: [n negative]) ifTrue: [^self error: 'boo!'].
        a := 1.
        (1 to: n) do: [:i | a := a * i].
        a yourself].
factorial value: 10
再帰:RS (Recursion Style)
| factorial |
factorial :=
        [:n |
        | a |
        (n isInteger not or: [n negative]) ifTrue: [^self error: 'boo!'].
        a := n = 0 ifTrue: [1] ifFalse: [(factorial value: n - 1) * n].
        a yourself].
factorial value: 10
継続:CPS (Continuation Passing Style)
| factorial |
factorial :=
        [:n :continuation |
        (n isInteger not or: [n negative]) ifTrue: [^self error: 'boo!'].
        n = 0
            ifTrue: [continuation value: 1]
            ifFalse: [factorial value: n - 1 value: [:a | continuation value: a * n]].
        n halt].
factorial value: 10 value: [:a | ^a]
継続(コンティニュエーション・パッシング・スタイル)を用いて階乗計算を行うプログラムの実行過程を、
プログラム(ソースコード)として生成し、整形し、実行し、その結果を獲得するプログラム。
| anInteger anInterval aStream aCode aTree aResult |
anInteger := 10.
anInterval := 0 to: anInteger.
aStream := String new writeStream.
aCode :=
        [anInterval do:
                [:n |
                | s |
                s := n printString.
                aStream nextPutAll: '| con' , s , ' | con' , s , ' := '.
                n < anInterval last
                    ifTrue: [aStream nextPutAll: '[:a' , s , ' | ']
                    ifFalse: [aStream nextPutAll: '[:a | ^a]. ']].
        anInterval reverse do:
                [:n |
                | s |
                s := n printString.
                aStream nextPutAll: 'con' , s , ' value: '.
                n > anInterval first
                    ifTrue:
                        [| r |
                        r := (n - 1) printString.
                        aStream nextPutAll: 'a' , r , ' * ' , s , ']. ']
                    ifFalse: [aStream nextPutAll: '1']].
        aStream contents]
                ensure: [aStream close].
aTree := Refactory.Browser.RBParser parseExpression: aCode.
aCode := aTree formattedCode.
aResult := Kernel.Compiler evaluate: aCode.
Core.Transcript
    clear;
    nextPutAll: aCode;
    cr;
    nextPutAll: '==> ';
    nextPutAll: aResult printString.
^aResult
トランスクリプトには次のように出力されます。
conNがfactorialNのコンティニュエーションを意味しています。
| con0 |
con0 :=
        [:a0 |
        | con1 |
        con1 :=
                [:a1 |
                | con2 |
                con2 :=
                        [:a2 |
                        | con3 |
                        con3 :=
                                [:a3 |
                                | con4 |
                                con4 :=
                                        [:a4 |
                                        | con5 |
                                        con5 :=
                                                [:a5 |
                                                | con6 |
                                                con6 :=
                                                        [:a6 |
                                                        | con7 |
                                                        con7 :=
                                                                [:a7 |
                                                                | con8 |
                                                                con8 :=
                                                                        [:a8 |
                                                                        | con9 |
                                                                        con9 :=
                                                                                [:a9 |
                                                                                | con10 |
                                                                                con10 := [:a | ^a].
                                                                                con10 value: a9 * 10].
                                                                        con9 value: a8 * 9].
                                                                con8 value: a7 * 8].
                                                        con7 value: a6 * 7].
                                                con6 value: a5 * 6].
                                        con5 value: a4 * 5].
                                con4 value: a3 * 4].
                        con3 value: a2 * 3].
                con2 value: a1 * 2].
        con1 value: a0 * 1].
con0 value: 1
==> 3628800

for VisualWorks 7.7 with Jun780


Updated: 2015/11/08 (Created: 2008/06/28) KSU AokiHanko