오늘은 함수에 대해 공부하는 시간이네요!
스탑. 잠깐만 멈춰서 스탑해보래이.
???
CALL, JUMP, GOTO 차례라고 안 했나?
CALL, JUMP, GOTO가 바꾸는 흐름에 대해 배우기 전에 함수에 대해 알아볼 필요가 있어서요!
의외로 무계획이 아니라구요?
내는 암말도 안했는데.
우선 CALL에 대해 공부해보죠!
아래의 코드를 확인해볼게요.
지금까지는 @EVENTFIRST라는 '이벤트 함수' 한 가지 만을 사용해왔고, 다른 함수를 만든 적은 없죠?
프로그래머가 작성하는 사용자 정의 함수를 실행하기 위해 필요한 명령이 바로 CALL이랍니다!
CALL은 함수를 '호출'(하고 나서 내용을 실행)한다는 뜻이에요.
이벤트 함수는 emuera의 실행 처리 중 자동으로 호출하니까 당연히 CALL을 쓸 일도 없었네요.
ㅎ
DRAWLINE은 이름만 봐도 무슨 명령인지 알겠네.
줄긋기?
정답~ 여백 한 줄을 실선으로 채워주는 명령이에요.
얼레, #DIM DYNAMIC NUMV가 두 갠데?
이래도 괘안나
괜찮다는 걸 확인할 겸 한번 실제로 실행해볼게요!
코노미 씨가 미아가 돼뿟네......
보시면요
@MESSAGE_KONOMI(KEYV=0)
#DIM DYNAMIC KEYV
IF KEYV == 1
PRINTL 찾았다!
ELSE
PRINTL 이 사람이 아닌데.
ENDIF
가 맨 처음으로 실행되고,
PRINTL 코노미 씨?
가 그 다음,
@MESSAGE_KONOMI(KEYV=0)
#DIM DYNAMIC KEYV
IF KEYV == 1
PRINTL 찾았다!
ELSE
PRINTL 이 사람이 아닌데.
ENDIF
가 또 다시 나오죠?
(@CHECK_KONOMI 도 있지만 문자 출력을 하지 않네요)
그러네
각 코드들의 흐름을
#DIM DYNAMIC NUMV = 38
CALL MESSAGE_KONOMI
PRINTW ...
DRAWLINE
REPEAT 2
CALL GREETING_KONOMI
CALL CHECK_KONOMI(NUMV+COUNT)
CALL MESSAGE_KONOMI(RESULT)
WAIT
DRAWLINE
REND
WAIT
부분에서 결정하고, 자세한 동작은 불러오는 코드들에서 기술하는 방식이라고 이해하면 좋아요.
다름이 아니라 @ 을 사용해 이름 붙여 선언한 것이 바로 오늘의 주제인 함수입니다!
CALL MESSAGE_KONOMI 는 @MESSAGE_KONOMI 함수를 호출한다 라는 뜻을 갖고 있어요.
그런데 밑에 있는 CALL MESSAGE_KONOMI는 (RESULT)가 붙어있는데?
적절한 질문이에요! 베리 나이스!
함수를 구성하는 필수적인 요건이 몇 가지 있는데요.
1. 이름
↑이건 @MESSAGE_KONOMI 와 같이 띄어쓰기 없이 써주어서 선언할 수 있어요!
이건 알기 쉽꾸마
2. 인수
일반적으로 매개변수, 영어로는 parameter라고 하는 것이에요!
@함수_명칭(매개변수,매개변수2)
또는
@함수_명칭,매개변수,매개변수2
와 같이 선언할 수 있어요.
ARG 또는 ARGS 배열변수를 사용하지 않는다면 매개변수는 반드시
#DIM DYNAMIC 매개변수
와 같이 함수 내에서 선언해줘야 한답니다!
이것을 CALL 함수_명칭(매개변수,매개변수2) 또는 CALL 함수_명칭,매개변수,매개변수2와 같은 형태로
전달 인자(arguments)를 함수에 연결시켜서 그 값을 함수 실행에 이용하도록 만든답니다.
초등학교 수학에 나오는 요술상자 비슷하네!
아, 그게 수학에서 말하는 함수의 초급편이에요.
뭐라꼬~?!
근데 매개변수가 있는데 전달 인자가 없어도 되는기가?
보통은 오류가 나는데요,
@MESSAGE_KONOMI(KEYV=0)
처럼 전달 인자가 존재하지 않을 경우 초기값을 설정해뒀다면
전달하지 않을 경우에도 오류가 나지 않고 초기값을 반영해 실행해요.
만약에 여러 매개 변수 중 가운데 하나를 생략해야 한다면 (전달인자1,,전달인자3)과 같이 쓰면 됩니다!
그리고 한 가지 더, #DIM DYNAMIC이란 표현은 변수가 차지하는 이름, 메모리 등을 동적으로 할당한다는 뜻이에요.
같은 이름을 가진 변수를 여러 함수들에 작성해도 그 함수 내부에서만 작동하고 실행이 끝나면 알아서 사라지게 됩니다.
A반에서 17번을 부르면 엥엥이가 나오고, B반에서 17번을 부르면 쟁쟁이가 나오는기가.
??? 비유는 잘 모르겠지만 아마 맞을거에요.
3. 반환값
RETURN 수치 명령으로 함수를 실행한 결과를 반환할 수 있어요.
생략하거나 해서 RETURN 없이 함수가 끝났을 경우에는 0이 반환됩니다.
반환값은 RESULT에 저장되고, 만약에
RETURN 0,1,2
와 같이 여러 값을 반환한 경우 RESULT:0, RESULT:1, RESULT:2에 저장되어요.
(RESULT는 RESULT:0과 같은 변수를 가리키는 표현이에요!)
RESULT 변수를 함부로 쓰면 안 되겠네!
수학 연산을 하는 함수를 통해 RESULT 값을 얻었다면 바로 사용하거나,
내용을 보존할 다른 변수에 옮겨두는 게 좋죠.
수학의 함수와는 다르게 프로그래밍의 함수는 결과로 아무 내용도 없이 반환하지 않는 경우,
즉 한 가지에 대응하는 하나가 없는 경우도 있어요. 이 점은 짜장면과 작장면이 다른 것과 비슷한 점이겠네요.
그럼 위에서 말한 코드를 다시 볼까요?
@EVENTFIRST 이벤트 함수는 emuera 기동 후 0번 입력으로 시작 시 자동으로 호출됩니다.
NUMV의 초기값은 38이고,
최초의 호출로 MESSAGE_KONOMI를 인자 없이 호출하네요.
결과로 매개변수 KEYV의 초기값은 0이므로 "이 사람이 아닌데."가 출력됩니다.
그리고 REPEAT 반복 제어문으로 넘어가서 COUNT를 NUMV에 더한 값을 CHECK_KONOMI의 인자로 전달하고,
RESULT를 그대로 MESSAGE_KONOMI의 인자에 전달해요.
2번째 반복했을 때 COUNT는 1이 되어서 38+1=39를 전달받은 CHECK_KONOMI가 1을 반환,
MESSAGE_KONOMI 가 "찾았다!"를 출력하게 되는 예제입니다.
실전 코딩에서는 좀 더 보기 예쁘고 실용적인 함수들을 많이 사용하게 되지만,
명령어의 기능을 간단히 알기 위해 예제를 써봤어요.
솔직하게 이 정도는 새발의 피라고 해라.
아리사가 졌습니다.
함수 호출은 실전에서 훨씬 더 복잡해질거에요...
다음은 JUMP인데요, 이건 길게 설명할 게 없어요.
JUMP는 CALL과 마찬가지로 함수를 호출하지만, 호출 이전의 함수는 잊어버리는 명령이에요!
그대로 코드의 흐름이 새로 호출된 함수로 뛰어 넘어가기 때문에 한정된 상황에서 유용하게 쓸 수 있습니다.
"시즈카쨩, 어딨어?"라는 문장을 출력하지 않고 다음 함수에서 종단을 맞이하는구나.
CALL과 거의 비슷하고 전달 인자와 매개 변수도 그대로 쓸 수 있는데,
RESULT를 참조해서 다음 함수에 전달하는 건 아무래도 안 되죠.
그 다음이 GOTO! 사악한 명령어로도 유명한 GOTO의 차례가 드디어 나왔네요. 므믓...
고토?
일반적으로 고 투 라고 읽어요.
예제를 보면 GOTO ANCHOR라고는 명령이 있죠.
GOTO ANCHOR는 $ 기호로 기록한 $ANCHOR의 밑줄로 코드의 흐름을 즉각 이동시키는 명령이에요.
코노미 씨는 무적이에요...... KOH는 신이고요.
위에도 아래에도 $ANCHOR가 있는데 어느쪽으로 갈지 어떻게 아나?
GOTO는 함수 영역 밖으로 나가지는 못하기 때문에 같은 함수에 있는 $ANCHOR를 찾아가게 됩니다!
결과는 이렇네요.
중독적인 후렴구긴 한데 따로 똑 떼어놓고보니 어색하네.
GOTO는 단순명쾌한 명령이고 블록과 상관없이 코드를 스킵하거나 반복해야 할 경우 유용하게 쓸 수 있어요.
단 아주 단순한 명령인 만큼 복잡한 해결방식에 도입하려 할수록 코드가 읽기 힘들어질 수도 있으니 조심해야 해요.
이것으로 끝이라면 좋겠지만, 몇 가지 더 남아있어요!
에에엥~~~
CALL, JUMP, GOTO를 보충하는 내용이에요.
CALL은 TRYCALL, TRYCALLFORM, TRYCCALL, TRYCCALLFORM, TRYCALLLIST, CALLFORM 등과 같은 변형이 있습니다
(*CALLF, CALLFORMF와 CALLEVENT 등은 나중에 다룰게요)
JUMP, GOTO도 마찬가지로 변형을 갖고 있어요.
TRY ~ | 함수 또는 앵커 이름이 존재하지 않는다면 아무것도 하지 않고 넘어갑니다. |
TRY ~ FORM | ~ FORM과 마찬가지로 FORM 식을 사용할 수 있고, 존재하지 않으면 아무것도 하지 않고 넘어가요. |
TRYC ~ CATCH ENDCATCH | 함수 또는 앵커 이름이 존재하면 실행 종료 후 바로 밑의 내용을, (생략 가능해요) 존재하지 않는다면 실행 없이 CATCH와 ENDCATCH 사이 행의 내용을 실행합니다 |
TRYC ~ FORM CATCH ENDCATCH | 위와 같지만 FORM식을 사용 가능해요 |
TRY ~ LIST FUNC ... FUNC ... ENDFUNC | 위에서부터 순서대로 FUNC ...에 해당하는 함수 또는 앵커 이름이 존재하지 않는다면 아래쪽을 찾아 시도하는 것을 반복하고 마지막에는 ENDFUNC 밑으로 이동해요. *GOTO 구문도 FUNC를 이용합니다. |
~ FORM | 함수 또는 앵커 이름에 FORM 식을 사용할 수 있어요. CALLFORM CHARA_MESSAGE_K{NUMV} |
CALLFORM 같은 경우 게임 캐릭터마다 대사(구상)를 다른 내용으로 출력해야 할 때 엄청나게 자주 쓰여요.
문자열 출력할 때 쓰던 %%랑 {}를 그대로 쓴다니까 변수나 계산식을 그대로 쓸 수 있단거네?
맞아요~!
오늘은 이만 마치고 다음 강의에서는 식중함수, 헤더 파일(ERH), 코딩 계획에 대해 알아볼게요.
다음 이 시간에!