零基础开发 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%
QUITCALL
@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这个值作为某种临时的「属性」。