오늘은 함수에 대해 공부하는 시간이네요!


스탑. 잠깐만 멈춰서 스탑해보래이.


???


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


가 맨 처음으로 실행되고,


@GREETING_KONOMI

PRINTL 코노미 씨?


가 그 다음,


@MESSAGE_KONOMI(KEYV=0)

#DIM DYNAMIC KEYV

IF KEYV == 1

    PRINTL 찾았다!

ELSE

    PRINTL 이 사람이 아닌데.

ENDIF


가 또 다시 나오죠?

(@CHECK_KONOMI 도 있지만 문자 출력을 하지 않네요)


그러네



각 코드들의 흐름을


@EVENTFIRST

#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), 코딩 계획에 대해 알아볼게요.


다음 이 시간에!