[心得] dynamic scoping
原文是 CSSE 186 篇
令以下程式:
class A
def f
puts 'A::f'
end
def g t
t.call
end
end
def f
puts '::f'
end
def g t
t.call
end
b = lambda{f}
g b # ::f
A.new.g b # 問號
問號應該填什麼?
依照 static scoping, 是 ::f
依照 dynamic scoping, 是 A::f
Ruby 是 static scoping 的,所以是 ::f
那麼要如何達到 dynamic scoping 的能力?
可以依靠 eval 這個好東西(但我想執行效能應該蠻差的)
這次,t 不能寫成 Proc, 因為成為 Proc 時就已經 binding 完成了
這意味著我們不能用 lambda. 把 t.call 的地方改寫成:
eval t
如此就能達到 dynamic scoping 的能力
只是,我們就不能用合乎直覺的寫法,所有的 Ruby code 都得寫成字串的形式
不能寫成
b = f
要寫成純字串模式:
b = 'f' 或是
b = 'send :f'
如此在 eval t 之處,就能依照該處的 scope 來做 binding
輸出結果就會是 A::f
這裡其實有改進之處,因為我們只是要執行某個 function 而已
所以把 eval t 改成 send t
再把 b = 'f' 改成 b = :f
這樣應該會獲得一點效率上的優勢
不過這樣做就使得彈性下降了,因為你的 :f 不能存取當地的 lexical content
f = lambda{ print i } # i ?
字串的話
f = 'print i'
def loop n, f
n.times{|i| eval f}
end
loop 10, f
這樣 'print i' 中的 i 就能存取到當地的 lexical content
不過我不知道 Ruby 的 Binding object 是否可以幫得上什麼忙
不是很懂 Binding 要怎麼用
另外,我還有試了一下 ECMAScript 和 Flash 的 ActionScript
乍看之下可以做到像是上面的動作,但是其實只是假像
function A(){}
A.prototype.f = function(){
print('A::f')
}
A.prototype.g = function(t){
eval(t)
}
function f(){
print('::f')
}
function g(t){
eval(t)
}
b = 'this.f()'
g(b)
new A().g(b)
這樣可以印出
::f
A::f
沒問題,可是如果把 b = 'this.f()' 改成 b = 'f()' 的話,結果會變
::f
::f
我想是因為他可能沒有隱喻 this 的關係吧(沒有查 spec, 猜的)
可是如果加上 this 的話,把 A.prototype.f 拿掉,
就會出現 undefined function call 了
這點在 Ruby 裡沒有問題,因為不用強制寫下 this(self),
所以 this(self) 中找不到人的話,就會往上一層 scope 去找,進而找到 ::f
ActionScript 的結果和 ECMAScript 一樣,係出同源的關係吧
PHP 不試了,物件導向的能力實在太差了
reference:
http://en.wikipedia.org/wiki/Scope_(programming)#Dynamic_scoping
或
http://en.wikipedia.org/wiki/Scope_%28programming%29#Dynamic_scoping
edited:
於是我們可以更進一步去想,那麼在字串中的程式,是否失去語法檢查?
f = 'print i'
不可能會有語法檢查,如果寫成
f = 'print (i}'
要等到真正 eval 時,才會報 error
字串裡應該要有語法檢查,不過不用檢查語意
f = 'say i'
說不定當地有 say 這個 method, 不能先行檢查
所以用字串還是有蠻大的缺點
regular expression 可以用 // 夾起來
這種可植入的程式碼,也應該用另一種形式夾起來
像是
f = <% say i %>
不過如果可以的話,一個符號就好了
f = < say i > 會簡潔一些
一種可能的改進方向吧
--
生死去来、棚頭傀儡、一線断時、落落磊磊
《花鏡》-世阿弥
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 220.135.28.18
※ 編輯: godfat 來自: 220.135.28.18 (01/25 23:05)
Ruby 近期熱門文章
PTT數位生活區 即時熱門文章