メタテーブルを使用してシーケンスのビューを表示するというprapinの提案は、おおよそ私が行う方法です。役立つ可能性のある抽象化は、セグメントのメタテーブルを定義することです。これは、テーブルとオフセットインデックスのペアを返す0-ary関数にすることができます。ここでは、タプルを表すために関数のみを使用しています。次に、この関数をテーブルのように動作させるメタテーブルを定義できます。
do
local tail_mt = {
__index = function(f, k) local t, i=f(); return t[k+i] end,
__newindex = function(f, k, v) local t,i=f(); t[k+1] = v end,
__len = function(f) local t,i=f(); return #t-i end,
__ipairs = function(f)
local t,i = f ()
return
function (_, j)
if i+j>=#t then
return nil
else
return j+1, t[i+j+1]
end
end, nil, 0
end,
}
tail_mt.__pairs = tail_mt.__ipairs -- prapin collapsed this functionality, so I do too
function tail (t)
if type(t) == "table" then
return setmetatable ( function () return t, 1 end, tail_mt )
elseif type(t) == "function" then
local t1, i = t ()
return setmetatable ( function () return t1, i+1 end, tail_mt )
end
end
end
__indexおよび__newindexメタメソッドを使用すると、f [2] = f[1]+1などのコードを記述できます。
この(テストされていない)コードは、1回限りのメタテーブルを無限に作成するわけではありませんが、サンク(0-ary関数)を呼び出してコンテンツを取得するため、おそらくprapinよりも効率が低くなります。ただし、シーケンスに関するより一般的なビューを使用するなどして機能を拡張することに興味がある場合は、これはもう少し柔軟だと思います。