吵吵   2018-06-04  阅读:8,362

到现在为止,我也不知道为什么cache数据库的开发语言叫M语言,难道仅仅是因为保存的routine后缀是mac?明明人家的所有文档管它叫ObjectScript,翻译一下叫做对象脚本语言?

不管它叫啥的问题,反正用的多了,问题就来了。

用这个系统的公司开发的程序bug是真多,但是bug多还真不是说cache数据库就不行,虽然它背这个锅很多年了。

大部分时候我们发现某个查询都不起作用了,或者那个界面刷新不出来了,然后反过去查代码,乌压压的一大片,全是…的缩进,简直不忍直视。

发现的最多的问题,还是变量的作用域的问题,比如functionA中定义了一个变量num=1,然后functionB中又对num变量进行了赋值s num=-1,那么functionA中的变量num也就改变了。

像不像当初JavaScript那样,变量是全局的,结果改的乱七八糟?

当然,JavaScript搞出了封装和闭包,不然全局的变量满天飞,一不小心就中招呀。

因此我们也有理由相信cache是会处理这个问题的,代码写的差不应该怪人家设计有问题,如果连作用域的问题它都没有方案的话,那这门开发语言就不算是门语言了。

废话就不扯了,来看看cache中routine中的函数的几种写法,分别是Procedures, Routines, Subroutines, Functions, and Methods。

我们就一一来看这几个有啥不同。

一、Procedure

在pascal的预言中,procedure被翻译为“过程”,意思是没有返回值的函数,但是在objectsript中就完全不是这个意思了,暂且叫过程吧,而且是官方最推荐的写法:

ProcedureName(Parameters) [PublicVariables]
{
// code…
Quit ReturnValue
}

我们自己写一个

Mypro(num) [totalNum] public
{
s totalNum=totalNum+1
s num=num+1
s num1=1
q num
}

过程特点是什么呢?

1、被调用可以是public或者private,当为private的时候,只能被这个routine内的其它方法或者函数调用,当为public的时候,可以被其它routine给调用。因此如果你要在termial中调试这个过程,比如

w $$Mypro^MyRoutine(1)

如果你没有加上public的标识的话,这样子调用就会报NOLINE,即找不到。

因此如果你要在terminal中调试或者在这个routine文件外调用这个过程的话,你就得加上public,因为你不写,默认就是private。

2、变量保护。在objectscipt其它函数的写法中,你定义的任何变量都是在进程中有效的,等于就是全局变量了,为啥官方推荐procedure的写法,因为里面的变量的作用域就是这个过程,在这个过程里面随便你咋定义变量,哪怕是变量名和外面的重复,你都不用去管它,不会影响,出了这个过程变量就销毁了。

比如上面那个过程中的num1,即便是还有其他函数中用到了num1,也不会造成任何影响,它还是独立的。

那如果我们想改变过程之外的其它变量的值怎么办呢?比如totalNum,我是用来全局计数的,那你就把它写在中括号里面,这样子的话,就把全局变量引入了这个过程了,你就可以改变它了。

3、可以有返回值,也可以没有。而且返回值可以是任何的类型的。

二、Routines

这个就不多说了,就是这个mac文件了,要是拿来跟c#或者java比较一下的话,就类似于类名。

三、Subroutines

这个是啥意思呢,就是routine中的子块的代码,我只能这么解释了…跟procedure比它不带括号{},没有返回值,里面的变量全部都是全局变量,不推荐。

label [ ( param [ = default ][ , …] ) ]
/* code */
Quit

四、Functions

这个其实和Subroutines是一样的,只不过有返回值,所以叫函数… 跟procedure比也它不带括号,里面的变量全部都是全局变量,也不推荐。

label([param[=default]][,…])
code
Quit expression

多说一句哦,大部分人写objectScript代码,都是用不带大括号的subroutine或者function格式来写的,因为它们的变量全部都是全局变量,所以bug满天飞舞!

五、Methods

这个是指class文件中的类的方法了,是cache数据库后面真正用的对象方式储存数据时类里面方法的表达方式了,这里就不讨论了。

说完这些,关于procedure还有个传值和传址的问题没有说。

比如上面那个过程中的totalNum,我想在MyPoc中改变它的值,我可以通过[totalNum]的方式来在过程中引用它,我也可以把它当变量输入,只要采用传址的方式。

我们写个代码来验证一下传值和传址的区别:

FunA(num)
{
s num=1
d $$FunB(num)
w num
}

FunB(num)
{
s num=-1
}

ok,现在我们调试FunA,结果输出值是1,意思是虽然我们把num传递过去了给FunB,但是因为是传值的,所以FunB中的num已经是它新new的一个变量了,只不过值也等于1,退出funB这个变量就销毁了。

那么我们现在改一下FunA

FunA(num)
{
s num=1
d $$FunB(.num)
w num
}

没错传址的话跟传值的区别就是加个.

这次输出的就是-1了,等于FunB中的num就是个指针,指向的还是FunA中的变量B。

好了,最后我们总结一下,如何写好objectscript:

1、所有的函数都用procedure的格式来表达,用大括号括起来,以免变量对其它函数进行干扰。

2、涉及到被其它文件调用的记得加上public标识。

3、如果需要改变过程以外的变量,用传址的方式,比直接用[]引入更加方便。

4、当然,最重要的,不用再用.去缩进了,用{}来缩进,代码清晰易读,就如文章的配图。

吵吵微信朋友圈,请付款实名加入:

吵吵 吵吵

3条回应:“cache数据库m语言变量的作用域”

  1. 液压扳手说道:

    多年的液压扭矩扳手制造经验带给您卓越的使用体验 http://www.pipercn.com

  2. 卫星电视说道:

    卫星高清电视接收机 http://www.satvcn.com

发表评论

电子邮件地址不会被公开。 必填项已用*标注