Io って頭おかしいなぁ (いい意味で)
curlyBrackets を知った。
Object curlyBrackets := Object getSlot("method")
foo := {
"aaa" println
}
bar := {a,
"bbb" println
a
}
foo
bar(getSlot("foo")) # method は普通に書くと実行されてしまうので getSlot する必要がある。aaa bbb aaa
ちょっと他の言語に近づいた感じ。
もう少し変態的にしてみる
def foo (mes) {
mes println
}こういうふうに書けるようにするために def メソッドを定義する
def := {
name := call message next name
args := call message next arguments map(i, i name)
meth := call message next next
next := meth next
# cut message chain
meth setNext(nil)
# set the method to caller context
call sender setSlot(name, call sender doMessage(meth))
# set arguments list
call sender getSlot(name) setArgumentNames(args)
# pass to next message
call message setNext(next)
# return the method
call sender getSlot(name)
}# 引数なしなら仮引数省略可
def hogehoge {
"hogehoge" println
}
def piyopiyo (mes) {
mes println
}
# 引数なしなら括弧いらない
hogehoge
hogehoge()
# 引数ありなら括弧必須
piyopiyo("foobar")
Foo := Object clone do (
def foo (mes) {
mes println
}
)
Foo foo("alert")書いた式がどうコンパイルされたかは (前にも書いたけど) 以下のようすればわかる。
Message fromString("def foo (mes) { mes println }") code println
#=> def foo(mes) curlyBrackets(mes println)call message は呼びだしもとのメッセージチェイン (def foo(mes) curlyBrackets(mes println)) をさしてる。call message next は今のチェインの次、すなわち foo(mes) curlyBrackets(mes println) で、call message next name で先頭のメッセージの名前がとれる。メッセージを自分でとって doMessage することでメソッドを作って、呼びだしもとのコンテキストにセットする。setNext でメッセージをチェインを切ったり、スキップしたりする。
実際もっと簡単に
def := method(
ret := Object clone do (
foo := method(
self args := call message arguments map(i, i name)
self
)
curlyBrackets := method(
meth := method() setMessage( call message argAt(0) ) setArgumentNames(args)
context setSlot("foo", meth)
)
)
ret context := call sender
ret
)
def foo () {
"faaa" println
}
fooとかだと、method_missing 相当がないのでうまくいかない。(これは動くけど、foo 決めうちだからうごいてる)
method_missing に相当するのは forward だった