프로시저(Procedures)
예제에서 사용된 `echo`, `readLine` 같은 새로운 명령을 정의하기 위해서는 프로시저(procedure) 개념이 필요합니다. 다른 언어에서는 이를 메서드(method)나 함수(function)라고 부르지만, Nim은 이 개념들을 구분합니다. Nim에서 새로운 프로시저(일반적으로 다른 언어에서 "함수"라고 부르는 것)는 `proc` 키워드로 정의합니다:
```nim
proc yes(question: string): bool =
echo question, " (y/n)"
while true:
case readLine(stdin)
of "y", "Y", "yes", "Yes": return true
of "n", "N", "no", "No": return false
else: echo "제대로 답하시오: yes or no"
if yes("중요한 파일을 다 삭제할까요?"):
echo "미안, 그건 좀 그래"
else:
echo "그건 좀 그렇지?"
```
위 예제는 `yes`라는 프로시저를 보여줍니다. 이 프로시저는 사용자에게 `question`을 던지고, “yes”(또는 그 비슷한 값)을 입력하면 true, “no”(또는 그 비슷한 값)을 입력하면 false를 반환합니다. `return` 문은 프로시저(따라서 while 루프도)를 즉시 빠져나옵니다.
`(question: string): bool` 구문은 이 프로시저가 string 타입의 매개변수 `question`을 받고, bool 타입의 값을 반환한다는 뜻입니다. `bool` 타입은 내장형으로, 가질 수 있는 값은 `true`와 `false`뿐입니다. if나 while 조건식은 반드시 bool 타입이어야 합니다.
예제에서 `question`은 (형식) 매개변수(formal parameter)라고 부르고, "중요한 파일을 다 삭제할까요?"는 이 매개변수에 전달되는 인자(argument)입니다.

Result 변수(Result variable)
값을 반환하는 프로시저에는 반환값을 나타내는 암묵적 result 변수가 선언됩니다. `return` 문에 표현식을 쓰지 않으면(즉, 그냥 `return`이라고만 하면), 이는 `return result`의 축약형입니다. `return` 문 없이 프로시저가 끝나더라도 `result` 값은 자동으로 반환됩니다.
```nim
proc sumTillNegative(x: varargs[int]): int =
for i in x:
if i < 0:
return # return result와 같음
result = result + i # return이 없어도 암묵적으로 return함
echo sumTillNegative() # 0 출력
echo sumTillNegative(3, 4, 5) # 12 출력
echo sumTillNegative(3, 4, -1, 6) # 7 출력 : 음수면 종료되므로
```
`result` 변수는 이미 프로시저 시작 시 암묵적으로 선언되므로, `var result`처럼 다시 선언하면 기존의 `result`를 가려버리게(shadowing) 됩니다. 또한 `result` 변수는 해당 타입의 기본값으로 초기화되어 있습니다(ex. 정수라면 0). 참조형referential 데이터 타입(C/C++에서 포인터를 사용하는 타입이라고 생각하면 될 듯)은 기본적으로 `nil`로 시작하기 때문에, 수동 초기화가 필요할 수 있습니다.
값을 반환하는 프로시저가 `return` 문을 전혀 사용하지 않고, 특별한 `result` 변수도 다루지 않으면, 마지막 표현식의 값이 자동으로 반환됩니다(rust와 유사합니다):
```nim
proc helloWorld(): string =
"Hello, World!"
```
위 코드는 문자열 "Hello, World!"를 반환합니다.
매개변수(Parameters)
프로시저 본문에서 매개변수는 불변(immutable)입니다. 기본적으로 그 값은 변경할 수 없습니다. 이는 컴파일러가 매개변수 전달을 가장 효율적으로 처리할 수 있게 해줍니다. 만약 프로시저 내부에서 변경 가능한 변수가 필요하다면, 본문 안에서 `var`로 새로 선언해야 합니다. 매개변수 이름을 가려 쓰는(shadowing) 것도 가능하며, 실제로 자주 쓰이는 관용구입니다:
```nim
proc printSeq(s: seq, nprinted: int = -1) =
var nprinted = if nprinted == -1: s.len else: min(nprinted, s.len) # 새로 선언
for i in 0 ..< nprinted:
echo s[i]
```
만약 프로시저가 호출자의 인자를 직접 수정해야 한다면, `var` 매개변수를 사용할 수 있습니다:
```nim
proc divmod(a, b: int; res, remainder: var int) =
res = a div b # 정수 나눗셈
remainder = a mod b # 정수 나머지 연산
var
x, y: int
divmod(8, 5, x, y) # x와 y가 수정됨
echo x
echo y
```
위 예제에서 `res`와 `remainder`는 `var` 매개변수입니다. 프로시저가 이들을 수정하면, 호출자에게도 변경 내용이 반영됩니다(C/C++에서 포인터를 argument로 넘기는 것과 같음). 다만 이 경우, `var` 매개변수 대신 튜플(tuple)을 반환값으로 사용하는 것이 더 나은 방법일 수 있습니다.
Discard 문(Discard statement)
반환값을 무시하고 단순히 부수효과(side effect)만 사용하려면, 반드시 `discard` 문을 써야 합니다. Nim은 반환값을 암묵적으로 버리는 것을 허용하지 않습니다:
```nim
discard yes("뜬금없는 질문을 해도 될까요?")
```
하지만 프로시저(또는 반복자)가 discardable pragma로 선언되었다면, 반환값을 무시해도 오류가 발생하지 않습니다:
```nim
proc p(x, y: int): int {.discardable.} =
return x + y
p(3, 4) # 이제 허용됨
```
본 설명은 Nim 공식 문서(https://nim-lang.org/docs/tut1.html, Creative Commons Attribution 3.0) 및 코드 예제(MIT License)를 바탕으로 하였습니다.
'Programming Languages > Nim' 카테고리의 다른 글
| [Nim 언어 강좌] 프로시저(3) - 연산자, 전방 선언, 함수와 메서드 (0) | 2025.10.01 |
|---|---|
| [Nim 언어 강좌] 프로시저(2) - 명명된 인자, 기본값, 오버로딩 (0) | 2025.09.30 |
| [Nim 언어 강좌] 문장과 들여쓰기 (0) | 2025.09.28 |
| [Nim 언어 강좌] 제어문(3) - break, continue, when (0) | 2025.09.27 |
| [Nim 언어 강좌] 제어문(2) - 반복문, 스코프 (0) | 2025.09.26 |