반응형

Iterator 에 대하여 알아봅시다.

 

C 의 STL 을 아시는 분은 iterator 가 무엇인지를 이해하실 것 입니다.

모르시는 분들을 위하여 잠시 여기에 소개하고자 합니다.

 

Iterator 란?

배열,리스트,큐,스텍 등등 어떠한 데이터 요소들을 다수 넣어 놓고 프로그램에서 이를 접근 운영하는 경우가 많습니다.

이러한 것을 container (컨테이너) 라고 합니다. 즉 데이터들을 담아 놓는 공간이라 생각하시면 됩니다.

 

이러한 컨테이너에 다수의 데이터들을 넣어 보관하다가 , 이 데이터들을 하나하나 순차적으로 접근할 필요가 있을때가 있습니다.

즉 데이터들을 하나하나 찾아다니며 돌아다니는 녀석이 바로 iterator (연속방문자? 정도로 해석) 라 합니다.

iterator 의 형태는 컨테이너의 자료구조에 의하여 정해집니다. 자료구조는 리스트의 구조와 트리의 구조가 있겠죠.

 

어찌됬든 이러한 방문자를 이용하여 루아의 for 문을 완성할 수 있습니다.

for 문은 일반적으로 어디서부터 어디까지 어떻게 증가하여 정해진 프로그램 블럭을 수행한다.. 라는 의미로 사용되죠.

 

여기서 iterator 를 이용하면 어디서부터 어디까지라기 보다는 해당 컨테이너(루아의 테이블)에 보관되어 있는 데이터들을 하나하나 방문하면서 for 루프를 돌리는 형태로 수행될 수 있습니다.

 

iterator를 이용하는 for loop 의 문법은 다음과 같습니다.

 

for var {, var} in explist do block end

 

여기서 explist 는 루프에 들어가기 전에 평가하는 함수 입니다. 이를 iterator function 이라 합니다.

 

다음의 함수들이 루아 테이블에서 iterator function 으로 사용되어 집니다.

 

pairs(table)

 

pairs() iterator 함수는 주어진 테이블의 key-value 쌍을 모두 처리 합니다.

인덱스에 의한 순차적인 테이블 뿐만 아니라 그렇지 않은 모든 key-value 쌍을 처리 하는 것 입니다.

 

for key,value in pairs(t) do print(key,value) end
3       10
1       3
4       17
2       7
pi      3.14159
banana  yellow

 

 

위와 같이 table t 에 있는 모든 key-value 쌍을 처리하며 , key 에 의한 순차적인 순서(order) 를 지키지 않습니다.

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

 

ipairs(table)

 

이 함수는 pairs 함수와는 다르게 순차적인 key order 를 처리 합니다. 즉 순차적이지 않은 key 에 대해서는 처리하지 않습니다.

 

for index,value in ipairs(t) do print(index,value) end
1       3
2       7
3       10
4       17

 

위에서와 같이 table t 에 있는 key-value 쌍중에 순차적인 인덱스로 이루어진 데이터들에 대해서만 순차적으로 처리하게 됩니다.

 

순차적이면서 순차적이지 않은 모든 key-value에 대하여 처리하고자 한다면 다음과 같이 사용하면 됩니다.

 

for key,value in next,t,nil do print(key,value) end


1       3
2       7
3       10
4       17
pi      3.14159
banana  yellow

이러한 형태는 next 함수를 사용하는 것 입니다. 위의 문장은 next 함수로 t 를 처리하며 nil 이 될때까지 진행 합니다.


반응형

루아에서의 for 문은 크게 두가지의 형태로 생각해 볼수 있습니다.

  1. 인덱스 증감에 의한 데이터 접근 (Numeric progression)  -- numeric for 문이라 함
  2. Iterators (반복자) 에의한 데이터 접근 (Iterators)            -- generic for 문이라 함

Numeric Progression

 

Numeric progression 에 의한 접근은 다음과 같은 문법을 갖습니다.

 

for variable = from_exp , to_exp [, step_exp] do block end

이러한 형태에서는

variable 이 for 문을 들어가기전에 from_exp 에 의하여 초기화 되며, to_exp 가 될때까지 진행 하며

block 문이 수행 됩니다.

각 block 문이 수행된 후 step_exp 만큼 variable 은 중감하게 되어 to_exp 까지 도달하게 됩니다.

만약 step_exp 가 생략될 경우 1로 간주 하게 되어 1씩 증가하게 되는 것 입니다.

 

for i = 1,3 do print(i) end

 

결과

1
2
3

 

for i = 3,1 do print(i) end

 

와 같이 하면 for문은 돌지 않습니다.

c 에서 생각한다면 무한루프의 소지가 있습니다만, 루아에서는 그렇지 않습니다.

 

for i = 3,1,-1 do print(i) end

 

결과

3
2
1

 

 

for i=1,0,-0.25 do print(i) end

 

결과

1
0.75
0.5
0.25
0

 

와 같이 증감을 실수를 사용할 수 도 있습니다.

 

위의 예들에서 순차적 증가값으로 i 라는 변수를 사용하게 됩니다. 이 변수는 local 로 변수입니다.

for 문에 사용된 증감 변수는 local 이라 지정하지 않아도 자동적으로 local 변수로 처리 됩니다.

 

for i=1,0,-0.25 do print(i) end

print(i)

 

를 수행하면

1
0.75
0.5
0.25
0
nil

와 같이 i 값이 nil 이 됩니다. 즉 for 문의 i 와 print(i) 의 i 가 다르다는 것이죠.

 

 

for i = e1,e2,e3 do myFunction(i) end

와 같이 변수를 사용할 수도 있습니다.

반응형

좀 의아해 할 수 있습니다만, 다음의 예를 살펴보죠.

 

t = { [function(x) print(x) end] = "foo" }
for key,value in pairs(t) do key(value) end


 

위에서 보면 t 라는 테이블은 function(x) print(x) end 라는 함수 즉  x 를 인수로 받아 이를 consol 에 출력하는 함수 입니다.

이 함수 자체가 키가 됩니다. 그러면서 이 키에 설정된 값이 "foo" 입니다.

 

그러면 for 문에 의해서

 

일단

 

key,value in pairs(t)

 

에 의하여 테이블 t 에 있는 key 와 value 를 가져오게 되겠죠.

여기서 key 는 결국 앞어서 말한 함수가 됩니다. 그리고 value 는 "foo" 라는 값이 되겠죠.

 

do key(value)

 

에 의하여 결국 key 라는 함수 , 즉 앞에 키로 넣은 함수 에 value 를 인수로 호출한 것이 됩니다.

 

function(value) 이렇게 되겠죠.

 

결국 value 가 화면에 찍히게 됩니다.

 

과연 이런것을 어디에 사용할 까요?

 

다수의 값이 있고 그 값을 처리하는 함수가 각각 따로 있다고 생각해보죠.

이들을 하나의 테이블에 보관하여 관리할 수가 있겠죠.

 

이런정도의 용도,, 약간의 OOP 적인 성격을 갖는 용도로 활용할 수 있지 않을까 합니다.

반응형

복잡하게 생각하지 말고 다음과 같은 예를 들어 보겠습니다.

 

 t = { apple=5 }
 a = "apple"
 b = "apple"
 print(t.apple, t[a], t[b])

 

결과는

5 5 5

위에서와 같이

t 라는 테이블은 apple라는 키에 5 가 설정된 테이블입니다.

 

이에 대한 접근은

 

t.apple

 

로 접근할 수 있으며,

 

또한 문자열 "apple" 이라는 것으로도 접근할 수 있다는 것 입니다.

 

이러한 기능이 별 필요 없거나 단순하다고 생각할 수 있습니다만,

 

이렇게 생각해보면 매우 유용합니다.

 

c/c++ 같은 고급 언어에서는 변수와 변수와 같은 이름의 문자열은 서로 연결할 수가 없습니다.

 

즉 c 에서

int apple;

string s = "apple";

 

이라는 것이 있을때

s 와 apple 사이의 관계는 특별히 매칭함수를 만들어 주지 않는이상 연결이 어렵습니다.

 

그러나 루아에서는 이렇게 특정 변수를 데이터인 문자열로 접근할 수 있도록 하는 기능을 제공하는 것 입니다.

반응형

루아 테이블에서의 저장 영역은 키-값 (key-value)의 쌍으로 이루어 집니다.

루아는 일반적인 배열(array) 과 dictionary 간의 차이점을 갖지 않습니다.

즉 배열과 dictionary 간의 차이를 루아 테이블에서는 볼수 없다는 것이죠.

 

모든 루아의 테이블들은 실질적으로는 dictionary 와 같이 동작 합니다. 일반적으로 배열에서의 키는 정수이어야 한다는것과도

다르죠.

 

> t = { 3,6,9 }                 -- is the same as...

> t = { [1]=3, [2]=6, [3]=9 } -- is the same as...
> t = {} t[1]=3 t[2]=6 t[3]=9

이러한 의미에서 위의 3줄은 모두 같은 내용 입니다.

 

테이블의 키는 일종의 레퍼런스(reference) 입니다.

a = { [{1,2,3}]="yadda" }              -- construct a table where the element has a table key
for k,v in pairs(a) do print(k,v) end  -- display the table contents: key-value pairs
print( a[{1,2,3}])                           -- display the element value

 

위와 같은 예제서 결과는

table: 014D9150 yadda
nil

입니다.

k,v in pairs(a) 에서

k 는 테이블 a에 있는 키, v 는 해당 키로 지정된 값 입니다.

또한 a 의 키는 {1,2,3} 이라는 테이블입니다. [] 를 쒸운것은 이 테이블 자체의 주소를 키로 사용한다는 것이죠.

그러므로 k 는 table 이라는 값이 나오는 것이고 그 주소가 나오는 것 입니다.

역시 v 는 해당 키에 대한 값 "yadda" 이죠.

 

위의 값을 다음과 같이 풀어보죠.

tablekey = {1,2,3}                     -- create a table with a variable referencing it
a = { [tablekey]="yadda" }             -- construct a table using the table as a key
for k,v in pairs(a) do print(k,v) end  -- display the table elements
print(a[tablekey])                          -- retrieve a value from the table
print(tablekey)              -- the table value is the same as the key above

 

결과는

table: 014D89D0 yadda
yadda
table: 014D89D0

 

위와 같이 보시면 이해가 좀 쉬우실 겁니다.

 

+ Recent posts