結局Context lookupはv0.5からv0.6でどう変わったのか
0.6になって以降、少しずつ変更して来ましたが、さすがにもう変化は無さそうなのでまとめておきます。
invokeは同じなので解説しません。以下の説明はcallの場合(関数を名前で呼んだ場合)のみに有効です。
0.6でContextの継承が無くなりましたが、それではローカル定義の関数同士が呼び合えないという事態になり不便であったため、その対策としてreceiver(obj.methのobj)がContextである場合にそれが保持するselfもlookupの対象となるようにしました。
結果、lookupの順番が変わったと言えます。
- local
- 継承したContext (v0.5)
- global
- receiverがContextの場合にself (v0.6)
下記において、0.5では1、0.6では0になります。
global.test: 0 test: 1 f: `[ test ] f.flush
下記においても同様の結果ですが、少し複雑です。f1内のselfがf2内のselfと同じになり、結果、同じContextをlookupすることになります。
test2: 0 f1: `[ test2 ] f2: `[ test2: 1 f1 ] f2.flush
selfのselfは対象にならない(無限ループ対策が面倒だし有効な場面が無い)ので、下記は0.5では有効ですが、0.6ではエラーです。
test3: 0 f1: `[ test3 ] f2: `[ f3: `[ f1 //self.f1ならself.self.f1と同じになり有効 ] f3 ] f2.flush
Contextの継承をやめた理由は、globalをオーバーライドしてしまうためですので、この順序であればその問題はありません。
未定義でエラーになるはずのものがならずにバグ発見が遅れるという問題は残りますが、利便性が勝ると判断しました。