零基础开发 era 游戏 #6 函数的定义和使用
在 era 游戏里的「函数」是一个很奇怪的东西。
为什么要打引号呢?因为他所谓的「関数」指他自创的新概念函数。
据说是跟日语 IT 圈结合日本文化环境的特殊语境下有关。
总之 Emuera 日语文档里说的「関数」,跟地球上其他地区的程序员圈子里常识概念上的「函数」,有一定区别。
两种不同类型的函数之间的区别#
一般函数(命令)#
- 必须用
CALL
命令调用(或JUMP
命令跳转)。 - 「返回值」返回(
RETURN
/RETURNFORM
)到全局公共变量RESULT
(数值)里。 - 定义时不用加修饰符。
有些系统内置的一般函数(命令)同时还会「返回」
RESULTS
(字符串)。
其实只是RESULTS = 新的结果
而已,这就是一般「函数」的「返回值」的本质:
用一个 全局 公共 变量,来临时存放处理后的结果。
行内函数(真正的函数)#
- 可以且只能直接用在表达式里(不能被
CALL
/JUMP
)。 - 「返回值」返回到(
RETURNF
)到原本调用它的地方。 - 定义时必须加修饰符(
/#FUNCTION
),用来限定返回值的数据类型。#FUNCTIONS
其他对比#
参数的定义 / 传递方式
函数(无论是一般函数还是行内函数)的参数定义格式无论是使用 ()
还是 ,
都行。
但只有一般函数支持用两种形式调用:
@SYSTEM_TITLE CALL DO_SOMETHING, "发呆" CALL DO_OTHER_THING("什么都没做") QUIT @DO_SOMETHING(sth) #DIMS sth PRINTFORML 做了一些事:%sth% RETURN @DO_OTHER_THING, sth #DIMS sth PRINTFORML 做了其他事:%sth% RETURN
行内函数除了调用时需要注意一下,定义时使用不同的参数写法实际并无区别:
@SYSTEM_TITLE ; 给行内函数传参必须用括号包起来 否则会报错「は解釈できない識別子です」 PRINTFORML %DO_SOMETHING("发呆")% PRINTFORML %DO_OTHER_THING("什么都没做")% QUIT @DO_SOMETHING(sth) #FUNCTIONS #DIMS sth RETURNF @"做了一些事:%sth%" @DO_OTHER_THING, sth #FUNCTIONS #DIMS sth RETURNF @"做了其他事:%sth%"
一般函数(命令)#
定义#
@DO_SOMETHING(num) #DIM num RESULTS = 做了一些事 RETURN num + 1 @DO_OTHER_THING(num) #DIM num RESULTS = 做了其他事 RETURNFORM 10{num}
使用#
@SYSTEM_TITLE CALL DO_SOMETHING(111) PRINTFORML DO_SOMETHING(111) → RESULT={RESULT} RESULTS=%RESULTS% CALL DO_OTHER_THING(999) PRINTFORML DO_OTHER_THING(999) → RESULT={RESULT} RESULTS=%RESULTS% QUIT
CALL
@SYSTEM_TITLE CALL SOMEDAY QUIT @SOMEDAY PRINTL 今天天气很好 PRINTL 恰巧路过一个公园 CALL TEST_EVENT PRINTL 回到公园入口 继续沿原路回家 PRINTL 完美的一天 @TEST_EVENT PRINTL 于是进去逛了一会 PRINTL 心旷神怡
使用 CALL
调用的函数运行结束后会回到原处。示例程序的结果:
今天天气很好
恰巧路过一个公园
于是进去逛了一会
心旷神怡
回到公园入口 继续沿原路回家
完美的一天
JUMP
@SYSTEM_TITLE CALL SOMEDAY QUIT @SOMEDAY PRINTL 今天天气很好 PRINTL 准备回家时被前辈叫住 JUMP TEST_EVENT ; 由于是直接「跳转」到目标函数 当目标函数运行完成后 本函数直接结束 PRINTL 回家路上遭遇无差别杀人魔 PRINTL 你遇害了 @TEST_EVENT PRINTL 前辈邀请你吃饭 你欣然前往 PRINTL 愉快的用餐后 前辈开车送你回家 PRINTL 完美的一天
使用 JUMP
跳转的函数运行结束后视为「跳转时的函数也执行结束」。示例程序的结果:
今天天气很好
准备回家时被前辈叫住
前辈邀请你吃饭 你欣然前往
愉快的用餐后 前辈开车送你回家
完美的一天
行内函数(真正的函数)#
定义#
@GET_NUMBER(num) #FUNCTION #DIM num RETURNF num + 233 @GET_STRING(text) #FUNCTIONS #DIMS text RETURNF "兄弟们!有" + text + "!"
使用#
直接插入表达式行内
@SYSTEM_TITLE PRINTFORML 我去!{GET_NUMBER(767)}!%GET_STRING("狗")% QUIT
本地(局部)变量#
即 LOCAL
/ LOCALS
,这是一组仅在函数内部生效的的变量。
可以用 #LOCALSIZE
/ #LOCALSIZES
修饰符来单独限定变量(数组)的大小。
(若没有手动指定,则默认使用 ./csv/VariableSize.csv
里设定的数组大小。)
究其本质,它实际上不是所谓的局部变量——
而是名为 LOCAL@函数名
或 LOCALS@函数名
的 public static 变量。
即使离开函数,该值也会被保存;从函数之外也能引用(甚至修改)。
另外,在像是循环 / 递归之类的多次调用的情况下也会共享同一个值。
@SYSTEM_TITLE WHILE 1 INPUT PRINTFORML 输入了 RESULT={RESULT} CALL TEST_COM PRINTFORML CALL TEST_COM 之后 LOCAL@TEST_COM={LOCAL@TEST_COM} PRINTFORML TEST_FUNC()={TEST_FUNC()}(LOCAL:1) 之后 LOCAL@TEST_FUNC={LOCAL@TEST_FUNC}(LOCAL:0) PRINTL WEND QUIT @TEST_COM #LOCALSIZE 1 LOCAL += 1 @TEST_FUNC #FUNCTION #LOCALSIZE 2 LOCAL:0 += 1 LOCAL:1 += 10 RETURNF LOCAL:1
如果你的函数只需要一个自变量,可以直接使用 LOCAL
/ LOCALS
。
但最好尽量使用 #LOCALSIZE
/ #LOCALSIZES
限定所需的大小,并且谨记在每次调用该函数的时候,一般都需要先初始化该变量。
除非你有特别的需求,比如把
LOCAL
/LOCALS
这个值作为某种临时的「属性」。