수색…


통사론

  • funcname = function (paramA, paramB, ...) body; return exprlist end - 간단한 함수
  • 함수 funcname (paramA, paramB, ...) body; exprlist 끝 반환 - 위의 속기
  • 로컬 funcname = 함수 (paramA, paramB, ...) 본문; return exprlist end - 람다
  • 로컬 funcname ; funcname = function (paramA, paramB, ...) body; return exprlist end - 재귀 호출을 할 수있는 lambda
  • 로컬 함수 funcname (paramA, paramB, ...) body; exprlist 끝 반환 - 위의 속기
  • funcname (paramA, paramB, ...) - 함수 호출
  • local var = var 또는 "Default"- 기본 매개 변수
  • return nil, "오류 메시지"- 오류가 발생하면 중단하는 표준 방법

비고

함수는 대개 function a(b,c) ... end 로 설정되고 거의 변수를 익명 함수 ( a = function(a,b) ... end )로 설정하면 설정됩니다. 함수를 매개 변수로 전달할 때 반대가 사실이며 익명 함수가 주로 사용되며 일반 함수는 자주 사용되지 않습니다.

함수 정의하기

function add(a, b)
    return a + b
end
-- creates a function called add, which returns the sum of it's two arguments

구문을 살펴 보겠습니다. 먼저 function 키워드를 봅니다. 글쎄, 그것은 꽤 설명 적입니다. 다음으로 add 식별자를 봅니다. 이름. 우리는 인수 (a, b) 를 볼 수 있습니다. 기능 본체 안에서만 액세스 할 수 있습니다. 이제 끝으로 건너 보자, 우리가 볼 ... 음, end ! 그 중간에있는 것은 모두 함수 몸체입니다. 코드가 호출 될 때 실행 된 코드. return 키워드는 함수가 실제로 유용한 출력을 제공하게합니다. 이 함수가 없으면 아무 것도 반환하지 않습니다. 이는 nil을 반환하는 것과 같습니다. 이것은 IO와 상호 작용하는 것들에 유용 할 수 있습니다. 예를 들면 다음과 같습니다 :

function printHello(name)
    print("Hello, " .. name .. "!");
end 

이 함수에서는 return 문을 사용하지 않았습니다.

함수는 조건부로 값을 반환 할 수도 있습니다. 즉, 함수가 아무 것도 반환하지 않도록 선택할 수 있습니다 (nil) 또는 값입니다. 이것은 다음 예제에서 설명됩니다.

function add(a, b)
    if (a + b <= 100) then
        return a + b -- Returns a value
    else
        print("This function doesn't return values over 100!") -- Returns nil
    end
end

다음과 같이 함수가 쉼표로 구분 된 여러 값을 반환 할 수도 있습니다.

function doOperations(a, b)
    return a+b, a-b, a*b
end

added, subbed, multiplied = doOperations(4,2)

또한 함수를 로컬로 선언 할 수 있습니다.

do
    local function add(a, b) return a+b end
    print(add(1,2)) --> prints 3
end
print(add(2, 2)) --> exits with error, because 'add' is not defined here

그들은 테이블에도 저장할 수 있습니다 :

tab = {function(a,b) return a+b end}
(tab[1])(1, 2) --> returns 3

함수 호출.

함수는 호출 할 수있는 경우에만 유용합니다. 함수를 호출하기 위해 다음 구문이 사용됩니다 :

print("Hello, World!")

우리는 print 함수를 호출합니다. "Hello, World" 인수 사용하기. 명백한 것처럼 이것은 출력 스트림에 Hello, World 를 출력합니다. 반환 된 값은 다른 변수와 마찬가지로 액세스 할 수 있습니다.

local added = add(10, 50) -- 60

변수는 함수의 매개 변수에서도 허용됩니다.

local a = 10
local b = 60

local c = add(a, b)

print(c)

테이블이나 문자열을 기대하는 함수는 구문 론적 설탕을 사용하여 호출 할 수 있습니다. 호출을 둘러싼 괄호는 생략 할 수 있습니다.

print"Hello, world!"
for k, v in pairs{"Hello, world!"} do print(k, v) end

익명 함수

익명 함수 만들기

익명 함수는 이름이없는 것을 제외하고 일반 Lua 함수와 같습니다.

doThrice(function()
    print("Hello!")
end)

보시다시피 print 또는 add 와 같은 이름에는 함수가 할당되지 않습니다. 익명의 함수를 만들려면 이름을 생략해야합니다. 이 함수는 인수를 취할 수도 있습니다.

통사론의 이해

다음 코드를 이해하는 것이 중요합니다.

function double(x)
    return x * 2
end

실제로는 단지 약식이다.

double = function(x)
    return x * 2
end

그러나 함수가 변수에 직접 할당되므로 위의 함수는 익명이 아닙니다 !

함수는 1 급 값입니다.

즉, 함수는 숫자와 문자열과 같은 기존 값과 동일한 권한을 갖는 값입니다. 함수는 변수, 테이블에 저장되고 인수로 전달 될 수 있으며 다른 함수에서 반환 할 수 있습니다.

이를 증명하기 위해 "반"함수도 만듭니다.

half = function(x)
    return x / 2
end

이제 우리는 두 변수 halfdouble 가지며, 둘 다 값으로 함수를 포함합니다. 두 함수에 숫자 4를 공급하고 두 결과의 합을 계산하는 함수를 만들고 싶다면 어떻게해야할까요?

우리는 sumOfTwoFunctions(double, half, 4) 와 같은이 함수를 호출하려고합니다. 이것은 double 함수, half 함수 및 정수 4 를 우리 자신의 함수로 제공합니다.

function sumOfTwoFunctions(firstFunction, secondFunction, input)
    return firstFunction(input) + secondFunction(input)
end

위의 sumOfTwoFunctions 함수는 함수가 인수 내에서 전달되고 다른 이름으로 액세스되는 방법을 보여줍니다.

기본 매개 변수

function sayHello(name)
    print("Hello, " .. name .. "!")
end

이 함수는 간단한 함수이며 잘 작동합니다. sayHello() 방금 호출하면 어떻게 될까요?

stdin:2: attempt to concatenate local 'name' (a nil value)
stack traceback:
    stdin:2: in function 'sayHello'
    stdin:1: in main chunk
    [C]: in ?

정확히는 위대하지 않습니다. 이 문제를 해결하는 방법에는 두 가지가 있습니다.

  1. 함수에서 즉시 반환합니다.

    function sayHello(name)
      if not (type(name) == "string") then
        return nil, "argument #1: expected string, got " .. type(name)
      end -- Bail out if there's no name.
      -- in lua it is a convention to return nil followed by an error message on error
    
      print("Hello, " .. name .. "!") -- Normal behavior if name exists.
    end
    
  2. 기본 매개 변수를 설정합니다.

    이렇게하려면이 간단한 표현식을 사용하면됩니다.

function sayHello(name)
    name = name or "Jack" -- Jack is the default, 
                          -- but if the parameter name is given, 
                          -- name will be used instead
    print("Hello, " .. name .. "!")
end

관용구의 name = name or "Jack" 때문에 작동 or 루아 단락에서. or 의 왼쪽에있는 항목이 nil 또는 false 이외의 항목이면 오른쪽이 평가되지 않습니다. 반면에 매개 변수없이 sayHello 가 호출되면 namenil 이되고 문자열 "Jack"name 할당됩니다. (이 관용구는 부울 false 가 문제의 매개 변수에 대한 합리적인 값인 경우 작동하지 않습니다.)

여러 결과

루아의 함수는 여러 결과를 반환 할 수 있습니다.

예 :

function triple(x)
    return x, x, x
end

함수를 호출 할 때이 값을 저장하려면 다음 구문을 사용해야합니다.

local a, b, c = triple(5)

이 경우 a = b = c = 5 됩니다. 또한 변수 목록의 원하는 위치에서 변수 _ 을 사용하여 반환 된 값을 무시할 수도 있습니다.

local a, _, c = triple(5)

이 경우 두 번째로 반환되는 값은 무시됩니다. 변수에 값을 할당하지 않아도 반환 값을 무시할 수도 있습니다.

local a = triple(5)

변수 a 에는 첫 번째 반환 값이 할당되고 나머지 두 개는 무시됩니다.

다양한 양의 결과가 함수에 의해 리턴 될 때, 그 안에 함수를 실행하여 테이블에 모든 결과를 저장할 수 있습니다.

local results = {triple(5)}

이렇게하면 results 테이블을 반복하여 함수가 반환 한 것을 확인할 수 있습니다.

노트

이는 다음과 같은 경우에 놀랄 수 있습니다.

local t = {}
table.insert(t, string.gsub("  hi", "^%s*(.*)$", "%1")) --> bad argument #2 to 'insert' (number expected, got string)

이는 string.gsub 가 2 개의 값을 반환하기 때문에 발생합니다 : 지정된 문자열과 교체 된 패턴의 발생 횟수 및 발생 된 총 일치 횟수입니다.

이를 해결하려면 다음과 같이 중간 변수를 사용하거나 put () 을 호출합니다.

table.insert(t, (string.gsub("  hi", "^%s*(.*)$", "%1"))) --> works. t = {"hi"}

이것은 호출의 첫 번째 결과 만 가져오고 나머지는 무시합니다.

변수의 개수

가변 인자

명명 된 인수

local function A(name, age, hobby)
    print(name .. "is " .. age .. " years old and likes " .. hobby)
end
A("john", "eating", 23) --> prints 'john is eating years old and likes 23'
-- oops, seems we got the order of the arguments wrong...
-- this happens a lot, specially with long functions that take a lot of arguments
-- and where the order doesn't follow any particular logic

local function B(tab)
    print(tab.name .. "is " .. tab.age .. " years old and likes " .. tab.hobby)
end
local john = {name="john", hobby="golf", age="over 9000", comment="plays too much golf"}
B(john)
--> will print 'John is over 9000 years old and likes golf'
-- I also added a 'comment' argument just to show that excess arguments are ignored by the function

B({name = "tim"}) -- can also be written as
B{name = "tim"} -- to avoid cluttering the code
--> both will print 'tim is nil years old and likes nil'
-- remember to check for missing arguments and deal with them

function C(tab)
    if not tab.age then return nil, "age not defined" end
    tab.hobby = tab.hobby or "nothing"
    -- print stuff
end

-- note that if we later decide to do a 'person' class
-- we just need to make sure that this class has the three fields
-- age, hobby and name, and it will be compatible with these functions

-- example:
local john = ClassPerson.new("John", 20, "golf") -- some sort of constructor
john.address = "some place" -- modify the object
john:do_something("information") -- call some function of the object
C(john) -- this works because objects are *usually* implemented as tables

인수 유형 검사

일부 함수는 특정 유형의 인수에서만 작동합니다.

function foo(tab)
    return tab.bar
end
--> returns nil if tab has no field bar, which is acceptable
--> returns 'attempt to index a number value' if tab is, for example, 3
--> which is unacceptable

function kungfoo(tab)
    if type(tab) ~= "table" then
        return nil, "take your useless " .. type(tab) .." somewhere else!"
    end

    return tab.bar
end

여기에는 몇 가지 의미가 있습니다.

print(kungfoo(20)) --> prints 'nil, take your useless number somewhere else!'

if kungfoo(20) then print "good" else print "bad" end --> prints bad

foo = kungfoo(20) or "bar" --> sets foo to "bar"

이제는 원하는 매개 변수로 함수를 호출 할 수 있으며 프로그램을 중단시키지 않습니다.

-- if we actually WANT to abort execution on error, we can still do
result = assert(kungfoo({bar=20})) --> this will return 20
result = assert(kungfoo(20)) --> this will throw an error

그렇다면 특정 클래스의 인스턴스로 무언가를 수행하는 함수가 있다면 어떻게 될까요? 클래스와 객체가 대개 테이블이기 때문에 type 함수가 'table' 을 반환하기 때문에 이것은 어렵습니다.

local Class = {data="important"}
local meta = {__index=Class}

function Class.new()
    return setmetatable({}, meta)
end
-- this is just a very basic implementation of an object class in lua

object = Class.new()
fake = {}

print(type(object)), print(type(fake)) --> prints 'table' twice

해결책 : 메타 테이블 비교

-- continuation of previous code snippet
Class.is_instance(tab)
    return getmetatable(tab) == meta
end

Class.is_instance(object) --> returns true
Class.is_instance(fake) --> returns false
Class.is_instance(Class) --> returns false
Class.is_instance("a string") --> returns false, doesn't crash the program
Class.is_instance(nil) --> also returns false, doesn't crash either

마감

do
    local tab = {1, 2, 3}
    function closure()
        for key, value in ipairs(tab) do
            print(key, "I can still see you")
        end
    end
    closure()
    --> 1 I can still see you
    --> 2 I can still see you
    --> 3 I can still see you
end

print(tab) --> nil
-- tab is out of scope

closure()
--> 1 I can still see you
--> 2 I can still see you
--> 3 I can still see you
-- the function can still see tab

일반적인 사용 예

function new_adder(number)
    return function(input)
        return input + number
    end
end
add_3 = new_adder(3)
print(add_3(2)) --> prints 5

고급 사용 예제

function base64.newDecoder(str) -- Decoder factory
    if #str ~= 64 then return nil, "string must be 64 characters long!" end

    local tab = {}
    local counter = 0
    for c in str:gmatch"." do
        tab[string.byte(c)] = counter
        counter = counter + 1
    end

    return function(str)
        local result = ""

        for abcd in str:gmatch"..?.?.?" do
            local a, b, c, d = string.byte(abcd,1,-1)
            a, b, c, d = tab[a], tab[b] or 0, tab[c] or 0, tab[d] or 0
            result = result .. (
                string.char( ((a<<2)+(b>>4))%256 ) ..
                string.char( ((b<<4)+(c>>2))%256 ) ..
                string.char( ((c<<6)+d)%256 )
            )
        end
        return result
    end
end


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow