这段代码的意思是什么(if v then return v end)?

我有一段代码,它长这个样子:

do

    local function index(n,m)
        return n*(n+1)//2 + m
    end

    local binomtable = {}

    function binom3(n,m)
        if n<0 or m<0 or m>n then return 0 end
        if n=0 or m=0 or m=n then return 1 end
        local i = index(n,m)
        local v = binomtable[i]
        if v then return v end
        v = binom3(n-1,m-1) + binom3(n-1,m)
        binomtable[i] = v
        return v
    end

end

我想知道

if v then return v end

的意思。

谢谢!

点赞
用户6879826
用户6879826

简短的回答是,if v then return v end 如果v为真值,则返回值v,即既不是 false 也不是 nil。否则,函数将继续通过计算 v 的值,将该值存储在 binomtable 中,最后将其返回。更有趣的问题是,为什么函数要这么做?

在发布的代码中,binom3 是一个递归函数。通过递归调用 v = binom3(n-1,m-1) + binom3(n-1,m),将会有很多努力重复,因此会浪费大量的空间和时间。例如:

binom3(4, 2)
--> binom3(3, 1) + binom3(3, 2)
--> binom3(2, 0) + binom3(2, 1) + binom3(2, 1) + binom3(2, 2)
--> 1 + binom3(1, 0) + binom3(1, 1) + binom3(1, 0) + binom3(1, 1) + 1

请注意,在第二次规约中有两个相同的术语:

binom3(2, 1) + binom3(2, 1)

没有必要计算两次项 binom3(2, 1),这样做意味着:

binom3(1, 0) + binom3(1, 1)

也必须计算两次,如第三个规约中所示。在mn更大且计算数量呈指数级增长时,这成为性能方面非常重要的问题,需要在所需的内存量和所需的时间量之间进行平衡。

发布的代码使用了记忆化技术来提高性能。当进行计算时,它将被存储在表 binomtable 中。在进行任何计算之前,会首先查看 binomtable。首先,将 v 设置为 binomtable[i] 的值;如果该值为任何真值(Lua 中的任何整数均为真值),则只需返回该值,而无需进行递归计算。否则,如果返回 nil(即尚未为该计算存储任何值),则该函数将继续进行递归计算。完成计算后,新值将被存储在 binomtable 中,以便在下次需要时使用。这种策略节省了大量的计算开销,并可以在这样的递归算法的性能方面产生巨大的差异。

2020-10-30 22:51:32
用户2137413
用户2137413

针对你的具体问题:

if v then return v end

的意思是,如果变量 v 不是 nilfalse,就返回变量 v 的值并停止执行该函数。

--类似的
function myfunc(input)
  local MyVar = "我是一个字符串,不是nil!"
  if MyVar then
    return "hi"
  else
    return "hello"
  end

  print("我不可见,因为我是不可达代码!")
end

如果调用此函数,则始终返回“hi”而不是“hello”,因为MyVar为真,因为它具有一个值。此外,在return调用后,下面的print函数将永远不会被调用,因为它停止执行该函数。

对于你的代码,它检查一个 table 来查看它是否在某个 index 拥有一个条目,如果它有,则返回该值。

2020-10-31 02:38:37