Function 为什么在函数';什么范围?

Function 为什么在函数';什么范围?,function,lua,scope,lua-table,Function,Lua,Scope,Lua Table,这样清除表会导致预期的行为: table1 = { "a" } table1 = {} print(unpack(table1)) -- results in printing a blank line 但如果在函数中执行相同的操作,则不需要: table1 = { "a" } function cleartest (x) x = {} print(unpack(x)) end cleartest(table1) -- results i

这样清除表会导致预期的行为:

table1 = { "a" }
table1 = {}
print(unpack(table1))        -- results in printing a blank line
但如果在函数中执行相同的操作,则不需要:

table1 = { "a" }

function cleartest (x)
    x = {}
    print(unpack(x))
end

cleartest(table1)            -- results in printing a blank line
print(unpack(table1))        -- results in "a"
是什么导致了这种行为

编辑:澄清Lua中传递表的工作方式。x不是表1的本地“副本”,因为它是“value is reference”类型,所以它实际上是对实际表的引用。例如:

table1 = { "a" }

function xisref (x)
    x[2] = "b"
end

xisref(table1)
print(unpack(table1))         -- results in printing "a    b" thus x is a reference to the actual table

你没有清理桌子。您正在创建一个新表并将其分配给变量

在第一种情况下,您将覆盖
table1
变量,因此后面的引用将获得新的空表

在第二种情况下,您正在覆盖函数本地的
x
变量,因此后面对
table1
的引用不受影响。请注意,如果您在
cleartest()
函数中说了
table1={}
,它的行为将与第一种情况类似

如果确实希望清除现有表,以便对同一表的其他引用看到已清除状态,则需要编写如下内容

for k in pairs(x) do
    rawset(x, k, nil)
end

你没有清理桌子。您正在创建一个新表并将其分配给变量

在第一种情况下,您将覆盖
table1
变量,因此后面的引用将获得新的空表

在第二种情况下,您正在覆盖函数本地的
x
变量,因此后面对
table1
的引用不受影响。请注意,如果您在
cleartest()
函数中说了
table1={}
,它的行为将与第一种情况类似

如果确实希望清除现有表,以便对同一表的其他引用看到已清除状态,则需要编写如下内容

for k in pairs(x) do
    rawset(x, k, nil)
end

因为您实际上无法清除表的值,只能清除名称

如果你这样做

table1 = { "a" }
table1 = {}
您没有将
{“a”}
设置为
{}
,而是将
table1
设置为
{}
替换先前的值。该值现在不可访问,最终将由垃圾收集器清除

调用
cleartest
时,
x
也将指向与
table1
相同的值
{“a”}
,但
x
是它的不同(本地)名称。通过执行
x={}
只需使
x
指向一个新的空表,但这并没有改变仍然指向
{a}
table1
的任何内容

回应您的编辑:

x
引用的值与
表1
中的值相同但是
x
仍然只是碰巧指向该值的本地名称。当您将某个内容分配给
x
时,局部变量
x
将指向新的内容,而不会影响它以前指向的值

试试这个(无论在哪里、全球、本地,都无所谓):


将新内容分配给
test2
并打印
test1
将产生相同的结果。

因为您实际上无法清除表的值,而只能清除名称

如果你这样做

table1 = { "a" }
table1 = {}
您没有将
{“a”}
设置为
{}
,而是将
table1
设置为
{}
替换先前的值。该值现在不可访问,最终将由垃圾收集器清除

调用
cleartest
时,
x
也将指向与
table1
相同的值
{“a”}
,但
x
是它的不同(本地)名称。通过执行
x={}
只需使
x
指向一个新的空表,但这并没有改变仍然指向
{a}
table1
的任何内容

回应您的编辑:

x
引用的值与
表1
中的值相同但是
x
仍然只是碰巧指向该值的本地名称。当您将某个内容分配给
x
时,局部变量
x
将指向新的内容,而不会影响它以前指向的值

试试这个(无论在哪里、全球、本地,都无所谓):


test2
分配新的内容并打印
test1
将产生相同的结果。

x变量不是函数的局部变量,它是对实际表的引用。例如,函数内的x[2]=“b”会将表1附加到函数作用域之外。@RossCharette:你错了<代码>x是函数的本地值。但它也是对实际表格的引用。但这并不能改变这样一个事实,即对
x
的赋值实际上不会影响原始表。@RossCharette:如果我有代码
locala={“a”};局部b=a;b={};打印(解包(a))
,您认为会发生什么?您的问题暗示您相信它不会打印任何内容,但实际上它会打印
a
,因为
b
的赋值实际上没有改变
a
。对x的赋值肯定会改变原始表,请参阅我在上面原始问题中的编辑,然后自己测试。@RossCharette no.
x[2]=“b”
不是分配给
x
x
首先作为一个名称进行计算,该名称指向您的值
{“a”}
(与
table1
指向的值相同)。然后,
[2]=“b”
是在该值上发生的赋值。在函数内部尝试
x={“b”}
:它不会更改
table1
,因为这是对
x
的赋值。如果你不相信凯文或我,请阅读参考手册。我用另一个澄清的例子更新了我的答案。x变量不是函数的局部变量,它是对实际表的引用。例如,函数内的x[2]=“b”会将表1附加到函数作用域之外。@RossCharette:你错了