ぐる式 (貳) より引っ越し作業中.未完.

2007年9月8日土曜日

Squeak: シンボルからブロック生成

asBlock

某 ML での話題が [SML 7312] ブロック生成のメタプログラミング として表に出て来た.んで,その VW 用のソースを Squeak で動かす.元はメソッドが三つだけだが, Squeak では 書き換える必要があるのは一個だけ SequenceableCollection>>with:collect: はオリジナルのダン・インガルス大先生のがけっきょく同じことをやってるので変更する必要はないので省く.それ以外の asBlockasBlockFor: はフォーマットしただけに過ぎない.ほかに, Squeak には fold: メソッドがないのでソレも inject:into: を参考にして追加し,ユニット・テストも加えた.ほとんど他人の褌で何とやらである.

  1. BlockGeneration.1.cs
  2. BlockGeneration-Tests.1.cs

なんかサーバ側で拡張子が cs から変更されてるけど (笑).

以下,実行例.

	(0 to: 9) select: #even asBlock		==>  #(0 2 4 6 8 ).	(0 to: 9) reject: #even asBlock		==>  #(1 3 5 7 9 ).	(0 to: 9) collect: #even asBlock		==>  #(true false true false true false true false true false ).	#('asaoka' 'aoki' ) collect: #size asBlock		==>  #(6 4 ).	#(0 2 4 6 8 ) with: #(1 3 5 7 9 ) collect: #@ asBlock		==>  {0 @ 1. 2 @ 3. 4 @ 5. 6 @ 7. 8 @ 9}.	#(0 2 4 6 8 )			with: #(1 3 5 7 9 )			collect: (#x:y: asBlockFor: Point))		==>  {0 @ 1. 2 @ 3. 4 @ 5. 6 @ 7. 8 @ 9}.	#(0 2 4 6 8 ) fold: #+ asBlock		==>  20.	#(1 3 5 7 9 ) fold: #* asBlock		==>  945.	(1 to: 6) fold: #* asBlock		==>  720.	#('Hello ' 'world' '!') fold: #, asBlock		==>  'Hello world!'.	#(12 21 -19 ) inject: 9999 into: #min: asBlock		==>  -19.	#(12 21 -19 ) inject: -9999 into: #max: asBlock		==>  21.

テストを走らせてみたのは Squeak3.9-final-7067, Squeak3.10beta.7143, Squeak3.10beta.7143 + New Compiler 272 + New Parser 4 + AST 150 + SmaCC 13 の三つ.

デコンパイルしてみると.

#size asBlock method decompileString "BlockContext" 'DoIt	| t2 |	^ [:t1 | 	t2 := Array new: 0.	t1 perform: #size withArguments: t2]' "BlockClosure" 'DoIt: t1 	| t2 |	t2 := Array new: 0.	^ t1 perform: #size withArguments: t2' #@ asBlock method decompileString "BlockContext" 'DoIt	| t3 |	^ [:t1 :t2 | 	t3 := Array new: 1.	t3 at: 1 put: t2.	t1 perform: #@ withArguments: t3]' "BlockClosure" 'DoIt: t1 with: t2 	| t3 |	(t3 := Array new: 1) at: 1 put: t2.	^ t1 perform: #@ withArguments: t3' (#x:y: asBlockFor: Point) method decompileString "BlockContext" 'DoIt	| t3 |	^ [:t1 :t2 | 	t3 := Array new: 2.	t3 at: 1 put: t1.	t3 at: 2 put: t2.	self perform: #x:y: withArguments: t3]' "BlockClosure" 'DoIt: t1 with: t2 	| t3 |	(t3 := Array new: 2) at: 1 put: t1.	t3 at: 2 put: t2.	^ unknown0 perform: #x:y: withArguments: t3'

う〜む (笑).そうそう, New Compiler (旧姓 ClosureCompiler) をインストールして BlockClosure を使うには Preference での設定が必要 (→sumim’s smalltalking-tos - ClosureCompiler).インストールそのものは Package Universe Browser で一発完了なんだけどな.

3 + 4 » Blog Archive » Selectors as Blocks

え〜 Symbol には value: しかないんで,っつ〜のは考えないとしても.

((0 to: 9) select: [:each | #odd value: each]) fold: [:x :y | x perform: #* with: y].

よか

((0 to: 9) select: #odd asBlock) fold: #* asBlock.

の方がブロックが表から見えない分だけ読みやすいと思うんだけど.

Symbol / String 以外に numArgs を実装しているのはブロック系以外に Pragma, CompiledMethod とか.

実際には, Symbolvalue:value: を定義すれば,

((0 to: 9) select: #odd) fold: #*.

で動く.こっちの方が短い (笑).が,パラメータの数を意識してないとダメ.

foldl (+) 0 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10](1 to: 10) inject: 0 into: #+.(1 to: 10) fold: #*.(1 to: 10) fold: #+ asBlock.
#('Hello ' 'Squeak ' 'World!' ) inject: String new into: #,.

0 件のコメント:

コメントを投稿