2012-12-05
■ [lisp][javascript] JavaScriptにコンパイルされるCommonLisp風言語、JSLispが面白そう
Lisp Advent Calendar 2012 5日目の記事です。
JavaScript Weeklyから来たメールを眺めていたら、こんなJSデモを見つけた。
作者は https://github.com/6502 の人らしい。見てみると、「JSLisp」というリポジトリが。 またyet anotherなLisp in JSかと思ったが、READMEを見ているとけっこう面白そうな記述が:
- Lisp風言語からJavaScriptにコンパイルする
- CLライクなlisp-2 (ていうか、マクロと関数を同名にできるから厳密にはlisp-3だよと書いてある)
- ネイティブ型はJSの型を使う、listはarray (car/cdrはない)
- defmacro, back quote
- optional引数、keyword引数
- defmethod, defobject
githubのNetworkを見ると、去年の夏からやっていることが分かる。
http://www.jslisp.org/ が公式サイトのようだ。permalinkがない :-( ので個別にリンクが貼れないが、以下のように凝った機能がいろいろあるみたいだ。
- Example : ルービックキューブとかチェスとか六角マップ上の最短距離探索とかあって格好いい
- Reader : リーダマクロがあるらしい
- Static checks : 使われていない変数などのコンパイル時検査
- Generic funcitons : 関数の挙動を条件別に定義できる
- Treeshaker : 使われていない(=main関数から辿れない)関数を除去してコンパイルする
まだあまりドキュメントが無く、残念ながらgit masterのコードは手元でうまく動かせなかったが、なかなか気になる処理系だ。
2012-12-06
■ [rumcoke] RumCokeという言語を作っています
altjs Advent Calendar 6日目の記事です。
「altjs」とは、JavaScriptにコンパイルされる or JavaScriptで実装された言語(処理系)のこと。 僕自身もBiwaSchemeというaltjs処理系を作っていますが、 秋のILC参加中に「もしCoffeeScriptがS式ベースだったら...?」というアイデアを思いついて、RumCokeというLisp風のaltjs言語を作り始めました。
例
Hello Worldです。
(define util (require "util"))(util.puts "Hello, world!")
あと、処理系自身がRumCokeで書かれているので、いまのところそれが一番大きな例です。 このプログラムが、このように変換されます。
RumCokeの特徴
- JSの薄いラッパー言語である
CoffeeScriptやTypeScriptのように、なるべくJSに近いsemanticsを意識しています。
- Scheme風の構文
JSはLisp-1なんで、Schemeが合うかなと思いました。
- Lispだけどリストがない
S式がArrayベースだったらどうなるんだろう?という実験のつもりでしたが、昨日のJSLispがもうやってましたね…。
- 構文木レベルのマクロ
SibilantJSのように文字列レベルのマクロだったり、 LispyScriptのように任意のコードが書けないものと違って、 ちゃんと「構文木を構文木に変換するもの」としてマクロが書けます。*1
- self-hosting
GHCやCoffeeScriptのように、その言語自身で自分の処理系を書くというのをやってみたかったのでした。 手順としては、
- まず素のJSで処理系を書く (このとき、なるべく使用するJSの構文要素を減らすことが望ましい)
- 簡単なRumCokeプログラムをJSに変換できるようにする
- 現在の処理系の1行目を生成するようなRumCokeプログラムを書く
- それをJSに変換できるように処理系を拡張する
- 現在の処理系の2行目を生成するようなRumCokeプログラムを書く
- それをJSに変換できるように処理系を拡張する
- ...
- 現在の処理系の最後の行を生成するようなRumCokeプログラムを書く
- それをJSに変換できるように処理系を拡張する
- さあ、手元には現在の処理系を生成するようなRumCokeプログラムがあるぞ。それを現在の処理系でJSに変換するぞ。
- 生成されたJSは、現在の処理系と全く同じであるはずだ。おめでとう、君はself-hostingに成功した。
- 古い処理系はもう要らないので捨てる。ここからは、RumCoke版の処理系だけをメンテすればいい。
という感じになります。Quineみたいでややこしいけど非常に面白かった。 以降は、処理系に新しい機能を追加する→その機能を使って処理系をリファクタリングする、みたいなループになります。
実装状況
quasiquoteを足そうとしたところで止まっています。そのうち暇を見つけて再開する予定です。
JS言語の作成に関してはいろいろ新たなノウハウを得たので、今月中にまた何か書くかもしれません。
*1 と言って、define-macroを用意してないのでユーザレベルではまだ書けないですが
2012-12-09
■ [esolang] 今年見つけたEsoteric Language関係の記事
Esolang Advent Calendar 2012 9日目の記事です。
昨年同様、今年ブクマしたesolang関係の記事を見返してみようと思います。
- Visual Brainf**k
- Brainf**kの高機能なIDE。
- Magic: the Gathering is Turing Complete
- カードゲーム「Magic: the Gathering」を使ってチューリング・マシンをエミュレートするという話。仕事中に「いまペアプロ中です」と称してカードゲームをできる可能性が?
- 平面上を移動してプログラミングする言語「Explore」作った - 厨二病患者のプログラミング入門
- 二次元言語としてはPietやBefungeなどがありますが、入力をcsvとすることでエクセルをIDEとして使うことが可能に。仕事中に、表計算を行なっているふりをしてesolangで遊べる可能性が(ry
- Brainfuck beware: JavaScript is after you!|Patricio Palladino
- 任意のJavaScriptプログラムを、「()[]{}!+」のみに変換することでBrainf**kみたいな見た目にしてしまうツール。たとえば「+[]」で0が作れたり、「!![]」でtrueを作ってそれを文字列化することで「"t"」「"r"」「"u"」「"e"」を得るなど、JSの仕様を駆使しているようです。
- 関数型言語「ルイズ」
- Lispをトークン置換したEsolang。
- Parenthetic
- 「(」と「)」のみでプログラミングする言語。カッコ中毒のあなたに。構文はLisp/Schemeに似ていて、「()()」がdefine、「(())」が+だそうです。
- 遺伝子をモチーフにした言語「Genomy」を作りました
- 「記述したルールがすべて並列に動く」という制約のもとでプログラムが書けるという話。
以下はesolangs.orgから。(ざっと眺めただけなので、インパクト重視です…)
- BlackCoffin.gif gif画像でプログラミング。Coffinは「棺」で、命令がグレースケール…。喪中ですね。それ以外のピクセルは無視されるため、絵の主線部分にプログラムを埋め込むといった使い方も。
- Ellipsis 「…」の一文字だけで構成されるプログラミング言語。実際にはファイル中に書かれている「…」の個数Nを8進数にして各桁をBrainf**kの文字に変換するため、文字が「…」である必然性は特にない。
- F**k (github) これはひどいw
- huh? これも別の方向でひどい
- Light Pattern 写真の列を入力とする言語。シャッタースピード、絞り、色味(RGB)の差分で命令が決まり、写真の内容は自由。デモを見るとなかなかサイケデリックで面白い
次点。
- Mobius 出力が音声(500/600/700Hzのbeep)。
- Monkeys 猿を操ってプログラミングするらしい。
- Objective LOLCODE I can haz cheezburger的な。
- Semicolon (github) Whitespaceベースですが、reversed semicolonという文字があることに驚いた。
- UniCode Unicodeの矢印記号を使った言語。このアイデアは二次元言語にした方向が面白そう
2012-12-10
■ [ruby][mac] MacRubyでアプリ作ってみた
ニコニコのコメントファイルを表示するだけのアプリを作った。
Retina MBP (13inch) に乗り換えてから、にこぷれの動画再生がカクカクすることがあって困っている。 仕方ないのでflvはVLCで再生して、コメントは別の方法で読むことにしたというわけ。
コメントは単純なXMLなので、Nokogiriで適当にパースすればテキストに変換できる。
# coding: utf-8
require 'nokogiri'
xml = Nokogiri::XML(ARGF.read)
start_time = if (thread = xml.at("thread"))
Time.at(thread[:server_time].to_i)
else
first_chat = xml.at("chat")
raise "chat not found" unless first_chat
Time.at(first_chat[:date].to_i)
end
xml.search("chat").each do |chat|
bsp = false
number = chat[:no]
date = Time.at(chat[:date].to_i)
time = date - start_time
min = time / 60
sec = time % 60
text = chat.text
if text =~ %r{\A/press show .* (.*?) @ (.*)}
bsp = true
text = "<#{$2}> #{$1}"
end
printf "%02d:%02d %s%s\n", min, sec, (bsp ? "" : " "), text
end
これをlvで見るのでもいいのだが、なんとなく単独のウィンドウで表示したくなって、MacRubyを使ってみることにした。
MacRubyについては、以下を上から順にやればだいたい雰囲気がわかる。
ファイルの読み込みAPIなどはRubyがそのまま使えるため、そんなに新しいことを覚えなくていいのがありがたい。 Nokogiriなどgemも使えるようだが、XCode上で使ってみたらなぜかNokogiri::XML("")がCレベルのエラーになったので、とりあえず正規表現に逃げてしまった。
今までだったらSinatra+ブラウザとかで実装してたと思うけど、ものによってはMacRuby使ったほうが簡単そう。
■ [javascript] Ember.jsで遊んでみた
Ember.jsはいわゆるJavaScript MVCフレームワークの一つ。 Ember.jsはその中でもわりとヘビーウェイト・高機能なやつで、モデル間やモデル・ビュー間でデータの依存関係を指定して、片方が変化したら従属する方に勝手に変更が反映されるような機構が備わっている。
という話を聞いて最初に思いついたのが、太陽・地球・月が回転するというデモ。月の位置は地球の位置に依存していて、地球が動いたら月も自動的に移動する、というやつ。 で出来たのがこちら。

リポジトリにはファイルがたくさんあるが、ほとんどはstarter kitに入っているもので、編集したのは app.js と index.htmlだけ。
描画はRaphaelJSを使っている。こういう小さいものを作る時にとても便利なライブラリだ。
ページのホスティングはgithub pagesを使っている。 今回のようにgithub pagesがメインのときは、「git push origin master」せずに「git push origin gh-pages」だけすることで、gh-pagesブランチのみにすると分かりやすくていい。
Ember.jsについては、Ember.js Advent Calendar 2012がとても参考になる。