Archive for June, 2007

Practional Functional Programming

Posted by on Tuesday, 5 June, 2007

とかいう本を誰かが Oreilly で書けばいいと思うよ。

……などと思った comp.lang.functional のスレッド。 practitioners むけの関数型プログラミングの本はないですか? という質問スレッド。

あんましちゃんとは読んでないんだけど、挙げられている本のメモ。

Ml for the Working Programmer

OCaml for scientists

Foundation of F#

Programming in Standard ML by Robert Harper

どうも Practical OCaml って本もあるみたいなんですが、これはだめなのかな(amazon.comのカスタマーレビューが星1つ半だけど)。

ところで、『ML for working programmer』って、そういう文脈で良書かなあというのは、ちょっと疑問。いや持ってるだけでちゃんとは読んでなくて(特に後ろの方は)、しかしざっと眺めた範囲では確かに読むとMLのことはよくわかるようになるようには感じられるものの、最終的に「Writing Interpreters for the λ-Calculus」とか「A Tactical Theorem Prover」とか、 working programmer ってそんなことするっけ?みたいな章題が並ぶんですよね。これらはあくまでも例題で、こういったトピックを通じて大規模な ML プログラムを書くことが学べるのかもしれないんですけど……。

日本語の本だと『入門OCaml』かな。

タイトルは「入門」ですが、入門的な内容はかなり割り切られていて、 OCaml を学びはじめたいという人にはまるっきり向いてないと思いますが、ガッコの授業で ML とか Haskell とかくらいはやったけど実際どうなの使えんの?みたいな人にはいいかも。多相バリアントで幽霊型な話とか見たときにはおったまげました。本当の入門者は五十嵐先生のObjective Caml 入門と合わせ技がいいんじゃないかと思います。

あと、こういう文脈では、夏に出るっていうGaucheプログラミングにも期待、かもね。

ただまあ、そうは言ってもなかなか理想的な本は見つからない状況で、なぜかと問うにまだまだぜんぜんニッチだからなんだよね。関数プログラミングというのは一般的にはようやく「そんなものもあるらしい」というのが知ってる人だけ知っている、一部の大卒の人間もそういえば授業でやったよなあ、とかいったレベルで、したがって書籍としても「それはこういうものなのです」という教科書が求められている。……少なくとも、そのような現状認識なんじゃないかと思うのだな。でもそろそろもうちょっと……と言いたい人が増えてきつつあるというのが、こういうスレッドが立った証拠なんじゃないかと思うわけであり、そんなわけで冒頭に結びつくとまあそういう次第です。


がんだむ

Posted by on Monday, 4 June, 2007

「だぶるおー」なる新作があるらしいが、日本SF新人賞なアレを連想した人は意外と多くはなかったらしい。キカイダーの方がメジャーだった。言われてみりゃそりゃそうだが。

やっぱり、いかにしょーもないネタでも、「すると何か、主人公は公務員でビームライフル一発打つたびに管理職から「予算がどうしたこうした」と文句をつけられるのか」くらいはもっと迅速に言った方がよかったか。

# よかーない


RubyKaigi不参加

Posted by on Sunday, 3 June, 2007

9日に RubyKaigi というのがありまして、チケットまで購入しといたんですが諸般の事情で参加を見合わせることにしました。

てなわけで、チケットが余ってしまったんですが、いまさらながら欲しい人とかいますか。

あ、同じ理由でLL魂もたぶん不参加の予定。こっちはチケットも買いません。


円城塔『Self-Reference ENGINE』

Posted by on Sunday, 3 June, 2007

Self-Reference ENGINE

ここ最近、SFファンのあいだで「黄色いヤツ」という渾名で囁かれていた、ハヤカワJコレクションの最新刊。

傑作。

人類を遥かに越える巨大知性体群が綾なす、過去改変、時空の乱れなどの演算戦。人間の理解を絶したそれらを、互いに矛盾するように見える20の断片で描写する。

というと、たとえばイーガンのように理解を絶してわけがわからん「凄さ」のある作品なのかなあ、というとさにあらず。そのような難解さはなく、むしろとってもわかりやすい。自分がさっぱり理解できていないということが極めて明瞭に理解される。それにまた、円城塔が描く理解を絶した世界の演算戦はどちらかというとSFファンとかがしゃべるバカ話に似て、バカバカしく笑えてしまう。

まあ、その笑いにはいささかの教養が必要な面も垣間見えて、そのようなペダンティックな側面に嫌悪感を感じる人もいると思うけれど……ま、そういう感想はそういう人に任せよう。とにかく愉快で笑えて、いやおもろかった。それに、教養のある方が笑えるジョークもあるだろうけど、なくったって充分に楽しめる。

飛浩隆の「爆笑ソラリスジョーク集」という指摘があまりにも的確すぎて、ほかの人の感想のすべてを無化してしまっていると思いました。


Haskell ではリスト内包表記って使ったことないんだよなー

Posted by on Saturday, 2 June, 2007

Rubyでリスト内包表記 を見て「そりゃないだろう」とちょっとしたコメントを付しました。

「そりゃないだろう」の配分は「正規表現かよ!」が4で「文字列かよ!」が6くらいかなあ。

後者から。言語内言語を文字列として保持させておいてあとで何らかの機構でもって評価させる、ってのは個人的には好きになれないんですね。 SQL の埋め込みとかも本当はわたしは好きではない(仕方ないが)。たとえば ActiveRecord みたいなアプローチがベストだとは思わないけれど、たとえば LINQ みたいな方法のがいいでしょうとか思ってしまうわけです。よく知らないけど、 LINQ。

でもってもうひとつ気になるのは、正規表現だということですね。こういうのにはつい正規表現を使いたくなるものなんですが、結果的にあれこれ不思議なルールを追加しないと上手く行かなくなってしまうんじゃないかと思うんですね。それは上手くない。コメントではうっかり「Ripperとか」と口走ってしまいましたが、それはともかく何らかのパーサを使うのがいいと思います。

もっとも、上手に scan を駆使すれば簡単にパースできるような気もするなあ、などとコメントしたあとで思ったのですが、ともかく正規表現でいきなり区切るのは感心しないなあと。

ただケチをつけるばっかりというのもナンですから、と思って「自分だったらどう実装するか」というのを現実逃避がてらあれこれ考えてました。で、最終的に思いついた設計は次みたいな感じ。

class ListComprehension BindVar = Struct.new("BindVar", :symb, :arr) Conditional = Struct.new("Conditional", :symb, :name, :args) def initialize(list) @result_value = list[0] @list = list[1..-1] end def calculate res = [] calculate_inner(res, {}, 0) res end def evaluate(b, v) case v when Symbol b.fetch(v){v} when Conditional receiver = b.fetch(v.symb){raise NameError} args = v.args.map{|e| evaluate(b, e)} receiver.__send__(v.name, *args) when Array v.map{|e| evaluate(b, e)} else v end end def calculate_inner(res, b, i) if i < @list.size then typ, symb, *arr = @list[i] case @list[i] when BindVar arr = @list[i].arr symb = @list[i].symb arr.each do |v| b[symb] = v calculate_inner(res, b, i+1) end b.delete(symb) when Conditional calculate_inner(res, b, i+1) if evaluate(b, @list[i]) end else res.push(evaluate(b, @result_value)) end end private :calculate_inner end class Symbol def <<(arr) ListComprehension::BindVar.new(self, arr) end def method_missing(name, *args) ListComprehension::Conditional.new(self, name, args) end end def lc(arr) ListComprehension.new(arr).calculate end

「うげー」という声が聞こえてきそうですが。しかもこんななりのわりに激しくショボイ。実行例はこんな感じで。

irb(main):001:0> require 'list_comprehension' => true irb(main):002:0> lc [[:x, :y], :x << (1..5), :y << (1..5)] => [[1, 1], [1, 2], [1, 3], [1, 4], [1, 5], [2, 1], [2, 2], [2, 3], [2, 4], [2, 5], [3, 1], [3, 2], [3, 3], [3, 4], [3, 5], [4, 1], [4, 2], [4, 3], [4, 4], [4, 5], [5, 1], [5, 2], [5, 3], [5, 4], [5, 5]] irb(main):003:0> lc [:x, :x << (1..5), :y << [2, 3], :x <= :y] => [1, 1, 2, 2, 3] irb(main):004:0> class Fixnum; def even?() self % 2 == 0; end; end => nil irb(main):005:0> lc [[:x, :y, :x+:y], :x << (1..5), :x.even?, :y << (1..5)] => [[2, 1, 3], [2, 2, 4], [2, 3, 5], [2, 4, 6], [2, 5, 7], [4, 1, 5], [4, 2, 6], [4, 3, 7], [4, 4, 8], [4, 5, 9]]

なぜ even? メソッドが必要なのかというと、 「:x % 2」は ListComprehension::Conditional オブジェクトであり、そこでさらに0と比較しようとするとふつうに比較されちゃうんですね。本気で頑張るならその辺も含めてキッチリと再定義することになるのかな。もう飽きたのでやりませんが。というか、さすがに Symbol#method_missing は影響が強すぎるだろうな。あくまでも「お遊び」の範疇ってことで許してね。

しかし、リスト内包表記ってそれなりの規模のプログラムでは書いたことがない(リストモナドというか ListT は利用経験あり)。まあ、そういうのがあると便利な問題とそうでない問題というのがあり、わたしはもっぱら後者を経験しているのかもしれないけれど、ほかの言語がこぞって取り入れるほど優れた記法かなあ……という気もするのでした。