■
class Prototype def initialize @_method_list = {} end def _my_eval(*_str, &block) _s = (class << self; self; end) if block_given? _s.module_eval &block else _s.module_eval _str[0] end end def method_missing( _name, *_args) if _name.to_s =~ /([^=]+)=/ # 代入? _name_ = $1 _my_eval %- def #{_name_}() @#{_name_} end def #{_name_}=(_val) if _val.kind_of? Proc @_method_list[ "#{_name_}" ] = _val _my_eval { define_method( :#{_name_}, _val) } else if @_method_list[ "#{_name_}" ] @_method_list[ "#{_name_}" ] = nil _my_eval { define_method( :#{_name_}) { @#{_name_}} } end @#{_name_} = _val end end - _x = _args _x = _args[0] if _x.kind_of? Array and _args.size==1 send( _name, _x) # _name_ = *_args else p "method_missing: #{_name.to_s}, #{_args}" if $DEBUG nil end end def get_method _name @_method_list[ _name ] end end
a = Prototype.new p a.x # => nil a.x = 99 p a.x # => 99 a.x = "foo" p a.x # => "foo" p "---" b = a.dup b.y = "bar" y = "global y" b.x = lambda() { self.y } # selfがないと上のyを参照してしまう p b.x # => "bar" p a.x # => "foo" p "---" a.y = "buz" a.x = b.get_method("x") p a.x # => "buz"
javascriptのソースを移植するために作ってみたんだけれど,javascriptってこんな感じなの?
追記:dupじゃなくてcloneにしないと特異メソッドがコピーされない.なるほど.
俺言語暫定終了
fun main() { print( fact(5)) // => 120 a = Point( 1, 2) a.pn() // => 1, 2 a.x = 4 a["pn"]() // => 4, 2 c = a c.y = 99 print( a.y) // => 99 書き換わってる… } fun Point(u,v) { var obj = {.x = u, .y = v} obj.pn = fun { print(x); print(y) } // fun obj.pn {...} も fun obj["pn"] {...} も等価 return obj } fun fact(n) { (n==0)? 1: n * fact(n-1) }
作ろうと思っていたものは大体出来たけど,達成感よりもまだやっと1合目かという気分.おかしいな.結構いい感じになるかと思ったんだけど.
コレクションを操作する命令/関数が全然ない所為か?eachとかmapとか
俺言語とセミコロン
セミコロンを省略できるようにと,パーサと悪戦苦闘をしたあげく,スキャナ側で不要な改行を削るようにしてみたのだが,どうにも上手くいかなかったので,RHGのパーサの部分を読んでみた.
スキャナで処理するところまではよかったのに,その後の爪が甘かったらしい.
基本的にはセミコロンを省いても動作するようになった.
いまのところ,カッコのバランスはみていないので
a = ( 5 ) // ok: a = (5);と等価 b = ((5 + 2) * 3) // ng: b = ((5; +2)*3); と解釈される
となってしまう.
'('は文の最後(の1つ前の終端記号)にならないので,改行はスキャナで削除されるけど,'5'は文の最後になりえるので,改行がパーサに渡されてしまう.
'('と対応する')'を数えれば式の途中であることは自明なので,改行を取り除くことが出来る…ということをrubyはやっているらしい.
四則演算とかのネット上によくあるパーサの説明と違って,本物のソースは勉強になる.
俺言語とクロージャ
ケース1:
fun main() { var f; m = 1; { var m = 2; f = fun() { print( m); var m = 3; // このmは無名関数のローカル変数 print( m); }; } f(); // => 2, 3 print(m); // => 1 }
ケース2:
fun main() { var f; var m = 1; { f = fun() { print( m); }; var m = 2; // このmは無名関数と同じスコープ } f(); // => 2 }
ケース1は予想通りの挙動だけど,2が気持ち悪い.fに無名関数を代入している時点では,関数の中身を評価していないので,mが同じスコープに存在していないことを知らない.
擬陽性からの回復
ウィルス疑惑 - ロバの耳で書いた,TCCのウイルス疑惑が気づいたら直ってた.
TCCのソース読みも再開したいところ.
inject
class Array def sum() inject{|x,i| x+i } end end def f(n) n % 7 end def g(n) # 3*f((1..7).inject{|x,k| x+k**n}) 3*f((1..7).map{|k| k**n}.sum) end p f(10) #=> 3 p g(6) #=> 18
injectがいるのが気持ち悪く感じる体になってしまった.合計を求めるのに中間変数を見たくない.
とはいえ,これはさすがにやりすぎだと感じる.
class Array def sum(nodata=nil) return nodata if empty? return self[0] if size==1 self[0] + self[1..-1].sum end end p [1,2,3,4].sum(0) #=> 10