エンジニアのソフトウェア的愛情

または私は如何にして心配するのを止めてプログラムを・愛する・ようになったか

もしもC++プログラマが((Pythonで) 書く (Lisp) インタプリタ)を読んでC++でLispを実装してみたら

タイトルのことですが。

「エンジニアのソフトウェア的愛情」というのは、もちろんキューブリック監督の作品「博士の異常な愛情」のパロディなわけですが。このあいだ、一行紹介の「〜を・愛する・ように〜」のところの点の打ち方が面白いと言われました。

これもまた同映画の正式な邦題「博士の異常な愛情 または私は如何にして心配するのを止めて水爆を・愛する・ようになったか」をそっくりマネたわけなんですけれども、今回それを確認したところ、現在販売されているDVDなどの商品では点がない。どこを探してもやっぱりない。「もしかしてまたなにか勘違いしたか?」と検索を続けてみたら、版元のソニーピクチャーズのサイトの古いページで点ありの記述を見つかりました。版が新しくなったときに変更された模様。


でも。「博士の異常な愛情」がもとネタなのは確かなもの、直接には「岸和田博士の科学的愛情」から拝借したというのが実のところ。

岸和田博士の科学的愛情(1) (ワイドKC)

岸和田博士の科学的愛情(1) (ワイドKC)

閑話休題

Liçpp

そんなわけで。lis.pyをRubyでlis.rbにしてみて、それをHaskellでlis.hsにしてみて、それを今回C++で実装してlis.cppにしてみました。


ここまでの経緯。


今回の成果。

内訳。

main.cpp エントリポイント
parser.cpp/.h パーサ
atoms.cpp/.h インタプリタの実体
functions.cpp/.h 定義済み関数


見てのとおりPythonRubyHaskellと比べてかなり大きくなりました。しかもかなり雑というか、細かいところを省いてもこの大きさ。C++は細部まで手を入れられる言語、とも言えますし、細部まで手を入れないといけない言語、とも言えそうです。

今回、いろいろ学ぶところがあったので、それをまた後日まとめてみます。


実行結果。githubリポジトリにも格納してあるsample.txtをリダイレクトで流し込んでいます。

$ cat sample.txt 
(+ 1 2)
(- 2 3)
(* (+ 3 4) (/ 9 3))
(quote (1 2 3))
(< 1 2)
(> 1 2)
(list 1 2 3)
(car (quote (1 2 3)))
(cdr (quote (1 2 3)))
(cons 1 (quote (2 3)))
(define x2 (lambda (x) (* x 2)))
(x2 10)
(define add (lambda (x y) (+ x y)))
(add 1 10)
(define fact (lambda (n) (if (< n 1) 1 (* n (fact (- n 1))))))
(fact 10)
(define map (lambda (f x) (if (null? x) () (cons (f (car x)) (map f (cdr x))))))
(define plus1 (lambda (x) (+ x 1)))
(map plus1 (quote (1 2 3)))
$ ./liscpp < sample.txt 
lis.cpp> ( + 1 2 ) -> 3
lis.cpp> ( - 2 3 ) -> -1
lis.cpp> ( * ( + 3 4 ) ( / 9 3 ) ) -> 21
lis.cpp> ( quote ( 1 2 3 ) ) -> ( 1 2 3 )
lis.cpp> ( < 1 2 ) -> true
lis.cpp> ( > 1 2 ) -> false
lis.cpp> ( list 1 2 3 ) -> ( 1 2 3 )
lis.cpp> ( car ( quote ( 1 2 3 ) ) ) -> 1
lis.cpp> ( cdr ( quote ( 1 2 3 ) ) ) -> ( 2 3 )
lis.cpp> ( cons 1 ( quote ( 2 3 ) ) ) -> ( 1 2 3 )
lis.cpp> ( define x2 ( lambda ( x ) ( * x 2 ) ) ) -> lambda ( x ) ( * x 2 )
lis.cpp> ( x2 10 ) -> 20
lis.cpp> ( define add ( lambda ( x y ) ( + x y ) ) ) -> lambda ( x y ) ( + x y )
lis.cpp> ( add 1 10 ) -> 11
lis.cpp> ( define fact ( lambda ( n ) ( if ( < n 1 ) 1 ( * n ( fact ( - n 1 ) ) ) ) ) ) -> lambda ( n ) ( if ( < n 1 ) 1 ( * n ( fact ( - n 1 ) ) ) )
lis.cpp> ( fact 10 ) -> 3628800
lis.cpp> ( define map ( lambda ( f x ) ( if ( null? x ) ( ) ( cons ( f ( car x ) ) ( map f ( cdr x ) ) ) ) ) ) -> lambda ( f x ) ( if ( null? x ) ( ) ( cons ( f ( car x ) ) ( map f ( cdr x ) ) ) )
lis.cpp> ( define plus1 ( lambda ( x ) ( + x 1 ) ) ) -> lambda ( x ) ( + x 1 )
lis.cpp> ( map plus1 ( quote ( 1 2 3 ) ) ) -> ( 2 3 4 )

再帰を使って、階乗の計算やmap関数の実装も実現できました。

「いつか読むはずっと読まない」:SFだけでなくてファンタジーもリハビリ

リハビリとか言っておいて、いきなり長編ハードSF方面に振り切ってしまったので、今回はファンタジーものを。

一番最近に読んだファンタジーものはなんだろうと考えてみたら。一昨年に読んだアスプリンの「ドラゴンズ・ワイルド」が一番最近かも。シリーズものながら邦訳第一巻の本書がでた前年に著者が他界してしまい、共著が多かったリン・ナイが続きを書いているとのことですが、邦訳はどうなるだろう。いままで読んできたシリーズものでも邦訳が完結してないのが多いんだよな…。「恐竜惑星(惑星アイリータ調査隊)」とか「ダーコーヴァ年代記」とか「ワイルド・カード」とか…。


今回手にした本は女性作家、女性翻訳家の作品のためか、なんか文体が柔らかいような感じ。ちょっと新鮮。雰囲気は、おなじように女性作家、女性翻訳家の作品「影との戦い」に通じるものがあるかも。

天才時計職人ミカルが両目を奪われて火トカゲ城から帰ってきた。娘のペトラは父の目を取りもどそうと、城に潜入。ところがイングランド大使ディーに正体を見破られ、黙っているかわりにある取引をもちかけられる。ミカルが王子のために作った、天候を支配する時計をこわしてくれというのだ。魔法と陰謀が渦巻く不思議な世界のボヘミアを舞台にした〈クロノス・クロニクル〉第一弾。

「〈クロノス・クロニクル〉第一弾」?
…またシリーズものに手を出してしまった。

ボヘミアの不思議キャビネット (創元推理文庫)

ボヘミアの不思議キャビネット (創元推理文庫)

ドラゴンズ・ワイルド (ハヤカワ文庫FT)

ドラゴンズ・ワイルド (ハヤカワ文庫FT)