如何在一个表达式中比较具有多个返回值的两个函数的结果?

4

我写了一个测试实用函数 aequals(断言相等),它期望实际结果和预期结果作为参数。我使用它的方式如下:

aequals(fib(8), 21);

现在我有一个具有多个返回值的函数:

function stuff() return 1,2,3 end

我想通过检查它的所有功能来检查它:

aequals( stuff(), {1,2,3} );

但是这样做不起作用,因为只有栈顶的 "1" 赋值给了 aequals

或者至少一个接一个地执行:

aequals( stuff()[1], 1 );
aequals( stuff()[2], 2 );
aequals( stuff()[3], 3 );

但这会产生语法错误,因为stuff返回的是元组,而不是数组/表格。

我尝试使用array-constructor进行修复,它应该可以将元组转换为数组/表格。

aequals( {stuff()}[1], 1 );

为什么这是一个语法错误我无法理解。

我通过定义一些辅助函数来规避此问题,我相信这些函数已经存在于 Lua 中,只要我知道在哪里寻找即可:

function arg0(a,b,c) return a end;
function arg1(a,b,c) return b end;
function arg2(a,b,c) return c end;

aequals( arg0(stuff()), 1 );

虽然这种方法可以工作,但它相当繁琐,如果能够将整个检查放在一行中,就会更加美观... 那么怎么做呢?


3
用于比较单个值的函数:aequals( select(1, stuff()), 1 ),用于比较多个值的函数:aequals_multiple( {stuff()}, {1,2,3} ) - Egor Skriptunoff
@EgorSkriptunoff select 是个好主意。aequals_multiple(或者 aequals_table/aquals_array?)怎么工作呢?如果参数是表,aequals 不能自己检查吗?我尝试过 {1,2,3} == {1,2,3},结果是 false,因为引用不同,参见 https://www.lua.org/pil/3.2.html。有没有逐元素比较的运算符?我想先写一个单独的函数。 - towi
@towi 你需要自己实现逐元素比较。请参考 http://lua-users.org/wiki/CompareTables 或 https://dev59.com/wWIj5IYBdhLWcg3wYUKR。 - Piglet
修复 {stuff()}[1] 的方法是在表字面量周围加上括号:({ stuff() })[1]。只有在字面值周围添加括号才能索引或调用方法。如果没有括号,会出现语法错误。类似地,"abc":sub(1, 1) 必须改为 ("abc"):sub(1, 1) - cyclaminist
1个回答

4
function stuff() return 1,2,3 end

aequals( stuff(), {1,2,3} );

使用这种方式,stuff()返回的列表将被缩减为第一个元素,因为stuff()不是该表达式列表中的最后一个表达式。

您可以交换表格和stuff()以简单地规避这个问题。

aequals({1,2,3}, stuff())

或者按照Egor的评论建议使用表格。

来自Lua 5.3参考手册3.4表达式

函数调用和可变参数表达式都可以返回多个值。如果将函数调用用作语句(参见§3.3.6),则其返回列表会被调整为零个元素,因此会丢弃所有返回值。如果将表达式用作表达式列表的最后一个(或仅有的)元素,则不进行调整(除非表达式用括号括起来)。在所有其他情况下,Lua将结果列表调整为一个元素,要么丢弃除第一个值以外的所有值,要么添加一个单独的nil(如果没有值)。


是的,我最喜欢将两个参数作为表格解决方案。我尝试过了,它像魔法一样工作。我还没有将其集成到aequals中,因为我不知道如何检查类型,但这没关系。 - towi
@towi type() - Piglet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接