반응형

Linked List, 참으로 필요한 것이죠.

그러나 lua 코딩을 하다보면 별 필요는 없습니다.

그 이유는 루아를 사용하여 그렇게 큰 데이터 리스트를 만들 이유가 많지 않고 또한 table 자체를 사용하면

제한 없이 정보를 보관할 수 있기 때문입니다.

 

하지만, 이론은 알고 넣어가야죠..

 

루아에서 Linked List 의 구현은 매우 쉽습니다. 그 이유는 루아의 table 이 dynamic entity (동적 요소??) 를 다루고 있기 때문이죠. 배열과 같이 정적인 메모리를 잡아서 사용하는 것이 아니라는 것이죠.

 

흔히 linked list 는 next 와 value 가 있습니다. next 는 해당 요소의 뒤에 따라오는 요소이고 value는 해당 요소에 저장하는 값이 되겠죠.

 

일단 list 는 root 가 있어야 합니다.

 

list = nil

 

이제 리스트의 가장 앞에 값 v 를 추가하는 것을 생각해 봅시다.

 

list = {next=list, value = v}

 

위와 같이 하면 list.next 가 있을 것이고, list.value 가 있을 것입니다.

list.next 는 추가되기 전의 가장 마지막의 위치가 되겠죠.

 

이렇게 계속 넣다보면 리스트의 구조를 가지게 됩니다. 마지막에 들어간 것이 물론 root 가 되어지는 것이니,

reverse list 라고나 할까요?

 

이제 이러한 list 를 순회해 봅시다. 여기서 순회란 리스트의 모든 요소를 한번 훓어서 본다 라고 생각하시면 됩니다.

iterator 에 대해서 살펴본적이 있습니다. 그와 유사한 개념 입니다.

 

    local l = list
    while l do
      print(l.value)
      l = l.next
    end

 

이들을 합쳐서 다음과 같이 테스트 해 봅니다.

 

list = nil

list = {next=list, value=10}
list = {next=list, value=20}

 

local l = list
   while l do
      print(l.value)
      l = l.next
   end

 

 

결과

20
10

앞서 말했듯이 뒤에 추가된것이 먼저 나오게 되었습니다. reverse 된 리스트라 생각하시면 됩니다.

이러한 응용에 의하여 순방향 리스트도 쉽게 구현이 가능합니다.

반응형

루아의 테이블의 활용은 막힘이 없습니다.

앞서 우리는 테이블을 이용하여 배열을 만들어 보는 것을 알아 보았습니다.

이제 2차원 배열을 알아보도록 하겠습니다.

 

    mt = {}          -- create the matrix
    for i=1,N do
      mt[i] = {}     -- create a new row
      for j=1,M do
        mt[i][j] = 0
      end
    end

위와 같이 할 경우, 물론 N 과 M 은 그 값이 미리 선언이 되어 있어야 겠지요, M*N 의 2차원 배열이 만들어 집니다.

이는 테이블의 각 요소를 테이블로 정하는 방법으로 구현한 것 입니다.

즉 mt 에 들어가는 것은 다른 배열의 row 로 사용할 또 다른 배열인 것 입니다.

 

위와 같은 경우 꼭 집어서 M*N 행이 아닐 수 있습니다. 희소행렬(Sparse matrix)의 형태가 되겠죠.

M*N 행렬이면  1열의 크기와 2열의 크기가 같아야 되지만 위의 경우 각 열이 또다른 table 이기 때문이고, table은 그 특성상

각각의 크기를 가질 수 있기 때문에 희소행렬로 보아야 할 것 입니다.

 

다음과 같은 것을 살펴봅시다.

 

    mt = {}          -- create the matrix
    for i=1,N do
      for j=1,M do
        mt[i*M + j] = 0
      end
    end


이는 전체적으로는 테이블이 하나만 생성 됩니다. 즉 1차원적인 테이블을 i , j 행렬의 계산에 의하여 2차원화 된 형상 입니다.

앞의 것 보다 사용하기는 다소 불편할지는 몰라도 M*N 행렬을 정확히 처리함은 의심의 여지가 없습니다.

 

아무튼 루아의 table을 이용한 다차원 행렬은 sparse matrix 에 적합한 구조를 제공하고 있습니다.

반응형

루아에서 배열 (Array) 은 어떻게 사용하는지를 알아 보겠습니다.

 

이미 lua table 의 사용법을 아시는 분은 이미 알고 있는 내용 입니다.

 

    a = {}    -- new array
    for i=1, 1000 do
      a[i] = 0
    end

위의 코드는 a 라는 것은 table 로 만들 어지게 됩니다 (여기서는 array 라고 여김)

a 라는 테이블에 키를 1 부터 1000 까지 바꾸면서 0의 값을 설정하는 코드 입니다.

 

table 은 대괄호 [ ] 에 의하여 key 인덱싱 될 수 있습니다. 여기서 key 인덱싱은 특정한 메모리 위치는 아닙니다.

즉 c 에서의 배열과 다릅니다.

 

그러므로 다음과 같은것이 가능 합니다.

 

a = {}

a[-1] = 20

 

print(a[-1])

 

즉 [] 안에 들어가는 것은 배열적인 인덱스가 아니라 그냥 어떤 데이터를 보관하는 장소에 대한 키 값으로 사용되는 것 입니다.

 

 

    -- creates an array with indices from -5 to 5
    a = {}
    for i=-5, 5 do
      a[i] = 0
    end

배열은 다음과 같이 초기화 할 수 도 있습니다.

 루아스크립트/루아/웹/웹프로그래밍/Lua

squares = {1, 4, 9, 16, 25, 36, 49, 64, 81}

이는

 

square[1] = 1

square[2] = 4

square[3] = 9

square[4] = 16

square[5] = 25

square[6] = 36

square[7] = 49

square[8] = 64

square[9] = 81

 

과 같은 뜻 입니다. 즉 인덱스가 1 부터 순차적으로 1씩 증가하면서 보관되게 되는 것 입니다.


반응형

for 문에 사용할 iterator 함수를 사용자가 직접 만들 수 있습니다.

 

다음의 내용은 lua-users wiki 에 있는 사용자 iterator 함수의 pseudo-code 입니다.

 

-- Equivalent to "for var1, ···, varn in explist do block end"
do
  local iterator, state, var1 = explist
  local var2, ... , varn
  while true do
    var1, ..., varn = iterator(state, var1)
    if var1 == nil then break end
      -- for block code
  end
end

 

좀 어려우니 예제를 살펴봅시다.

 루아스크립트,web,프로그래밍,웹프로그래밍,웹

function square(state,n) if n<state then n=n+1 return n,n*n end end
for i,n in square,5,0 do print(i,n) end

결과

1 1
2 4
3 9
4 16
5 25

위의 코드를 보면 square 라는 iterator 용으로 사용할 함수를 하나 만들었습니다.

이 함수를 for 문에 적용하여 iterator 역할을 수행하도록 만든 것 입니다.

 

square 함수는 state 와 n 이라는 인수를 받아서 n 이 state 보다 작을때는 n=n+1 을 해주고 return 으로

n 과 n*n 을 돌려줍니다. 2개의 값을 돌려주며, 루아에서는 함수가 한개 이상(다수의) return을 할 수 있다는 것을

알기 바랍니다. 어쨌든 위의 경우 n 과 n*n 즉 n의 제곱을 돌려주고 있습니다.

 

이 함수를 for 문의 iterator로 사용하였습니다.

 

in square,5,0 이라는 부분이 iterator 부분을 구성합니다.

 

즉 square 함수를 state = 5, n = 0 으로 초기화 하여 지속적으로 호출해 줍니다.

단 명심해야 할 것은 square 함수 자체가 지속적으로 호출되는 것이 아닙니다.

다시 말해 square 함수가 호출되면 지속적으로 함수에 인수가 전달되어야 겠죠. 그러나 이렇게 지속적으로 인수가 전달되는

것이 아닙니다. 인수는 처음에만 전달되고, 그 상태가 지속적으로 그 후에도 남게 됩니다.

 

잘보시면 square 함수의 인수에 n 이라는 변수가 있습니다. 인수로 사용한 변수이지요.

또한 for 문에 보면 i,n 에  역시 n 이라는 변수가 사용됩니다.

 

이 두게 모두 local 변수이므로 서로 다른 변수 인것을 알아야 합니다.

 

위의 코드를 분석하면 , for 문에 들어가 square 함수가 호출되어 state 및 n 에 각각 5 와 0 이 할당되어지고

square 함수의 내부계산에 의하여 return 되는 두개의 값(n,n*n) 이 각각 for 문의 i,n 에 전달되게 되어

for 문의 블럭인 print(i,n) 에서 i 와 n 즉  n,n*n 이 출력되어지고 다시 square 내부 계산이 이루어지며

조건에 맞을때 다시 n,n*n 이 return 되어 집니다.

 

조건이 만족하지 못하면 square 문은 아무것도 return 하지 않고 함수 자체가

종결이 되며 for 문의 i,n 은 nil 의 값을 받게 되어서 결국 for 문이 종료되게 되어 있습니다.

 

좀 복잡하지만, 또한 논리적으로 이해하기 힘들 수 있습니다만, 이것이 루아의 특징이라고 생각하시기 바랍니다.

 

function squares(nbvals) return square,nbvals,0 end  -- iterator,state,initial value


for i,n in squares(5) do print(i,n) end
1       1
2       4
3       9
4       16
5       25

위와 같이 squares 라는 함수를 다시 하나 더 만들어 pairs 또는 ipairs 와 같이 일반적인 iterator 함수와 같은 역할을

수행하는 함수를 만들어 사용할 수 도 있습니다.

반응형

루아는 특별히 지정하지 않는 변수는 global 변수로 지정됩니다.

그러나 함수의 인수로 사용하는 변수는 해당 함수에서만 사용되는 local 변수 입니다.

 

function f(a)

 print(a)

end


f(10)
print(a)

 

그런 이유에서 위의 코드를 실행시켜 보면

 루아스크립트,웹,프로그래밍,웹프로그래밍,web,lua

10
nil

이 나옵니다.

 

이와 마찬가지로 for 문과 같은 제어문에 사용하는 변수도 해당 for loop 에서만 사용할 수 있는 local 변수가 됩니다.

 

for i=0,5 do print(i) end

print(i)

 

결과

0
1
2
3
4
5
nil

 

위와 같은 경우에 for 문의 i는 for 문 안에서만 유효하며

for 문 밖에서는 다른 변수가 됩니다.

 

+ Recent posts