사용자 도구

사이트 도구


kb:luaglossary

차이

문서의 선택한 두 판 사이의 차이를 보여줍니다.

차이 보기로 링크

kb:luaglossary [2014/11/06 17:18] (현재)
줄 1: 줄 1:
 +====== Lua Glossary ======
 +루아에서 나오는 여러 가지 용어들에 대해 정리해보고자 한다. C랑 루아랑 서로 호출하는 것도 좋지만, 루아라는 언어 자체에 대해서 좀 심도있게 알지 못하니, 바깥쪽만 맴도는 느낌이 들었기 때문이다.
 +
 +
 +====== First-class function ======
 +함수를 변수에다 할당하거나,​ 리턴값으로 반환할 수 있는 기능을 말한다. 루아에서는 함수가 명시적인 이름을 가지지 않고, 오로지 변수를 통해 액세스된다. 그러므로 이름을 바꾸거나,​ 삭제가 가능하다. 이를 이용해 HigherOrderFunction이나 FunctorObject를 간단하게 구현할 수 있다.
 +
 +<code lua>
 +function new_function()
 +    return function(msg)
 +        print(msg .. " World"​)
 +    end
 +end
 +
 +a = print
 +a("​Hello"​)
 +a = new_function()
 +a("​Hello"​)
 +</​code>​
 +
 +====== Lexical Scoping, Upvalue or External Local Variable, Closure ======
 +internal 함수가 external 함수 안에서 정의되었을 때, internal 함수는 external 함수의 지역 변수를 모두 액세스할 수 있다. 이런 기능을 **lexical scoping**이라고 한다. 루아는 lexical scoping을 지원한다. 다음과 같은 예를 생각해 보자.
 +<code lua>
 +function external()
 +    local i = 0
 +    return function() -- 무명(anonymous) 함수
 +        i = i + 1
 +        return i
 +    end
 +end
 +</​code>​
 +무명 함수 안에서 external 함수 안에 있는 i 변수를 액세스하고 있다. 이 경우 무명 함수에게 있어 i는 전역 변수도 아니고, 그렇다고 지역 변수도 아니다. 이런 변수를 **external local variable**, 또는 **upvalue**라고 부른다.
 +
 +위의 예에서 계속해서,​ external 함수를 호출해 함수 객체를 변수에다 저장한 다음, 저장한 함수를 호출했다고 하자.
 +<code lua>
 +f = external()
 +f()
 +</​code>​
 +f 함수, 즉 무명 함수를 호출하는 시점에서 i 변수는 이미 존재하지 않는다. 그렇다면 무명 함수는 어디서 i 변수를 찾아야 하는가? 루아는 이를 처리하기 위해 **closure**라는 개념을 도입했다. 즉 closure란 **함수 + 그 함수에서 액세스하는 external local variable들의 집합**이다.
 +
 +그렇다면 external 함수를 여러번 호출하면 어떻게 되는가?
 +<code lua>
 +f = external()
 +g = external()
 +</​code>​
 +f와 g는 서로 다른 closure, 즉 서로 다른 external local variable들을 가지게 된다. 즉 f 함수를 계속 호출해 i 값을 증가시키더라도,​ g 함수의 i 변수와는 아무런 상관이 없다는 말이다.
 +
 +
 +====== Tail Call or Proper Tail Recursion ======
 +테일 콜은 임의의 함수가 다른 함수(자기 자신도 포함)를 마지막 명령(instruction)으로 호출하는 경우를 말한다. 다음과 같은 경우에 테일 콜이 일어난다.
 +<code lua>
 +function f(x)
 +    return g(x)
 +end
 +</​code>​
 +f 함수가 g 함수를 호출한 후에는 더 이상 할 일이 없다. 즉 g 함수를 호출한 다음에 f 함수로 돌아올 필요가 없다는 말이다. 따라서 f 함수에 대한 정보를 스택에다 보관할 필요가 없다. 루아는 이 사실을 적용해서 테일 콜을 실행할 때는 스택 공간을 사용하지 않는다.
 +
 +그렇다면 이것이 의미하는 바는 무엇인가?​ 바로 무한 재귀 호출이 가능하다는 말이다. 테일 콜만으로 이루어진 함수의 경우, 무한으로 재귀호출을 해도 스택 오버플로가 일어나지 않는다. 아래의 함수가 좋은 예이다.
 +<​code>​
 +function foo(n)
 +    if n > 0 then return foo(n-1) end
 +end
 +</​code>​
 +마지막 함수를 호출한 다음 할 일이 아무 것도 없어야 테일 콜이라는 것을 상기하면 다음의 구문들이 테일 콜이 아니라는 것을 알 수 있을 것이다.
 +<code lua>
 +return g(x) + 1  -- 더하기 연산을 해야 한다.
 +return x or g(x) -- 둘 중에 하나를 골라 리턴해야 한다.
 +return (g(x)) ​   -- g(x)의 반환값 중에 하나를 골라 리턴해야 한다.
 +</​code>​
 +즉 루아에서 테일 콜 구문의 포맷은 반드시 <​nowiki>​return g(인수들...)</​nowiki>​의 형태를 가져야한다. 그러므로 다음과 같은 구문은 테일 콜이다.
 +<code lua>
 +return x[i].foo(x[j] + a*b, i+j)
 +</​code>​
 +
 +====== Coroutine ======
 +스레드와 비슷한 개념이다. 각각 자신만의 스택과 지역 변수 등을 가지고 있고, 전역 변수는 서로 공유한다. 단 스레드는 알다시피 동시에 실행되나,​ 코루틴은 그렇지 않다. 즉 한 순간에 하나의 코루틴만이 실행된다. 다른 코루틴을 실행하기 위해서는 현재 실행 중인 코루틴의 동작을 중지시켜야 한다. 또한 외부에서 코루틴의 동작을 중지시킬 수 없다. 비선점형(Non-preemptive)이라는 말이다.
 +
 +
 +====== Metatable & Metamethod ======
 +메타 테이블은 테이블의 동작을 정의하는 테이블이다. ​
 +
 +굳이 비슷한 걸 들자면, C++의 오퍼레이터 오버로딩을 들 수 있겠다. C++에서 임의의 클래스를 만든 경우, 기본적으로 "​+"​ 연산이 불가능하다. 하지만 "​+"​ 연산자를 재정의해주면 가능해진다. ​
 +
 +루아에서도 테이블의 경우, 기본적으로는 "​+"​ 연산이 불가능하다. 그러나 테이블에 임의의 메타 테이블을 설정하고,​ 그 메타 테이블에 <​nowiki>"​__add"</​nowiki>​ 필드를 정의해 주면, "​+"​ 연산도 가능해진다. <​nowiki>"​__add"</​nowiki>​ 필드에 들어가는 함수, 즉 메타 테이블에 들어가는 함수를 메타 메서드라고 부른다.
 +
 +
 +====== Protected mode ======
 +보호 모드가 아닐 경우, 루아 내부에서 문제가 생기면, 루아 컨텍스트 자체가 오염될 수 있다. 컨텍스트 자체가 오염된 경우, 더 이상 스크립트를 실행할 수 없다. 경우에 따라서는 호스트 프로그램이 종료될 때도 있다. ​
 +
 +보호 모드에서는 문제가 생겨도, 컨텍스트가 오염되지 않는다.
 +
 +C 함수는 논외다. 루아에서 호출한 C 함수 내부에서 에러가 발생한 경우, 루아가 할 수 있는 일은 거의 없기 때문이다.
 +
 +
 +====== Weak Table ======
 +테이블 안에 오브젝트(함수,​테이블,​풀 유저데이터)가 들어있는 경우, 그 오브젝트는 테이블이 사라지지 않는 이상, 기본적으로 가비지 컬렉션의 대상이 되지 않는다. 위크 테이블을 이용하면 테이블 안의 오브젝트도 가비지 컬렉션의 대상이 되도록 할 수 있다.
 + 
 +임의의 테이블을 위크 테이블로 만들기 위해서는 메타테이블과 __mode 메타메서드를 설정해줘야한다. 자세한 것은 [[LuaGarbageCollection]] 페이지에...
 +----
 +  * see also [[Lua]]
  
kb/luaglossary.txt · 마지막으로 수정됨: 2014/11/06 17:18 (바깥 편집)