函数的数据传入/传出

人们刚开始编程时,很快就会发现将所有代码写在一个大块中变得难以管理。因此,像 Lua 这样的现代编程语言支持一种称为函数的概念,它允许程序员指示程序的某些部分执行特定任务。除了编写清晰、有组织的代码之外,函数还是DRY(Don't Repeat Yourself,不要重复自己)概念的基础。“不要重复自己。”

如果您发现自己多次编写相同的代码块,并且每个块只有细微的差异,那么使用函数是最佳解决方案。此外,任何时候您想要多次执行相同的操作,函数都是最佳方法。

类似的任务函数

让我们考虑一个场景,我们只需要围绕单个数据值更改一小部分代码

local tanx = math.abs( 12 ) / math.abs( 15 )
local atanx = math.atan( tanx )  -- Result in radians
local angle = atanx * 180 / math.pi  -- Converted to degrees

print( angle )

tanx = math.abs( 34 ) / math.abs( -16 )
atanx = math.atan( tanx )  -- Result in radians
angle = atanx * 180 / math.pi  -- Converted to degrees

print( angle )

tanx = math.abs( 80 ) / math.abs( -4 )
atanx = math.atan( tanx )  -- Result in radians
angle = atanx * 180 / math.pi  -- Converted to degrees

print( angle )

在这个代码块中,我们只是根据三角形的宽度和高度计算角度。如您所见,这段代码很快变得重复——我们基本上是在一遍又一遍地做同样的事情,每次只改变三角形的参数。这是一个函数非常有用的典型例子,所以让我们看一下使用函数重写这段代码

local function calculateAngle( sideA, sideB )

    local tanx = math.abs( sideB ) / math.abs( sideA )
    local atanx = math.atan( tanx )  -- Result in radians
    local angle = atanx * 180 / math.pi  -- Converted to degrees
    return angle
end

print( calculateAngle( 15, 12 ) )
print( calculateAngle( -16, 34 ) )
print( calculateAngle( -4, 80 ) )

请注意,我们只编写了一次基本代码,但我们使用变量sideAsideB进行计算。在函数块之后,我们使用与原始版本相似的数值输出了三次 calculateAngle() 函数的 return 值(return 的用法将在下面详细讨论)。

传入数据

数据作为参数发送给函数,或者一些开发人员称之为“参数”。它们作为函数括号 (()) 内以逗号分隔的值/变量列表传递给函数,例如

local picWidth = 32
local pic = display.newImageRect( "pic.png", picWidth, 64 )

在这个例子中,我们调用了一个常见的 Solar2D 函数 display.newImageRect(),并向其传递

  1. 一个字符串值 ("pic.png")。
  2. 一个变量 (picWidth)。
  3. 一个数字 (64)。

逗号之间的空格不是必需的,但字符串值必须在引号内传递,而变量和数字必须在不带引号的情况下传递。也可以传递其他项目,包括数据表,甚至是其他函数。本质上,任何有效的 Lua 数据类型都可以传递给 Lua 函数。

让我们看看更多例子

local result = myFunction( "test" )
local myString = "test"
local result = myFunction( myString )

这两种情况的行为相同,只是在第二种版本中,唯一的参数是预先声明为变量 myString

这是另一个传入表格的等效集合

local result = myFunction( { 1, 2, 3 } )
local myTable = { 1, 2, 3 }

local result = myFunction( myTable )
local myTable = {}
myTable[1] = 1
myTable[2] = 2
myTable[3] = 3

local result = myFunction( myTable )

在这里,您可以看到完全相同的结果——一个包含一系列值的表格——被传递给 myFunction()。您如何选择传入数据完全取决于您,它可能仅仅取决于您需要的灵活性。

如前所述,函数可以接受一种数据类型的参数或混合数据类型的参数。作为开发人员,您有责任确保传递给函数的值是您期望的值——不要粗心大意地传递字符串,而您希望它是数字,反之亦然反之亦然.

参数名称

参数名称应该是对您有意义的任何名称——它们不需要是任何特定的名称。但是,如果您不使用逻辑完整的名字,以后检查您的代码的人(甚至您自己!)可能会难以理解函数期望什么值。让我们以触摸处理函数为例进行检查

local function handleTouch( event )

    if ( event.phase == "ended" ) then
        -- Handle touch lifting off screen
    end
    return true
end

此函数只需要一个参数 event,它是一个表示用户触摸屏幕“事件”的 Lua 表。假设此函数通过如下命令用作侦听器函数Runtime:addEventListener( "touch", handleTouch ),则此表包含各种值,包括事件的“阶段”和屏幕上触摸坐标的x/y位置。

请注意,一些程序员可能会编写如下相同的函数

local function handleTouch( e )

    if ( e.phase == "ended" ) then
        -- Handle touch lifting off screen
    end
    return true
end

这些函数的行为相同,只是参数名称 event 已缩短为 e。虽然 e 不是描述性名称,但它表明名称本身并不重要——但是,最好明智地命名参数,这样您将来就不会忘记其用途。

传出数据

通常,需要从函数中检索数据。在本教程的第一个示例中,我们需要根据传入的参数获取 angle 值。幸运的是,这可以通过简单的 return 命令轻松完成,后跟要返回的值

local function calculateAngle( sideA, sideB )

    local tanx = math.abs( sideB ) / math.abs( sideA )
    local atanx = math.atan( tanx )  -- Result in radians
    local angle = atanx * 180 / math.pi  -- Converted to degrees
    return angle
end

多个返回值?

与大多数其他编程语言不同,Lua 允许函数返回多个值(其他语言通常只返回一个)。如果您需要从 Lua 函数返回多个值,只需提供一个逗号分隔的return 的值列表,并在调用函数时为每个返回的值提供唯一的变量。比较区别

local function returnOneNumber()
    return 10
end

local value = returnOneNumber()
local function returnTwoNumbers()
    return 10, 20
end

local value1, value2 = returnTwoNumbers() 

请注意,由于第二个函数返回两个值,因此逻辑上需要两个变量 value1value2 来存储返回的值。

可以通过 Solar2D API myObject:getLinearVelocity() 直接观察到这种多返回值概念,这是一个检索物理对象当前线速度的物理函数。由于物理线速度始终由两个速度值组成,水平 (x) 和垂直 (y),因此通常像这样调用此函数

local linearVelocityX, linearVelocityY = myObject:getLinearVelocity()

但是请注意,您不需要将所有返回的值存储为单独的变量。例如,如果您只关心物理对象的线性x速度,则只存储该值,线性y值将被丢弃

local linearVelocityX = myObject:getLinearVelocity()

可变数量的参数

有时函数可能需要接受可变数量的参数。Lua 使用可变参数 ... 语法来适应这种情况。考虑以下函数,它接受数量不确定的数值参数并将它们加在一起成为一个总和

local function addNumbers( ... )

    local sum = 0

    for i = 1,#arg do
        sum = sum + arg[i]
    end

    return sum
end

local finalSum =  addNumbers( 1, 12, 4, 5, 2 )
print( finalSum )

在这里,请注意 Lua 如何使用三个连续的句点 (...) 来表示数量不等的参数,并且一旦进入函数内部,这将生成一个名为 arg 的表,它是一个数字索引的表(数组),可以对其进行迭代以访问每个参数

local function addNumbers( ... )

    local sum = 0

    for i = 1,#arg do
        sum = sum + arg[i]
    end

    return sum
end

总结

希望本教程能够帮助您理解函数的性质、它们的巨大用途、如何将不同类型的数据传递给函数,以及如何检索所需的信息。请记住,清晰的编码和巧妙地使用函数将改进应用程序的结构和性能,并使程序代码更易于理解。