# レキシカルスコープでダイナミックスコープを実装する。(Ruby編)
_published: 2010/08/28_ 
よく考えたら、ダイナミックスコープを採用している言語を使ったことがありませんでした。まあ、よく考えなくても、使ったことはないのですが。というわけで、レキシカルスコープなRubyで、ダイナミックスコープを実装してみます。
valvallowさんによると、レキシカルスコープなSchemeでダイナミックスコープを実装したマクロや、ダイナミックスコープなEmacs Lispでレキシカルスコープを実装したマクロがあるのだとか。その話を聞いたのが、事の発端です。案の定です。
まずは、こんな実装。
```ruby
def method_missing(name, *args)
$context.eval(name.to_s)
end
def output
puts x
end
def test
x = 123
$context = binding
output()
end
test() #=> 123
```
`output` メソッドの中で定義されてない `x` を使おうとすると、 `method_missing` が呼ばれるのを利用しました。`output` 呼び出し直前の `binding` を保存しておく必要があります。これはメソッド呼び出しをフックしても解決しません。メソッドが呼び出された時点で、コンテキストが変わってしまいます。
メソッド呼び出し直前に `$context = binding` の1行をいれなければならない。おもしろくないですね。そもそも、すべての変数をダイナミックスコープにしなくてもいいんじゃないでしょうか。Common LispやPerlのように、スコープを選択できると便利です。
そんな、実装。
```ruby
def method_missing(name, *args)
eval("$#{name}")
end
def local(name, val)
eval("$#{name} = val")
end
def output
puts x
end
def test
local :x, 123
output()
end
test() #=> 123
```
変数の定義が特殊すぎますね。` local x = 123` としたいところですが、 `=` は制御構造なのでカスタマイズできません。また、 `.call` としなくていいのであれば、 `proc` を使う方法もあるのですが。
と書いてみましたが、どちらの実装も変数がリードオンリーなんですよね。とりあえず、この辺でやめておきます。Lispのマクロはすごいなー。