본문 바로가기
카테고리 없음

LUA 살펴보기..2

by 철이아부지 2008. 12. 16.

http://www.lua.org/pil/index.html 

함수 부분 부터 계속 보자

 

Function

함수는 lua에서 추상화를 지원하는 기본 메카니즘이다. 넘겨줄 argument가 없어도 호출시에는 꼭 ()를 사용해야 한다.

lua에서는 객체 지향적 호출 방법을 : 을 통해 제공한다. o:foo(x) 또는 o.foo(o, x) 로 쓸수 있다. 점을 사용하는 경우는 자기 자신을 먼저 던져줘야 하는군.

절차형 언어에서 객체 지향을 흉내내기 위한 편법을 여기서도 쓰네;;;

함수 선언은 다음과 같이 한다

function 함수명(인자)

    return 반환값1, 반환값2;

end

 

헉. return 이다. loop에서 C의 continue처럼 쓴다더니. 헷갈리네. 확인해보니 매뉴얼을 설겅설겅 읽어서 break와 return이 함께 다뤄져서 오.해.(그분이 즐겨 쓰시는..) 를 한듯 하다.

function func(a,b,c) 가 있을때 func(1,2) 로 호출하면 a == 1, b == 2, c == nil 이 된다. func(1,2,3,4)로 하면 4는 무시된다.

return에서 반환값을 콤마로 구분하여 여러개 던지면 여러개 넘어간다.

unpack을 사용하면  table 구조로 된 변수 안에 것을 각각의 인자로 던져준다. 뭐가 좋은지는 나중에 써보면 알겠지..

 

가변 개수 인자

... 을 사용하면 가변 개수의 인자를 받을 수 있다. print 함수 같은 경우처럼..

입력된 값은 arg라는 table 타입의 로컬 변수로 넘어오니까 for문으로 디비면서 처리하면 된다. table은 인덱스가 1부터 시작한다는걸 잊지 말자!

... 을 다른 함수로 던지려면 어떻게 하면 될까? unpack(arg)을 사용하면 된다. ^^;

여러 반환값중 특정 이후 데이터만 사용할때는 select함수를 사용하면 편리하다. select(시작인덱스, 값의 배열) 형식으로 사용한다.

select( 3, 1, 2, 3, 4 ) == 3, 4 이다.

 

이름을 가지는 인자

함수를 호출할때 {} 를 이용하여 table 값을 인자로 던져 버릴수 있다. 함수측에서는 arg 변수를 통해 받아 처리하게 된다.

function who( arg )

    print( arg.id..":"..arg.name );

end

 

who{ id="jjlee", name="joonjolee"}

이런식으로 쓰는데 복잡한 인자를 던질때 쓸만하려나.

 

함수는 변수로 할당 될수 있다.

아까 만든 who 함수의 경우 a.func1 = who; 이렇게 할당해두고 a.func1 해서 함수를 호출할 수 있다. a:func1 하면 첫번째 인자로 a 자체가 전달된다.

위의 방법을 편법 이용하여 객체 지향 처럼 사용할 수 있다만.. 사용자 측면에서는 기존 언어와 달라 헷갈리다. 쩜. 을 이용한 호출은 보통 객체의 멤버를 콜하는 것이고, 콜론 : 을 이용한 호출은 스태틱 멤버를 콜하는 것인데.. 이건 두개가 바뀌어 있는 기분

 

함수 자체를 인자로 던질때는 익명 함수도 사용 가능하다. function(인자) end 이런식으로 함수를 정의한다. (함수명이 없당.)

 

포함된 함수

함수안에 함수를 넣을 수 있는데 해당 함수는 겉의 함수의 local 값에 접근할 수 있다. 하지만 외부에서는 접근 못한다. (ㅡ.ㅡ;; 그냥 객체지향 하지 마라. 이건 편법 난무다.)

간단한 소스를 보자..

function newCounter()

    local count = 1;

    return

        function()

            count = count + 1;

            return count;

        end

end

 

c = newCounter() 라고 호출하면 c에는 반환된 익명 함수가 들어간다. c() 로 호출 하면 해당 함수가 콜 되는데, 재밌는 점은 count 라는 로컬 변수는 해당 익명 함수에서는 접근이 가능하지만 외부에서는 접근이 안된다는 것이다.

 

컴파일과 실행 그리고 오류

lua는 인터프리팅 언어로, 적재하는 시점에서 precomile 한 후 실행한다.

dofile을 이용하면 다른 루아 파일을 적재하여 실행한다. 반면 loadfile을 사용하면 적재후 실행하지 않는다. 적재하면 fuction으로 반환되니까 call하면 실행된다. dofile을 쓰는 것 보다 loadfile을 쓰면 적재하지 못했을때의 예외 처리 등 여러가지를 할 수 있다. loadstring을 사용하면 파일이 아니라 문자열로 부터 코드를 읽어 함수로 반환한다. loadstring과 loadfile은 오류를 발생시키지 않으며 결과값이 nil인지 여부를 파악하여 오류를 확인할 수 있다.

 

require

lua에서 라이브러리를 적재 실행하기 위해서 require 명령어를 사용한다. dofile과 비슷해 보이긴 하지만 다른점이 있다.

1. require는 지정된 경로에서 파일을 검색한다.

2. 중복 실행되지 않는다. 이미 적재 되어 있으면 적재하지 않는 다는 이야기.

위와 같은 특성때문에 require는 라이브러리 적재에 적합하다.

 

require는 LUA_PATH라는 환경 변수에 지정된 경로들에서 파일을 찾는다. 경로는 ; 로 구분하며, 파일명 대신에 ?를 넣는다.

?;?.lua;c:\lua\lib\?;c:\lua\lib\?.lua 라고 되어 있다고 하면 require "test" 라고 했을때

현재 경로에서 test, test.lua, c:\lua\lib\test, c:\lua\lib\test.lua 순으로 파일을 검색하여 적재한다.

적재된 파일은 _LOADED table 변수에서 확인할 수 있다. 위의 예에서 test 적재가 끝났으면 _LOADED["test"] 에는 nil이 아닌 값이 들어간다.

 

딸내미 인터럽트로 나머지는 내일~