最小の Lua テーブル コピー

235

SoniEx2 の 239 回答の根性に実質的に基づいています。

local o,k,F=type,next,{}for n=0,2 do
F[n]=function(a,r,t,G)if n<1 or o{}~=o(a)then return a end
t={}r=r or{}r[a]=n<2 and t G=F[n%2]for x,y in k,a do
t[r[x]or G(x,r)]=r[y]or G(y,r)end
return t end end
table.copy={shallow=F[2],deep=F[1]}

利点は、両方の関数に同じ関数プロトタイプを使用することです。異なる上位値で同じ関数プロトタイプをインスタンス化すると、両方の役割を満たすことができます。

アンゴルフ:

-- ungolfed
-- note that type and next must have local copies to meet the spec
local o, k, F = type, next, {}
for n = 0, 2 do
  -- F[0] will be the identity function
  -- F[1] will be table.copy.deep
  -- F[2] will be table.copy.shallow
  F[n] = function(a, r, t, G)
    -- a is the table input
    -- r is the optional "custom recursion table" that is required
    -- t and G are just locals
    -- the spec implies (but does not state) that the global environment shouldn't be polluted
    -- r will only be used by recursive calls

    -- if n < 1, this is F[0], so act is the identity
    -- o is type, o{} is "table"
    -- if a is not a table, just return it
    if n < 1 or o{} ~= o(a) then
      return a
    end

    -- t will be the copy
    t = {}

    -- r will be the map that remembers which tables in the original map to which tables in the copy
    -- or, if it is passed in, it is a table that controls the behavior of the copy
    r = r or {}

    -- F[0] doesn't each here
    -- F[1] must add t to the map
    -- F[2] must not add t to the map
    -- (adding false will not hurt F[2] -- only true values will be picked up below)
    -- (behavior may not be exactly as desired for shallow copy, but spec doesn't require this feature)
    r[a] = n < 2 and t

    -- this is the function we will call to copy members
    -- for F[1] table.copy.deep, this is F[1] itself
    -- for F[2] table.copy.shallow, this is F[0] the identity
    -- (for F[0], we never get this far)
    -- the byte count seems equivalent making this a local vs putting it
    -- in both places it is used, but this is probably more efficient
    G=F[n%2]

    -- loop over and copy members
    -- first try r (which will only have non-1 entries for tables in F[1])
    -- then try G
    -- note that instead of calling "pairs" as usual, we can observe that pairs(a)
    -- is defined to return next, a, nil -- we use these (with implicit nil) directly
    for x, y in k, a do
      t[r[x] or G(x,r)] = r[y] or G(y,r)
    end

    return t
  end
end

-- export the functions as required
table.copy = {
  shallow = F[2],
  deep = F[1]
}

うまくいけば、仕様を正しく理解できました。これは提供されたテスト ケースに合格し、構造に十分な類似性があるため、同じことを行うと合理的に確信しています。

注 - 最初は「カスタム再帰テーブル」に関する部分がわかりませんでしたが、それをサポートするために回答を編集しました。

注2 - 改善された回答。また、提供された 239 バイトのリファレンス ソリューションは、カスタム再帰テーブルがどのように機能するかについての私の理解と完全には一致しないと判断しました。これは、コピーに false を追加するために使用できないためです。ただし、私のソリューションは提供されたものと同様に機能すると思います。