언어 — 문장
언어 — 문장 (The Language — Statements)
루아는 자유 형식(free-form) 언어지만, 문장(statement)이 실행되는 순서는 소스에 나타난 순서대로예요. 루아의 문장은 크게 여러 종류가 있어요.
블록 (Blocks)
하나의 블록(block)은 문장들의 나열이에요. 블록은 명시적으로 do ... end로 둘러쌀 수도 있고, 함수 본문, for/while/repeat 루프 본문, if 분기 본문 등이 블록을 이뤄요.
do
local x = 1
print(x)
end
블록은 지역 변수(그리고 to-be-closed 변수)의 스코프를 도입해요. 블록 안에서 선언된 지역 변수는 그 블록 안에서만 접근할 수 있어요.
청크 (Chunks)
**청크(chunk)**는 루아가 실행하는 단위로, load/dofile 등으로 읽히는 코드 단위예요. 청크는 단순히 문장의 나열(블록)이에요. 청크는 파일이거나 문자열일 수 있어요. 각 청크는 독립된 _ENV(전역 환경)를 가져요.
-- 파일 또는 문자열로 된 청크
local f = load("print(1 + 1)")
f() --> 2
청크는 함수 호출처럼 ...(vararg)를 통해 추가 인자를 받을 수 있는데, 이는 독립 실행 인터프리터가 스크립트에 인자를 넘길 때 유용해요.
할당 (Assignment)
변수에 값을 넣는 문장이에요. 자세한 내용은 "변수 (Variables)" 절을 참조해요. 기본 형태는 다음과 같아요.
varlist = explist
할당은 오른쪽 모든 표현식을 먼저 평가한 뒤 왼쪽 변수들에 대입해요.
local a, b = 1, 2
a, b = b, a -- 스왑
제어 구조 (Control Structures)
루아는 다음 제어 구조를 제공해요.
if: 조건에 따른 분기.while: 조건이 참인 동안 반복.repeat ... until: 본문을 먼저 실행하고 조건이 참이 될 때까지 반복 (조건은 반복 후 검사).- 숫자 for:
for i = start, stop [, step] do ... end. - 일반 for:
for var in explist do ... end. break: 가장 안쪽 루프를 즉시 종료.goto: 레이블로 무조건 점프.
조건식 (Conditions)
조건식은 논리적 참/거짓을 판정할 때, false와 nil만 "거짓"으로 간주하고 그 외의 모든 값은 "참"으로 간주해요. 0이나 빈 문자열도 참이에요.
If 문 (If statement)
if v < 0 then
print("음수")
elseif v == 0 then
print("영")
else
print("양수")
end
if는 then과 end로 묶이고, elseif로 여러 조건을, else로 기본 분기를 가질 수 있어요. elseif는 중첩 if의 설탕이에요.
While 문 (While statement)
local i = 0
while i < 10 do
i = i + 1
end
while은 조건이 참인 동안 본문을 반복 실행해요. 조건이 거짓이 되거나 break를 만나면 종료해요. 본문이 실행되기 전에 조건을 검사하므로, 조건이 애초에 거짓이면 본문은 한 번도 실행되지 않아요.
Repeat 문 (Repeat statement)
local j = 0
repeat
j = j + 1
until j >= 10
repeat ... until은 본문을 먼저 실행한 후 until의 조건을 검사해요. 따라서 본문은 최소 한 번은 실행돼요. until 안에서는 루프의 지역 변수(본문에서 선언된)를 볼 수 있어요.
For 문 (For statement)
숫자 for (Numeric for)
for i = 1, 10 do
print(i)
end
for v = e1, e2 [, e3] do body end에서 v는 제어 변수예요. e1은 초기값, e2는 종료값, e3는 증가분(기본값 1)이에요. 세 표현식 모두 반복 시작 전에 한 번만 평가돼요. 루프는 v가 e2 이하(증가분이 양수일 때) 또는 이상(증가분이 음수일 때)인 동안 반복해요. v는 루프 내부에서 변경해도 되지만, 루프 진행에 영향 주지 않도록 일반적으로 변경하지 않아요.
제어 변수는 루프 스코프 안에서만 유효한 지역 변수예요. 루프가 끝나면 자동으로 nil 처리돼요.
일반 for (Generic for)
for k, v in pairs(t) do
print(k, v)
end
일반 for는 반복자(iterator) 함수를 사용해요. for varlist in explist do body end 형태로, explist는 보통 반복자 함수·상태·초기값을 반환하는 표현식이에요. 각 반복에서 반복자 함수를 호출하고, 반환값들을 varlist에 대입한 뒤 본문을 실행해요. 반복자가 nil을 반환하면 루프를 종료해요.
pairs는 테이블의 키-값 쌍을, ipairs는 정수 키(1부터 시작하는 연속 배열)만 순회해요.
Break 문 (Break statement)
break는 가장 안쪽의 루프(for, while, repeat)를 즉시 종료해요. break는 루프 본문 밖에서는 쓸 수 없어요.
Goto 문 (Goto statement)
goto label은 레이블로 점프하고, ::label::로 레이블을 정의해요.
local i = 1
::start::
if i > 5 then goto finish end
print(i)
i = i + 1
goto start
::finish::
루아의 goto는 제한적이에요: 점프는 지역 변수의 스코프에 들어가거나 나갈 수 없고(즉, 초기화되지 않은 지역 변수의 스코프 안으로 점프할 수 없음), 함수 안팎으로 점프할 수 없어요. goto는 주로 복잡한 흐름을 단순화할 때 사용해요. *goto는 C의 goto와 달리 예외 구조나 자원 정리를 자동으로 하지 않아요 — 닫힐 변수(이미 초기화된 to-be-closed 변수)의 스코프를 빠져나갈 때는 그 __close 메타메서드가 호출돼요.
Function Calls as Statements
함수 호출은 문장으로도 사용할 수 있어요. 반환값은 무시돼요.
print("hello")
t.insert(list, 1)
Local Declarations (지역 선언)
local namelist [= explist]로 지역 변수를 선언해요. 초기화 표현식이 생략되면 nil로 초기화돼요.
local a, b = 1, 2
local x -- x는 nil
지역 변수는 선언된 지점부터 블록 끝까지 스코프를 가져요. 지역 변수 선언 시점에 그 변수 자신도 참조할 수 있지만, 초기화 전 자기를 참조하면 바깥의 같은 이름(있다면)을 가리켜요.
To-be-closed 변수 (To-be-closed variables)
지역 변수 선언 시 그 값이 "닫힐 변수(to-be-closed)"로 지정될 수 있는데, 이는 선언 아래 형식으로 표시돼요.
local x <close> = open_resource()
<close> 속성이 붙은 지역 변수는 블록을 벗어날 때(정상 종료든 오류든, goto로 빠져나가든) 자동으로 정리돼요. 정리란 그 값에 __close 메타메서드가 있으면 그것을 호출하는 것, 또는 값이 함수/닫히지 않은 값이면 오류를 내는 것을 말해요. 파일 핸들, 잠금 등 자원 정리에 유용해요.
local f <close> = assert(io.open("file.txt", "r"))
-- 블록을 벗어나면 f가 자동으로 닫힘
Return 문 (Return statement)
return은 함수에서 값을 반환해요. return은 블록의 마지막 문장이어야 해요. 값을 생략하면 nil을 반환해요.
local function f(x)
return x * 2
end
return은 여러 값을 반환할 수 있어요: return a, b, c.
문장 문법 요약 (Statement grammar)
stat ::= ';'
| varlist '=' explist
| functioncall
| label
| break
| goto Name
| do block end
| while exp do block end
| repeat block until exp
| if exp then block {elseif exp then block} [else block] end
| for Name '=' exp ',' exp [',' exp] do block end
| for namelist in explist do block end
| function funcname funcbody
| local function Name funcbody
| local attnamelist ['=' explist]
| return [explist] [';']
출처: 문장 (Statements)
본문
문장의 종류
루아 문장은 위 문법에 따른 여러 형태를 가지며, ;(세미콜론)은 빈 문장이나 문장 구분자로 쓸 수 있어요. 루아는 문장을 명시적으로 종료할 필요가 없지만, 가독성을 위해 세미콜론이나 줄바꿈을 쓸 수 있어요.
함수 정의는 문장
function 구문은 문장으로도 쓸 수 있어요. 전역 함수 정의 function f(...) ... end는 f = function(...) ... end와 같고, 지역 함수 정의 local function f(...) ... end는 자기 자신을 참조할 수 있는 지역 함수를 만들어요.