集算器初体验
【摘要】
集算器专注于结构化数据分析与处理, 是一门新型的快速开发语言,它有什么特性呢?去乾学院看个究竟:集算器初体验!
1、从经典的 Hello, world! 开始
先看图(1):
图(1)
新建 p1 程序文件,在 A1 格子中输入 =output(“Hello, world!”)。点击图(1)中红圈圈住的三角按钮,执行 p1 的代码,就可以在控制台中看到输出结果,如红色方框所示。
从这个例子可以看出,集算语言不同于传统语言,没有 main 函数入口,也没有引入类、或者头文件。那么程序是如何工作的呢?从图(1)可以看到,代码是写在类似 Excel 命名的格子里面的。既然有了行列,集算语言就按照“先行后列”的顺序开始计算。所以程序的入口就是 A1 格,依次执行 B1 直到最后一列,再从 A2 开始,直到最后一个包含代码的格子为止。
2、变量都去哪了?
无论是 C 语言还是 Java,都有一个变量声明的概念。例如,我们要用到一个字符串时,需要先定义好名字以及类型,就像:
char* msg=”Hello,world!”; //C 风格
String msg=”Hello,world!”; //Java 风格
而在集算语言中,这个例子会写成表(1):
A | |
---|---|
1 | Hello,world! |
2 | =output(A1) |
表(1)
运行后,输出结果一样。但我们并没有将“Hello,world! ”先赋值给某个变量。而是在 A2 中直接引用了格子的名字 A1,也就是说,集算语言中格子的名字就可以直接用作变量名。所以集算语言中初看并没有“变量”,实际是集算语言自动使用了格子名字作为缺省变量名,这样一方面可以省去我们为变量取名的烦恼,同时也让代码看起来更加简便和整洁。
但是,你可能会说:“那我要取一个有意义的名字来作为变量,支持不?”
——当然支持!
很显然,如果全是字母加数字的变量名而变量又很多,想要寻找某个有特殊含义的变量时,结果一定是你在众里寻它千百度,它却问你的眼镜有没有千百度,这就尴尬了……所以,我强烈建议:只针对真正有意义的变量进行命名!
那么,要取个有含义的变量名,是不是在 A1 中写入 String msg=”Hello,world!” 就可以了? 这个问题我先给出答案:“输入错误。”至于原因嘛,下面第 4 节再讲。别急,先让我们熟悉一下语法。
3、格子内容的几种表示方法
我们知道,传统程序文件通常都是由常量、变量、关键字、函数名、函数体、语句和注释等部分构成。集算语言也不例外,也有上述各种组成部分,只不过组织结构有点不同。
首先,有别于传统 C 语言,集算语言中一个文件只能定义一个函数,且文件名就是函数名。而 C 语言的一个文件中是可以定义多个函数的。
另外,由于集算语言的代码都位于格子中,而为了区分格子中代码的不同类型,我们需用不同的字符开头来表示不同的代码类型,具体来说有:
1、单或双斜杠开头
这个跟常规语言类似,斜杠后面直接跟注释,不过在集算语言中,单斜杠表示注释当前格,双斜杠表示注释当前格以及该行后面的所有格,这类格子我们称作 “注释格” 。参考表(2):
A | B | |
---|---|---|
1 | / 这是一个集算语言注释格 | /A1 为一个 注释格 |
2 | // 这是一行注释 | 因为 A2 是双斜杠,B2 后面都是注释格 |
表(2)
2、直接输入内容
这部分包括常量(但在集算语言中,常量被赋值后仍然是可变的),这样的格子我们称作 “常数格” ;关键字开头的语句(比如表示循环的 for,返回值的 return 等),这类格子我们称作 “语句格” 。参考表(3):
A | B | |
---|---|---|
1 | Hello,world! | /A1 为一个 常数格 |
2 | return A1 | /A2 为一个 语句格,返回 A1 的内容 |
表(3)
3、等号开头
凡是需要计算一下的代码,或者说表达式都可以由等号开头。包括定义一个变量、计算一个表达式或者执行一个函数。这类格子我们称作 “计算格 ” 。参考表(4):
A | B | |
---|---|---|
1 | =msg=”Hello,world!” | /A1 为一个 计算格,计算后产生变量 msg,值为字符串 Hello,world!同时 A1 格子的值也为 Hello,world! |
2 | =to(1,100) | /A2 为一个 计算格,计算后 A2 的值为 1 到 100 的一个序列 |
表(4)
4、大于号开头
同样是要计算一下的代码,但计算过后,如果有返回值,会直接扔掉忽略,并不返回给格子变量,这样的代码我们也叫做代码块,这类格子我们称做 “执行格” 。参考表(5):
A | B | |
---|---|---|
1 | >msg=”Hello,world!” | /A1 为一个 执行格,执行后产生变量 msg,值为字符串 Hello,world! 不同于计算格,此时的 A1 并没有值 |
2 | >output(A1) | /A2 为一个 执行格,执行后在控制台输出 A1 的内容 Hello,world! |
表(5)
上述计算格和执行格两种类型,后面跟的都是要执行的语句,那么它们之间到底有何区别,又该如何使用呢?一般来说,我们会根据有返回值和没返回值两种情况,对语句或者表达式进行区分。
对于有返回值的语句,一般规范为使用计算格,例如给当前格赋值:=3.14。但是如果返回值在后面不再使用时,建议使用执行格,以减少内存占用。
对于无返回值的语句,一般规范是使用执行格。例如:> output(“Hello world!”)
下面用表(6)来对上面描述的各种格子类型进行一下总结:
A | B | C | |
---|---|---|---|
1 | // 这是一个示例代码 | 由于 A1 是双斜杠的注释,所以 C1 也是注释格 | |
2 | Hello,world! | / 给 A2 格赋常量初值 | |
3 | >output(A2) | / 使用 output 函数输出 A2 的内容 | |
4 | >msg=”Hello,world!” | /A4 定义了一个名为 msg 的字符串变量 | |
5 | >output(msg) | /output 函数没有返回值,所以采用执行格 | |
6 | =to(1,100) | /A6 使用 to 函数返回 1 到 100 的整数集合,返回序列对象到当前格。由于后面需要引用 A6,故此格只能为计算格 | |
7 | =summary=0 | / 定义名为 summary 整数型变量,并赋初值为 0。虽然有返回值,但我们只用 summary 变量,故此格定义为计算格,执行格均可以 | |
8 | for A6 | /A8 为一个 for 关键字开头的语句,表示循环遍历序列 A6。关键字不需要任何标记开头,是为语句格 | |
9 | >summary=summary+A8 | / 执行高斯同学的加法,没有高斯聪明,挨个加。注意,代码 B9 是循环体内容,相对于 for 关键字要退一格,据说 Python 也有强制退格,这样子,层次更分明。 | |
10 | return summary | / 该函数返回计算后的值 |
表(6)
4、变量的类型
前面已经提到,格子的名称可以直接作为变量使用,也就是定义变量时,在格子里面输入值就行了。那么变量的类型如何确定呢?熟悉 JS 的同学都知道,不管什么类型的变量都用 Var 来定义,至于值到底是什么类型,取决于值的写法。集算语言比 JS 更简便,Var 都不用写,那么集算语言的基本变量类型有哪些呢?
1、整数
直接输入数字即可,例如:100
2、长整数
数字后面加上字母 L,例如:100L
3、浮点数
直接输入带小数的数值,例如:3.14
4、布尔数
用 true 或 false 来表示,当然也可以是一个比较条件,例如:true、a>b
5、日期
缺省用连接符‘-’分开的年月日表示法,例如:2018-1-31。但是在表达式中引用时,得用日期函数转换。例如:=date(“2018-1-31”)。
注意: 用连接符‘-’分开的年月日是集算器缺省的格式,可以通过菜单“工具 > 选项”打开选项对话框,在“环境”页面的“日期格式”的一致,否则集算器无法解析,就会被当成普通字符串,而在表达式中引用时,就会报解析异常。
6、时间
缺省用冒号‘:’分开的时分秒表示法,例如:20:30:50。同样地,在表达式中需要用时间函数来转换。例如:=time(“20:30:50”)。
注意:和日期类型一样, 时间的格式也必须和选项对话框中的“时间格式”选项设置的格式一致。
7、字符串
直接输入字符串即可,例如: Hello,world!。但是对于有歧义的字符,比如电话号码,直接输入时,会被当成长整数,此时需要用单引号开头表示后面跟的是字符串,例如:’13901020888。在表达式中时则需要加上双引号。
下图是这些基本数据类型的一个汇总:
图(2)
这里简单介绍一下这里例子中用到的 debug 函数,在集算语言中,它用于调试输出中间变量的值。但是有些值,比如 100,光看到值我们分不清它是普通整数 100,还是长整数的 100,甚至可能是字符串 100。这时可以加上函数选项 @t,将变量的类型也一并输出。
上述 7 种基本数据类型是集算语言中能够直接使用的,但是光有它们,计算的便利性远远不够。集算语言发明出来就是用来应对数据计算的。所以,集算语言自身提供了一些专门用于计算的对象,只要使用对象的内置方法就能很轻松地完成大部分数据运算。
不过,集算语言自身还不算是一门通用程序语言,还不能像 Java 一样自定义对象。
8、对象
集算语言针对数据的处理,预置了很多的对象,常用的有数据库、序列、记录、序表、排列和游标等。
其中,序列、记录、序表和排列尤为常用,这里先简单介绍一下。
序列: 就是一堆数据的集合,但同时成员是有序的,相应地,你也可以理解为 Java 中的数组 Array。上面表(6)例子中,A6 格子的表达式“=to(1,100) ”返回的就是一个序列。此时我们知道,对 A6 的求和,只要调用序列的“sum”方法即可,就像这样:“=A6.sum()”。
记录 : 跟数据库中的记录相同,即一个由表结构描述的一组数据。通常由一些字段组成。
序表: 是序列的子集,当序列中的全部成员都是记录时,我们称之为序表。序表跟数据库中的数据表类似。用数据库对象的“query”方法查询出来的表就是序表。
排列: 是序表经过过滤运算后,得到的一张引用序表成员的序表。有点拗口,意思就是排列仍然是序表,只不过排列里面的记录跟计算出它的源表的记录是同一个对象。通常情况下,不用刻意区分排列和序表,只需要注意到修改排列里面字段的内容时,它的源表字段也会跟着改掉,因为本来就是同一条记录。
5、是时候演示真正的数据处理了
数据处理最常见的当然是从数据库取数,使用 SQL 查询出自己想要的数据表。我们来看看使用集算语言如何做这些事情。
首先当然得有数据库,我们在这里直接使用集算器现成的示例数据库。找到“安装路径 \esproc\bin\startDataBase.bat”,双击它启动示例数据库。下面按步骤来:
第 1 步,连接到数据源。这里是连接到一个叫 demo 的数据源,连接信息已经由安装包事先配置好了。如果要用自定义的数据源,只需打开菜单“工具 > 数据连接”,然后在弹出的“数据源”对话框中增加自己的数据源。那么如何连接它呢?会不会像 Java 一样要先使用 DriverManager 去注册 Driver,然后获取 Driver 再获得连接?……听着就有点晕,又是注册,又是连接什么的。集算语言可不会这么干,直截了当,一句 connect 就已足够,如图(3)中 A3 所示,根本不用去懂那么多大道理。
图(3)
第 2 步,查询取数。demo 同样地,不会像 Java 一样要构建什么 Statement 、设参数、再执行查询得到结果集,然后遍历结果集才能取数。在集算语言中,仍然是一句话的事,直接使用数据库对象的查询方法 query 就好,执行过后,直接得到序表对象,如图(3)中 A4 所示。
第 3 步,过滤序表。这一步看似多余(你完全可以打击我,在上面第 2 步的 SQL 中加上 WHERE 条件不就行了么?何必多此一举?嘿嘿,不带这样打击人的。我的例子是帮你入门,目的是让你了解集算语言的特点和结构。真要弄一个只能通过多步 SQL 才能算出结果的实例来时,我们就绕到例子里面出不来了)……但不要着急,这“多余”的一步正是体现了集算语言是为了 SQL 的分步计算而设计的。在后续章节的很多例子中,你会学习到面对令人头疼的复杂 SQL 时,使用分步运算将是一件多么爽心悦目、轻松愉快的事。回到主题,这一步过滤出库存量少于 10(斤)的商品,看看哪些商品比较畅销,函数仍然简单,一句 select 加上条件,如图(3)中 A5 所示。
第 4 步,修改商品值。从第 3 步得到的排列中,取出需要修改值的记录,由于记录就是序表的成员,所以只要像引用数组一样,给出坐标就可以得到记录对象。区别于 Java 中用中括号“[]” 进行数组引用,序表是一个对象,获取它的成员时,采用小括号“()”,如图(4)的 A6 格所示。可以看到该记录是花生,把这条记录的 “单价” 字段修改为 20(元),直接引用属性的字段名并赋值。如图(3)的 A7 所示。
另外,图(3)中还有 A1 跟 A2 两个格子,是为了演示集合的 sum 运算。
现在我们来看看执行结果,单击图(1)红圈中的三角形按钮,代码很快运行完毕,算完后,A 列格子的背景都从白色变成了黄色,这说明 A 列格子里面都有了返回值。
不过这样一次性从头到尾的执行,不利于我们更好地理解排列跟序表之间的成员关系。因此我们使用分解动作,一步步执行,每走一步停下来看看当前的执行结果。为此我们只要重复单击图(1)中蓝色圆圈里的单步执行按钮。
单步执行第一步,算出 A1 的结果如图(4):
图(4)
可见 A1 是一个序列对象,它的成员为 1 到 100 的整数。
第二步,A2 为 A1 对象 sum 后的结果,返回的就是一个整数值,如图(5):
图(5)
第三步,A3 为数据库对象,执行后可以看到数据库的一些属性设置,如图(6):
图(6)
第四步,A4 为从数据库对象 A3 中执行查询方法 query 后得到的序表对象,列出各种产品以及库存,如图(7):
图(7)
注意图(7)的红圈表示,此时花生的单价为 10(元)。
第五步,A5 为从序表 A4 中,过滤出库存量不到 10(斤)的产品。返回一个排列,内容如图(8):
图(8)
第六步,A6 为从排列 A5 中取出第 3 条记录,返回一条记录,内容如图(9):
图(9)
第七步,经过 A7 中对花生的单价重新赋值后,A6 格中记录的单价字段变为了 20(元),如图(10):
图(10)
上面第七步看似只是修改了排列中第 3 条记录的单价,但我们再回头看看序表 A4 的内容,发现序表中的花生的单价也变为了 20(元)。这就说明,排列和序列中的记录,其实就是同一条记录,A4 格的内容此时如图(11):
图(11)
经过本例的学习,我们对集算语言已经有了一个大致印象,也了解了集算语言在进行数据处理时使用的一些最基础的概念。当然,作为一门专业的数据处理语言,集算语言还有很多概念需要熟悉,还有很多函数需要了解。但这些都不是问题,老话不是说,磨刀不误砍柴工嘛,让我们通过后面的教程把刀磨得越来越锋利吧。