集算器初體驗
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、浮點數
直接輸入帶小數的數值,例如: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)
經過本例的學習,我們對集算語言已經有了一個大致印象,也了解了集算語言在進行數據處理時使用的一些最基礎的概念。當然,作為一門專業的數據處理語言,集算語言還有很多概念需要熟悉,還有很多函數需要了解。但這些都不是問題,老話不是說,磨刀不誤砍柴工嘛,讓我們通過後面的教程把刀磨得越來越鋒利吧。
集算器初體驗