多返回值

简介: 多返回值

Lua 语言中一种与众不同但又非常有用的特性是允许一个函数返回多个结果Lua 语言中几个预定义函数就会返回多个值。例如函数 string.find ,该函数用于在字符串中定位模式。当找到了对应的模式时,该函数会返回两个索引值:所匹配模式在字符串中起始字符和结尾字符的索引。使用多重赋值可以同时获取到这两个结果:

s, e = string.find("hello `Lua` users", "`Lua`")
print(s, e)   --> 7     9


Lua 语言编写的函数同样可以返回多个结果,只需要在 return 关键字后列出所有要返回的值即可。例如:一个用于查找序列中最大元素的函数可以同时返回最大值及该元素的位置:

function maximum (a)
  local mi =1           -- 最大值的索引
  local m = a[mi]       -- 最大值
  for i = 1 #a do
    if a[i] > m then
      mi = i
      m = a[i]
    end
  end
  return m, mi          -- 返回最大值及其索引
end
print(maximum({8, 10, 23, 12, 5}))    --> 23  3


Lua 语言根据函数的被调用情况调整返回值的数量。

  • 当函数被作为一条单独语句调用时,其所有返回值都会被丢弃
  • 当函数被作为表达式(例如,加法的操作数)调用时,将只保留函数的第一个返回值
  • 只有当函数调用是一系列表达式中的最后一个表达式(或是唯一一个表达式)时,其所有的返回值才能被获取到。


这里所谓的“一系列表达式”在 Lua 中表现为4种情况:

  1. 多重赋值
  2. 函数调用时传入的实参列表
  3. 表构造器
  4. return语句。


如下所示:

function foo0 () end                    -- 不返回结果
function foo1 () return "a" end         -- 返回1个结果
function foo2 () return "a", "b" end    -- 返回两个结果


在多重赋值中,如果一个函数调用是一系列表达式中的最后(或者是唯一)一个表达式,则该函数调用将产生尽可能多的返回值以匹配待赋值变量:

x, y = foo2()            -- x="a", y="b"
x = foo2()               -- x="a", "b"被丢弃
x, y, z = 10, foo2()     -- x=10, y="a", z="b"


在多重赋值中,如果一个函数没有返回值或者返回值个数不够多,那么 Lua 语言会用 nil 来补充缺失的值:

x, y = foo0()       -- x=nil, y=nil
x, y = foo1()       -- x="a", y=nil
x, y, z = foo2()    -- x="a", y="b", z=nil


请注意,只有当函数调用是一系列表达式中的最后(或者是唯一)一个表达式时才能返回多值结果,否则只能返回一个结果:

x, y = foo2(), 20       -- x="a", y=20  ('b'被丢弃)
x, y = foo0(), 20, 30   -- x=nil, y=20  (30被丢弃)


当一个函数调用是另一个函数调用的最后一个(或者是唯一)实参时,第一个函数的所有返回值都会被作为实参传给第二个函数。例如函数 print ,由于函数 print 能够接受可变数量的参数,所以 print(g()) 会打印出g返回的所有结果。

print(foo0())         -->       (没有结果)
print(foo1())         --> a
print(foo2())         --> a   b
print(foo2(), 1)      --> a   1
print(foo2() .. "x")  --> ax


当在表达式中调用 foo2 时, Lua 语言会把其返回值的个数调整为 1 。因此,在上例的最后一行,只有第一个返回值" a "参与了字符串连接操作。


当调用 f(g()) 时,如果f的参数时固定的,那么 Lua 语言会把g返回值的个数调整成与f的参数个数一致。这并非巧合,实际上这正是多重赋值的逻辑。


表构造器完整的接受函数调用的所有返回值,而不会调整返回值的个数:

t = {foo0()}    -- t = {}   (一个空表)
t = {foo1()}    -- t = {"a"}
t = {foo2()}    -- t = {"a", "b"}


不过,这种行为只有当函数调用是表达式列表中的最后一个时才有效,在其他位置上的函数调用总是只返回一个结果:

t = {foo0(), foo2(), 4}     -- t[1] = nil, t[2] = "a", t[3] = 4

最后,形如 return f() 的语句会返回 f 返回的所有结果:

function foo (i)
  if i == 0 then return foo0()
  elseif i == 1 then return foo1()
  elseif i == 2 then return foo2()
  end
end
print(foo(1))   --> a
print(foo(2))   --> a   b
print(foo(0))   --> (无结果)
print(foo(3))   --> (无结果)


将函数调用用一对圆括号括起来可以强制其只返回一个结果:

print((foo0()))   --> nil
print((foo1()))   --> a
print((foo2()))   --> a


return 语句后面的内容是不需要加括号的,如果加了括号会导致程序出现额外的行为。因此,无论 f 究竟返回几个值,形如 return (f(x)) 的语句只返回一个值。有时这可能是我们所希望出现的情况,但有时又可能不是。

目录
相关文章
|
4天前
|
设计模式 Python
学习函数的参数传递和返回值
在编写函数时,不可避免地会出现一些错误。通过调试代码,查看参数的值在函数内部的变化以及返回值是否符合预期,有助于更好地理解参数传递和返回值的机制。
|
2月前
|
JavaScript 前端开发
&&、|| 的返回值
本文探讨了JavaScript中逻辑与(&&)和逻辑或(||)操作符的返回值特性,说明了它们在不同条件下的返回结果,以及如何利用这些特性进行条件表达式的简写。
40 0
&&、|| 的返回值
|
6月前
|
存储 弹性计算 运维
有返回值的函数
【4月更文挑战第29天】
37 1
|
6月前
|
存储 搜索推荐 Python
函数的调用和返回值
函数的调用和返回值
|
6月前
|
存储 Serverless Python
函数的返回值
在编程中,函数不仅用于执行特定的任务,还经常用于计算和返回结果。函数的返回值是函数执行完毕后向调用者提供的信息或数据。通过返回值,我们可以从函数中获取所需的结果,并将其用于后续的计算或操作。本文将详细讨论函数的返回值,并附上相应的代码示例。
168 1
|
6月前
|
定位技术 C++ Python
C++一个函数返回两个或更多个返回值的方法
C++一个函数返回两个或更多个返回值的方法
178 1
|
C++ Python
C++函数如何返回两个或以上的返回值?
本文介绍C++语言中,一个函数返回两个及以上、同类型或不同类型的返回值的方法~
424 1
C++函数如何返回两个或以上的返回值?
|
JavaScript 前端开发
带有返回值的函数
带有返回值的函数
159 0
|
开发者 Python
函数的返回值| 学习笔记
快速学习函数的返回值
|
测试技术 开发者 Python
多个返回值| 学习笔记
快速学习多个返回值