[Lua] 함수의 내부

Lua Script 2018. 3. 28. 20:28

Introduction 
: 함수는 숫자나 문자열처럼 전역이나 지역변수에 또는 테이블에 넣을 수 있고, 함수에 인자로 전달이 가능하며, 다른 함수로부터 반환 받을 수도 있다. 

함수는 이름이 없다. 
??? 무슨말인가 하면, 우리가 알고 있는 함수의 이름은 사실 그 함수 주소값을 담고 있는 변수의 이름이다. 

a = {p = print}
a.p("Hello world") --> Hello World
print = math.sin   -- print는 이제 sin 함수를 참조
a.p(print(1))         --> 0.841470
sin = a.p            -- sin은 이제 print 함수를 참조
sin(10, 20)        --> 10 20

그렇다 사실
function foo (x) return 2*x end 문장은 
foo = function (x) return 2*x end 를 보기좋게 썻던 것 뿐이다. 


1. 클로저 
: 클로저는 익명함수 + 비지역 변수 이다. 
익명함수는 알겠는데 비지역 변수는 무엇? 

function newCounter()
    local i = 0
    
    return function ()  -- 익명 함수 
                    i = i + 1
                    return i
                end
end

c1 = newCounter()
print(c1()) --> 1 
print(c1()) --> 2

위 코드에서 c1이 참조하고 있는 익명함수가 호출되는 시점에는 newCounter() 호출이 끝난 상태이기 때문에 지역변수 i의 생명주기가 끝나 버린다. 그런데 어떻게 c1이 참조하고 있는 익명함수에서 지역변수 i를 사용할 수 있는거지?
그것은 블럭이라는 존재 때문이다. 블럭은 익명함수와 위 코드에서 지역변수 i의 값을 저장해서 가지고 있는 놈이라고 보면 된다. 
그럼 아래를 보자. 

c2 = newCounter()
print(c2()) --> 1
print(c1()) --> 3
print(c2()) --> 2 

c1과 c2는 서로 다른 블럭이기 때문에 위와같이 서로다른 인스턴스처럼 동작한다. 

사실 루아에서 우리가 함수라 부르며 호출하는 것들은 함수가 아니라 클로저 이다. 

클로저는 콜백 함수를 구현할 때도 유용하다. 예를들어, 계산기를 만들때 0~9 까지 유사한 버튼을 만들어야 하는데 이런 버튼을 다음과 같은 함수로 만들어 낼 수 있다. 

function digitButton (digit) 
    reutrn Button { label = tostring(digit),
                             action = function ()
                                               addToDisplay(digit)
                                           end
                            }
end

다음은 테이블에 함수를 저장하는 특별한 문법을 소개하겠다. 일반적인 값을 테이블에 넣을 때 사용하는 문법을 써도 되지만, 다음과 같이 사용해도 된다.

Lib = {} 
function Lib.foo (x, y) return x + y end 
function Lib.goo (x, y) return x - y end 




            

'Lua Script' 카테고리의 다른 글

[Lua] 메타테이블과 메타메서드  (0) 2018.03.28
[Lua] 반복자  (0) 2018.03.28
[Lua] 함수  (0) 2018.03.27
[Lua] 문장  (0) 2018.03.27
[Lua] 표현식  (0) 2018.03.27
Posted by 홍성곤
,

[Lua] 함수

Lua Script 2018. 3. 27. 21:31

Introduction
: 루아에서는 루아로 작성한 함수를 물론, C로 작성한(또는 호스트 애플리케이션에서 사용하는 다른 언어로 작성한) 함수도 쓸 수 있다. 실례로 루아 표준 라이브러리의 모든 함수는 C로 작성한 것이다. 

function 함수이름 (매개변수)
    몸체
end

매개변수의 개수와 호출시 전달되는 인자의 개수가 다르면 남는 인자는 버려지고 인자가 모자란 경우에는 해당 매개변수는 nil이 된다. 

1. 여러 값 반환
: lua의 함수는 여러값을 반환할 수 있다. 

function multiReturn(a) 
    return a, a+1
end

local b, c = multiReturn(1)
print(b c) --> 1 2

함수의 반환값과 반환값을 저장하려고 하는 변수의 갯수가 틀린 경우 동적으로 처리해 주는 부분에 대해서 알아 보겠다. 

function foo0() end
function foo1() return "a" end
function foo2() return "a", "b" end

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
print(foo2() .. "x") --> ax
t = {foo0(), foo2(), 4} -- t[1] = nil, t[2] = "a", t[3] = 4

테이블 생성자는 함수가 반환하는 값을 개수 조정 없이 모두 받아간다. 
t = { foo0() } -- t = {}
t = { foo1() } -- t = {"a"}
t = { foo2() } -- t = {"a", "b"}

다음과 같은 형태도 가능하다. 
function foo(i)
    if i == 0 then return foo0()
    elseif i == 1 then return foo1()
    elseif i == 2 then return foo2()
end

print(foo(0)) --> nil
print(foo(1)) --> a
print(foo(2)) --> a b
print(foo(3)) --> nil

반환값 중에서 딱 하나를 받으려면 다음처럼 ()로 감싸면 된다. 
print((foo0())) --> nil
print((foo1())) --> a
print((foo2())) --> a

* f(g()) 에서 함수 f의 인자 개수가 정해져 있다면, g가 반환하는 개수가 f에 맞게 맞춰진다. 

table.unpack은 다중 반환을 해주는 특수 함수다. 인자로 받은 배열의 원소를 index 1의 원소부터 모두 다중반환 한다. 
a, b = table.unpack({10, 20, 30}) -- a = 10, b = 20 이고 30은 버려짐

unpack을 이용하면 동적으로 어떤 함수든지 임의의 인자로 호출할 수 있다. 
f(table.unpack(a)) -- f는 함수이고 a는 가변 개수의 인자를 담고 있는 배열이다. 

다음과 같이 길이지정도 가능하다. 
print(table.unpack({ "Sun", "Mon", "Tue", "Wed" })) -> Mon Tue 


2. 가변 인자 함수 
: 루아 함수는 가변 인자를 받을 수 있다. 

function luaPrint(...)
    for index, value ipairs {...} do
        print(value)
    end
end

luaPrint(1, 2, 3) --> 1 2 3

가변 인자를 table.pack 으로 묶어서 테이블로 저장 가능하다. 

function a(...)
    local packedTable = table.pack(...)
end


'Lua Script' 카테고리의 다른 글

[Lua] 반복자  (0) 2018.03.28
[Lua] 함수의 내부  (0) 2018.03.28
[Lua] 문장  (0) 2018.03.27
[Lua] 표현식  (0) 2018.03.27
[Lua] 타입과 값  (0) 2018.03.27
Posted by 홍성곤
,

[Lua] 문장

Lua Script 2018. 3. 27. 20:57

1. 제어 구조
1) 조건문

if  a < 0 then 
    a= 0
end

if a < 0 then
    a = 0
elseif a == 0 then
    a = 1
else 
    a = -1
end

위처럼 사용한다. 

2) while문

while true do
    print("while")
end 

3) repeat-until문 
: 몸체를 실행한 다음 조건을 검사하기 때문에, 몸체가 한 번은 꼭 실행된다. 

repeat 
    line = io.read()
until line ~= ""
print(line)

위 코드는 빈 줄이 아닌 첫 줄의 내용을 출력하는 것이다. 즉, until 조건을 만족할때까지 몸체 부분을 계속 수행한다.

4) for문
1- 수치 for문

for var = exp1, exp2, exp3 do
    <something>
end

위 코드는 var의 값을 exp1에서 시작해서 exp2까지 exp3만큼 증가시키면서 <something>을 실행한다. exp3은 생략 가능하다. 생략하는 경우에는 1씩 증가한다. 
제한 없이 반복하고 싶은 경우에는 math.huge 상수를 쓰면 된다. 

2- 일반 for 문

for key, value pairs(t) do 
    print(k, v)
end

위 코드는 테이블 t의 모든 key, value 값을 출력하는 것이다.





'Lua Script' 카테고리의 다른 글

[Lua] 함수의 내부  (0) 2018.03.28
[Lua] 함수  (0) 2018.03.27
[Lua] 표현식  (0) 2018.03.27
[Lua] 타입과 값  (0) 2018.03.27
[Lua] 기본 문법  (0) 2018.03.27
Posted by 홍성곤
,