什么是"类型签名"在Lua中的对()?

时间:2018-06-07 18:39:35

标签: lua

查看&#34; Lua编程中的7.1 – Iterators and Closures章节&#34;好像for foo in bar循环需要bar需要类型(使用Java typesto表达它)Supplier<Tuple>for-in将继续调用bar直到它返回nil

所以类似于:

for k,v in pairs( tables ) do
    print( 'key: '..k..', value: '..v )
end

暗示pairs的类型为Function<Table,Supplier<Tuple>>

我想创建一个行为类似pairs 的函数,除了它跳过元组,其中第一个参数以下划线开头(即_)。

local function mypairs( list )
    local --[[ Supplier<Tuple> ]] pairIterator = pairs( list )
    return --[[ Supplier<Tuple> ]] function ()
        while true do
            local key, value = pairIterator()
            if key == nil then
                return nil
            elseif key:sub(1,1) ~= '_' then
                return key, value
            end
        end
    end
end

然而,自

以来它无法正常工作
--[[should be: Supplier<Table>]] pairIterator = pairs({ c=3; b=2; a=1 })

我称之为

pairIterator()

它返回

stdin:1: bad argument #1 to 'pairIterator' (table expected, got no value)
stack traceback:
    [C]: in function 'pairIterator'
    stdin:1: in main chunk
    [C]: in ?

但是

pairIterator({ c=3; b=2; a=1 })

返回

Lua>pairIterator({ c=3; b=2; a=1 })
c       3

2 个答案:

答案 0 :(得分:4)

您的基本问题是您在Lua问题上使用Java逻辑。 Java和Lua是具有不同结构的不同语言,识别它是很重要的。

pairs没有返回值;它有多个返回值。这是Java完全缺乏的概念。 Tuple是一个可以存储和操作多个值的值。 Lua函数可以返回多个值。这在语法和语义上与返回包含多个值的表不同。

基于迭代器的for语句将多个值作为输入,而不是多个值的表或容器。具体来说,它存储3个值:迭代器函数,状态值(用于保持调用之间的状态)和初始值。

因此,如果您想模仿pairs的行为,则需要能够存储和操作其多个返回值。

您的第一步是存储pairs实际返回的内容:

local f, s, var = pairs(list)

您正在创建一个新的迭代器函数。所以你需要返回它,但 还需要返回svar返回的pairs。您的退货声明需要如下所示:

return function (s, var)
    --[[Contents discussed below]]
end, s, var --Returning what `pairs` would return.

现在,在您的功能中,您需要使用fs来呼叫var。此函数将返回键/值对。你需要正确处理它们:

return function (s, var)
    repeat
        local key, value = f(s, var)
        if(type(key) ~= "string") then
            --Non-string types can't have an `_` in them.
            --And no need to special-case `nil`.
            return key, value
        elseif(key:sub(1, 1) ~= '_') then
            return key, value
        end
    until true
end, s, var --Returning what `pairs` would return.

答案 1 :(得分:3)

pairs()返回三个单独的值:

  • 使用返回键和值的参数(table, key)进行调用的函数
  • 你传递给它的表
  • 要传递给函数的第一个'key'值(对于pair()为0,对于ipairs()为0)

这样的事情:

for k,v in pairs({a=1, b=13, c=169}) do print(k, v) end

可以这样做:

local f,t,k = pairs({a=1, b=13, c=169})
local v
print('first k: '..tostring(k))
k,v = f(t, k)
while k ~= nil do
  print('k: '..tostring(k)..', v: '..tostring(v))
  k,v = f(t, k)
end

结果:

first k: nil
k: c, v: 169
k: b, v: 13
k: a, v: 1

并且您不必参与论证,这包含每个值的手动if语句:

function mypairs()
  -- the function returned should take the table and an index, and
  -- return the next value you expect AND the next index to pass to
  -- get the value after.  return nil and nil to end
  local myfunc = function(t, val)
    if val == 0 then return 1, 'first' end
    if val == 1 then return 2, 'second' end
    if val == 2 then return 3, 'third' end
    return nil, nil
  end

  -- returns a function, the table, and the first value to pass
  -- to the function
  return myfunc, nil, 0
end

for i,v in mypairs() do
  print('i: '..tostring(i)..', v: '..tostring(v))
end

-- output:
-- i: 1, v: first
-- i: 2, v: second
-- i: 3, v: third

对于你的mypairs(list),你可以继续调用从对返回的函数,只要该键有一个下划线来获得下一个值:

local function mypairs( list )
  local f,t,k = pairs(list)
  return function(t,k)
    local a,b = f(t, k)
    while type(a) == 'string' and a:sub(1,1) == '_' do  a,b = f(t,a) end
    return a,b
  end, t, k
end

local list = {a=5, _b=11, c = 13, _d=69}
for k,v in mypairs(list) do print(k, v) end

-- output:
-- c    13
-- a    5

您链接到的文档有一个只返回一个值的迭代器,pairs()返回2,但如果需要,您可以返回更多。 for ... in ...构造仅在第一个值为非零时才执行主体。这是一个版本,它还返回被跳过的键,如果你没有以实际值结束,则不会执行正文,因此你可能看不到所有_键:

local function mypairs( list )
  local f,t,k = pairs(list)
  return function(t,k)
    local skipped = {}
    local a,b = f(t, k)
    while type(a) == 'string' and a:sub(1,1) == '_' do
      table.insert(skipped, a)
      a,b = f(t,a)
    end
    return a,b,skipped
  end, t, k
end

local list = {a=5, _b=11, c = 13, _d=69}
for k,v,skipped in mypairs(list) do
  for i,s in ipairs(skipped) do
    print('Skipped: '..s)
  end
  print(k, v)
end