IT戦記 このページをアンテナに追加 RSSフィード Twitter

2007-08-24

JavaScript < jQuery < Lisp ?

はじめに

僕は jQueryLisp も触ったことがないので、このエントリが言ってることは間違えてる可能性があります><

もし、「それ違うよ」ってのがあれば指摘してくれると嬉しいです><

そういえば

初めて dankogai さんと会ったときに「S 式とアセンブラは両極端にいながら データ==プログラム というところが同じだ」というようなことを言っていた(気がする)。

データ==プログラムというのは本当にすごい

データとしてプログラムを直接書き換えたりいろいろなことができる。本当にすごい。

もちろん、他の言語でも、リフレクションすることや、変数やプロパティ関数を格納することでそれと似たようなことは可能だ。でもそれは、データ=プログラムとは全然違う。

バイトコード書き換えは似ているが、バイトコードの世界がデータ==プログラムなのであってその言語自体はそうじゃない。でも、バイトコードを直でいじれるのはすごい。

で、 JavaScript は?

JavaScript は残念ながらデータ!=プログラムである。

たとえば、以下のコードがあって

var hoge = function(a, b) {
  return a + b;
};

「この関数の a + b を a - b に変えて」って言われてもそう簡単にはできません><

functioin で囲まれた中身の処理部分はデータではないから。

じゃあ、Lisp なら?
(+ 3 1)

リストの先頭に入っているデータ + を - に変えるだけ。楽勝ですね。

話しは jQuery に移って

jQuery の作者の John Resig さんが以下のようなプレゼンテーションをしていました。

http://www.slideshare.net/jeresig/building-a-javascript-library/

そして、そのスライドの 50 ページ目に以下のようなコードが乗っていました。

$("div.section")
  .find("dt")
    .addClass("section")
    .onclick()
      .next()
        .toggle()
      .end()
    .end()
  .end();

で、これはもう既に JavaScript をベースにした別の言語なのではないかと思ったわけです。

じゃあ、この言語は データ==プログラム か

残念ながら データ==プログラム ではない。

じゃあ、こう変えてみたらどうだろう。
var lang = [
  ['find', 'dt'],
    ['addClass', 'section'],
    ['onclick'],
      ['next'],
        ['toggle'],
      ['end'],
    ['end'],
  ['end']
];

var ctx = $('div.section');

for (var i = 0; i < lang.length; i ++) {
  ctx = lang[i].shift().apply(ctx, lang[i]);
}

おおおお。これならデータ==プログラムな言語ではないのか。

もはや Lisp ではないのか(違

この言語を JS から使えば並列なインターバル処理を簡単に実現することも可能だ。

var prog1 = [..略..];

var prog2 = [..略..];


var ctx1 = $('hoge');
var ctx2 = $('fuga');

setInterval(function() {
  ctx1 = prog1[i].shift().apply(ctx1, page1[i]);
  ctx2 = prog2[i].shift().apply(ctx2, page2[i]);
}, 0);

おおおお。

まとめ

jQuery すげげえええええええええええええええええ!

この辺の話しは Shibuya.JS できっと id:send さんが話してくれます><

yuum3yuum3 2007/08/24 20:58 ×「リファクタリング」 ○「リフレクション」だと思います。

soutarosoutaro 2007/08/24 22:17 たとえば,function(x){ return x+1; }.toString()とすれば関数のソースコードが得られます.このソースコードに対して,「a + b」を「a - b」にする置換を行い,もう一度evalすれば目的は果たせるのではないでしょうか?

amachangamachang 2007/08/24 23:04
>> id:yuum3 間違えてました><直します。ありがとうございました!

>> id:soutaro コメントありがとうございます。はい。たしかに文字列化された関数はプログラムを表したデータと言えますが、僕が言いたかったのはプログラム==データ構造ということであり、もう一度文法を解析しなければならないような文字列は、少し違うかなと思います><

piro_orpiro_or 2007/08/25 01:48 誰か、

Function.prototype.__defineGetter__(’statements’, function() {
if (!this.statements) {
var source = this.toSource();
this._statements = [];
// 中略
}
return this._statements;
});

てなコードを書いてくれれば、JSもLisp風に使えるようになるのかな? と思いました。

soutarosoutaro 2007/08/25 03:40 >もう一度文法を解析しなければならないような文字列は、少し違うかなと

はい.実用上,その差はとても大きいというのには同意します.

一方で「JavaScriptだと『オブジェクト・値』からソースコードを取得できるが,Lispにはそれはできない」という点を指摘したいと思いました.こちらのほうが,はるかに大きな差だと思いますし,この点では「データ=プログラム」,というか「データ(=オブジェクト)⇔プログラム(=ソースコード)」な世界にはJavaScriptの方がかなり近いと思います.

#「プログラム=データ構造」という話ならば,確かに違いますね.すみません.

# と思っていたら,CommonLispには,function-lambda-expressionという関数があるそうです.関数を渡すと,その関数のS式が返ってくるという…負けた…

流浪人流浪人 2007/08/27 10:19 >>javascript、「この関数の a + b を a - b に変えて」って言われてもそう簡単にはできません><
functioin で囲まれた中身の処理部分はデータではないから。
じゃあ、Lisp なら?
(+ 3 1)
リストの先頭に入っているデータ + を - に変えるだけ。楽勝ですね
>>
の意味がわかりません。。。。
比較が変わってるのは意図があるのでしょうか?
両方ともfuncitonで囲まれた例題を出すべきだと思います。
なぜ functionであるa + b を a - bに変える。という行為が、lispでは 3 + 1 という直値になっているのでしょうか?

しきりに「すごい」と言われても何がすごいのかさっぱりです。

amachangamachang 2007/08/27 11:03 流浪人さん
コメントありがとうございます。たしかに言われてみればそうでした。

(define hoge (lambda (a b) (+ a b)))

これでいいですか?

amachangamachang 2007/08/27 12:21 流浪人さん
本当にできるのかちょっと Lisp を勉強してやってみました。

> (define hogedata ’(lambda (a b) (+ a b)))
> (define hoge (eval hogedata ’()))
> (set! (car (car (cdr (cdr hogedata)))) ’-)
> (define hoge (eval hogedata ’()))

で出来るのかなあ?たぶん。

流浪人流浪人 2007/08/27 13:06 ぉぉぉなるほどです。勘違いしてました。
プログラム内でプログラム(データ)を書き換えることが出来るからすごいって意味だったんですね。
ちょっと感動しました><
例題ありがとうございます、試してみまする。

はてなユーザーのみコメントできます。はてなへログインもしくは新規登録をおこなってください。