Method Curry

lua-users home
wiki

目標:讓方法呼叫 (foo:bar()) 不包含呼叫部分 (foo:bar) 也能評估出 curried 閉包。當前我們有下列語意:

function object:wrap(method_name)
  local f = self[method_name]
  return function(...) return f(self, ...) end
end

不過假如能直接寫成這樣,不是更好嗎?

f = foo:wrap("bar")

我們可以這樣寫:

f = foo:bar;

Slact 想到了這個點子,我也對剖析程式碼動了些腦筋,看看實作起來有多容易。

優點:與現有程式碼完全相容,提供一個簡單的方法,用已存在語法來使用匿名的函式。

缺點:每次方法呼叫時都會建立一個新的封閉,嚴重影響效能。可能需要最佳化這些部分,並只在下一段不是參數清單(表示將儲存而非呼叫它)時才建立閉包。

在純粹的 Lua 中測試時,包覆 wrap(foo, 'bar') 與直接呼叫 nowrap(foo,'bar') -- 給無作用函式nowrap 的速度差異達到 106%。如果純粹 Lua 中的測試結果可以反映在剖析程式碼中進行編碼時的效能影響,那保留當前的方法呼叫後檢查參數以進行最佳化的方式,可能就有意義了。

備註

-- on changes to the grammar
<ToxicFrog> Hmm. I think this changes primaryexp from:
            prefixexp { '.' NAME | '[' exp ']' | ':' NAME
            funcargs | funcargs } to prefixexp { '.' NAME |
            '[' exp ']' | ':' NAME | funcargs }

-- on the emitted code
<ToxicFrog> Table at 0
<ToxicFrog> SELF 0 0 <<field>>
<ToxicFrog> CLOSURE 2 <<wrapper>>
<ToxicFrog> MOVE 0 0
<ToxicFrog> MOVE 0 1
<ToxicFrog> CLOSE 0
<ToxicFrog> And then some stack cleanup. (FIXME: do I fully
            understand what CLOSE does?)
<ToxicFrog> And <<wrapper>> is a function that looks like:
<ToxicFrog> GETUPVAL 1 0
<ToxicFrog> GETUPVAL 2 1
<ToxicFrog> VARARG 3 0
<ToxicFrog> TAILCALL
<ToxicFrog> 1 0 0
<ToxicFrog> RETURN 0 0
<ToxicFrog> So, the problems that need to be solved:
<ToxicFrog> - emitting <<wrapper>> into the generated chunk
<ToxicFrog> - making the stack consistent after we generate the closure
</pre>
-- 有關要修改的內容

所有有趣的部份都在 lparser.c 中。需要變更 primaryexp 的程式碼產生。需要執行的兩個主要動作:如果我們有 foo:bar 結構,它需要發出在堆疊頂端留下閉包的程式碼 - 大部分都在上面寫了,但需要在完成後做一些清理。此外,實際的函式必須出現在常數表中。我們有以下三個選項

最後一個選項可能是最容易的,但可能會產生許多重複的函式 - 需要測試這個


RecentChanges · 首選設定
編輯 · 歷史記錄
最後編輯日期為 2008 年 12 月 18 日 上午 5:12(格林威治標準時間)(diff)