2007-12-01
■ [javascript] JSONをevalするときは括弧で囲まないといけないらしい?
eval("{}")
これはundefinedだが
eval("({})")
これは Object のインスタンスを返す。
JSONをevalするときは
result = eval("("+json+")");
とするのがセオリーなのかな?(prototype.jsはそうなっている)
■ [ruby][scheme] S式をRubyで手軽に生成する
ちょっと気の利いたWebAPIを作ったとき、フォーマットはJSONかXMLが代表的なんだけど、 ことSchemeから使うのならS式の方が使いやすいのは容易に想像できると思われます。 が、JSONは gem install json すれば JSON.generate(obj) で手軽に生成できるのに対し、 S式はRubyから手軽に生成する方法がありません。困りましたね。
というわけで、S式をRubyで手軽に生成するコードを書いてみましたよ。
sexp.rb:
class Array def to_sexp items = self.map{|item| case item when true "#t" when false "#f" when Array item.to_sexp when Symbol item == :dot ? "." : "'#{item}" when Float if (i = item.infinite?) i == 1 ? "+inf.0" : "-inf.0" else item.to_s end else item.inspect end }.join(" ") ["(", items , ")"].join end end
こんな感じで使えます。
[1, [2, 3], 4].to_sexp #=> "(1 (2 3) 4)"
ドット対の表現がちょっと格好悪いんですけど、手軽さのためと割り切って我慢してください。
[1, :dot, 4].to_sexp #=> '(1 . 4)'
余談
ちなみにS式はリストなので、Rubyの配列とそのまま対応するものではありませんよ。
'(1 2 3) というリストは、無理やり配列で表現すると[1, [2, [3, nil]]] のようになります。 '(1 (2 3) 4)というリストは、[1, [ [2, [3, nil]], [4, nil]] のようになります。 実際にセルの絵を書いてみるとよく分かると思います。
これを手書きするのはかなり辛いので、上のコードではそのへんを割り切った仕様にしてみました (だいたいSchemeの「()」を「[]」に直せばOKなように)。
テスト
RSpecによるテストです。
require 'sexp' describe "sexp" do context "nil" do [].to_sexp.should == "()" end context "single" do [1].to_sexp.should == "(1)" end context "double" do [1, 2].to_sexp.should == "(1 2)" end context "triple" do [1, 2, 3].to_sexp.should == "(1 2 3)" end context "string" do [1, "asdf", 3].to_sexp.should == '(1 "asdf" 3)' end context "nest" do [1, [2, 3], 4].to_sexp.should == '(1 (2 3) 4)' end context "dot pair" do [1, :dot, 4].to_sexp.should == '(1 . 4)' end context "symbol" do [:a, :b, :c].to_sexp.should == "('a 'b 'c)" end context "boolean" do [true, false].to_sexp.should == "(#t #f)" end context "infinity" do [1.0/0, -1.0/0].to_sexp.should == "(+inf.0 -inf.0)" end end