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
[ツッコミを入れる]