【问题标题】:lua not modifying function argumentslua没有修改函数参数
【发布时间】:2017-05-04 19:14:58
【问题描述】:

我一直在学习 lua,但似乎无法对这个二叉树进行简单的实现......

function createTree(tree, max)
    if max > 0 then
        tree = {data = max, left = {}, right = {}}
        createTree(tree.left, max - 1)
        createTree(tree.right, max - 1)
    end
end

function printTree(tree)
    if tree then
        print(tree.data)
        printTree(tree.left)
        printTree(tree.right)
    end
end

tree = {}
createTree(tree, 3)
printTree(tree)

程序在执行后只返回 nil。我在网上搜索以了解参数传递在 lua 中的工作原理(如果是通过引用或通过值),并发现某些类型是通过引用传递的(如表和函数),而另一些是通过值传递的。尽管如此,在将全局变量“tree”传递给“createTree”函数之前,我还是将它设为了一个表,并且出于相同目的,我什至将“left”和“right”初始化为“createTree”内部的空表。我做错了什么?

【问题讨论】:

    标签: function lua arguments binary-tree lua-table


    【解决方案1】:

    可能不需要通过新表进行初始化,而只是设置其值。

    function createTree(tree, max)
        if max > 0 then
            tree.data = max
            tree.left = {}
            tree.right = {}
            createTree(tree.left, max - 1)
            createTree(tree.right, max - 1)
        end
    end
    

    【讨论】:

    • 虽然这个答案让我接近理解问题,但它并不完整。无论如何,感谢提供规避我的问题所需的信息:)
    【解决方案2】:

    在 Lua 中,参数是按值传递的。赋值给一个参数不会改变原来的变量。

    试试这个:

    function createTree(max)
        if max == 0 then
            return nil
         else
            return {data = max, left = createTree(max-1), right = createTree(max-1)}
         end
    end
    

    【讨论】:

    • 我承认这不是让我理解我的错误的答案,但看看你是如何创建那棵树的仍然很有帮助。我从没想过那样做;它比我想出的更简单、更优雅,所以无论如何谢谢!不过,您的版本不会利用尾递归吗?
    【解决方案3】:

    在大多数情况下,lua 按值传递参数是安全的。但是对于数字以外的任何对象(数字实际上不是对象),“值”实际上是指向所述对象的指针。

    当您执行a={1,2,3}b="asda" 之类的操作时,右侧的值会动态分配到某处,而ab 只会获取这些地址。因此,当您将a 传递给函数fun(a) 时,指针被复制到函数内部的一个新变量中,但a 本身不受影响:

    function fun(p)
       --p stores address of the same object, but `p` is not `a`
       p[1]=3--by using the address you can 
       p[4]=1--alter the contents of the object
       p[2]=nil--this will be seen outside
    
       q={}
       p={}--here you assign address of another object to the pointer
       p=q--(here too)
    end
    

    函数也由指向它们的指针表示,您可以使用debug 库来修改函数对象(例如更改上值),这可能会影响函数的执行方式,但是,再一次,您不能更改外部引用的位置正在指点。

    字符串是不可变的对象,您可以传递它们,有一个库可以对它们进行处理,但是该库中的所有函数都返回新字符串。因此,如果您尝试在函数内使用“asda”字符串执行某些操作,那么来自b="asda" 的外部变量b 也不会受到影响。

    【讨论】:

    • 你的回答很清楚,让我明白我的错误。基本上,我的误解是“对象”变量(例如字符串和表)是通过 REFERENCE 传递的,但我现在明白它们是由指针表示并通过值传递的。这使得函数可以更改它们指向的数据,但不能更改指针本身的地址(如果我理解正确的话,就像将指针按值传递给 C/C++ 函数时一样)。其他答案使我接近这个结论,但正是你的答案消除了所有怀疑。谢谢:)
    • 解释得很好!所以基本上函数参数是常量指针。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-05
    • 1970-01-01
    • 2017-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-26
    相关资源
    最近更新 更多