Quine

自己出力。JavaScriptで書いてみる。

JavaScriptのメタっぽい話といえば eval と toSource がまず思い浮かんだのでこいつらを使ってみることにします。

前者はLispから脈々と続く由緒正しき関数なのに対して後者を実装しているのはJavaScriptぐらいしか知らないんですが、両方あると言語としての面白味がいっそう増しますよね。

eval版

eval(s='document.write("eval(s='"+s.replace(/&/g,"&")+"')")')

73B。クォートの処理がちょっと面倒臭いことになってます。

toSource版

まぁ全体的な方針は上と似たような感じで、よりシンプルに書けます。

(f=(function () {document.write("(f=" + f.toSource() + ")()");}))()

67B。スペースの空け方とか括弧のつけ方とかはFirefoxに合わせました。


というか今の今まで知らなかったんですけど Object.prototype.toSource ってFirefoxとNNにしか無いんですね。デバッグする時に無茶苦茶便利なのに。
他のブラウザだと大体の場合こんな感じで代替できるようです。

ちなみに

toSource版だと s/document\.write/alert/ とかでもきちんと出力しますが、eval版は実体参照に依存してるんでHTMLに書き出さないとダメですね。

そんな感じでした。

追記。

ていうかコレじゃん。賞味期限切れっぽいのでまぁいいか。

てなわけで SpiderMonkey 入れてみました。ふむふむ、readline と print で入出力。

あー。関数をtoStringしたら中身出るんだった。ごっそり短くなりますね。その場合toSourceよりもっと整形されてしまう、と。

js> function f(){return 0}
js> f.toSource()
function f() {return 0;}
js> f.toString()
function f() {
    return 0;
}
js>

あと(f=(function ... ))() とかやるより素直に function f ... f() の方が短くいける。後者の場合はきちんと toSource/toString した時も関数名を補ってくれる。
うーん、細かいとこ覚えないと。

結局、ブラウザに表示させる場合の最短はいまんとこ

function f() { document.write(f, "f()"); }f()

45B。

蛇足。

HyperText Quine 特有の問題。

document.write(document.getElementsByTagName('script')[0].firstChild.textContent)

とか試みてたら、scriptタグの中をHTMLコメントで括ってると中身を取れないことが判明したりとか、URL で javascript:〜 と入力する場合は location からコードを引っぱってこれるかと思ったら気のせいだったりとか。

eval(s='document.write("eval(s="+(q=unescape("%27"))+s+q+")")')

が63Bなんだけど、これはURLから入力しようとすると%27が先に処理されちゃってSyntaxErrorになってまう。