第 21 期 常規遍歷語法

2021-09-19 22:02:15 字數 2109 閱讀 2614

遍歷可以說是最基本的集合運算了,比如求和、計數、尋找最大最小值等聚合運算,按條件過濾集合、根據集合成員生成另乙個新集合,也都是遍歷運算。集合化語法要求我們能用很短的語句(經常就只有一句,而不是若干語句構成的一段程式)來描述大部分遍歷運算,這樣我們需要考查遍歷運算中可能出現的各種常見情況,並設計出合理自洽的語法規則。

我們從簡單到複雜來考查遍歷運算中的可能情況,並討論 sql 語法在這方面的表現。

直接針對集合成員運算

比如計算集合成員的合計。

這是最簡單的情況,採用普通的函式語法風格就可以,將待遍歷的集合作為引數獲得返回值,比如 sum(a) 用於計算整合 a 成員的合計,當然也可以使用物件式的語法風格寫成 a.sum()。

引用集合成員

比如我們不是要計算集合成員的合計,而是要計算平方和,那麼這個平方該如何描述?

這就會用到我們在談集合化語法時提到的 lambda 語法。平方這個運算本質上是乙個函式,在遍歷過程中它以被遍歷集合的當前成員作為引數,返回該引數的平方。而 lambda 語法允許將這個函式以表示式的形式並一起寫入整個計算遍歷表示式,乙個語句就可以完成。但這裡就有乙個問題,我們在這個 lambda 表示式中用什麼識別符號或符號表示這個當前成員呢?

顯然,象普通函式那個先定義引數名不是個好辦法,那會讓 lamdba 表示式寫得很臃腫,失去 lambda 語法的簡潔性。儘管有些程式語言確實是這麼做的,不過我們並不提倡。使用乙個固定的識別符號也不好,太長了用起來不方便,太短又很可能與其它區域性變數重名導致歧義。我們提倡在這裡使用乙個特殊符號來完成這個目的。

比如使用 ~ 表示當前成員時,平方和就可以寫成 a.sum(),簡單易懂。也可以分兩步做,先計算出集合成員的平方構成乙個新集合,再計算新集合的合計,寫成類似 a.().sum() 的形式,後一步不再需要 ~ 寫法,前一步仍需要 ~ 寫法來描述平方這個表示式函式。

使用結構化資料時引用字段

但是,我們發現,被認為是集合化語言的 sql 中並沒有使用某個符號或識別符號來表示當前遍歷成員,那麼 sql 又是怎麼解決問題 2 的呢?

事實上,sql 並沒有普通意義上可由任何成員構成的集合。sql 的集合就是表,而表的成員都是相同結構的記錄。sql 體系中有記錄這個概念,但並不能把記錄作為一種資料型別來引用。如果我們要在 sql 中針對乙個單值成員的集合進行遍歷,也只能把單值做成只有乙個欄位的記錄,而針對這些記錄構成的表進行遍歷。所有計算都是針對某些字段進行的,而不能針對整條記錄。

但這和 sql 沒有表示當前成員的符號有什麼關係呢?

我們在前面說集合化語法時還提到,面向結構化資料計算的集合化語法需要有簡潔的方式引用字段,sql 提供了可以直接引用欄位的便捷機制,而 sql 又只能計算字段,那就可以不必再提供引用當前成員(記錄)的手段了。比如 sql 中計算平方和一定是某個欄位的平方和,而整條記錄(集合成員)的平方則沒有意義。

sql 犧牲了集合的表達能力而簡化了語法。對於能夠支援泛型成員構成集合的語言來講,~ 寫法就是必要的了。而且,如果用於結構化資料計算時,sql 這種可以直接欄位的寫法也要得到支援才會方便,計算某銷售帳目的金額時寫成」~. 單價 ~. 數量」顯然不如寫成」單價 數量「更為簡單直觀,好的程式語言應當借鑑 sql 這種風格。

巢狀引用時的規則

遍歷在本質上就是乙個迴圈,而迴圈語句可能有多層,這樣遍歷也可能會有巢狀引用。比如計算 a,b 兩個集合的交集,簡單的演算法就是遍歷 a 的成員,看是不是在 b 集合**現過(也是遍歷),這就會涉及到兩層的遍歷。

這時候 ~ 寫法就會產生歧義了,~ 到底是指 a 集合還是 b 集合的當前成員,這需要在語法規則上做乙個明確的約定。

一般採用的是就近原則,即如果沒有指明 ~ 是哪個集合的,那預設認為是內層遍歷集合的,而外層遍歷集合的當前成員則需要顯式地指出其從屬於哪個集合。計算交集的表示式就可以寫成 a.select(b.count(~==a.~)>0),其中的 ~ 預設表示 b 的當前成員,而另乙個要顯式地寫成 a.~ 以示區分。

面向結構化資料計算時可以直接引用欄位名,這時也可能產生內外層的歧義,也可以適用於就近原則,sql 就是這樣。當內外層表有相同欄位名時,則預設被認為是記憶體表的字段,引用外層表的同名字段時必須顯式地寫上表名;如果內外存表中沒有相同欄位名,則可以正確識別出來而不必書寫表名。

遍歷運算雖然很基本,但設計其語法時仍有一些注意事項。sql 在這方面總體表現不錯,除了缺乏泛型成員的集合外,用於描述常規遍歷運算還是比較方便簡捷的。

第21周作業

1 搭建乙個 redis 哨兵集群 實驗環境 主節點 10.0.0.81 從節點1 10.0.0.82 從節點2 10.0.0.83 首先安裝redis,yum install y redis 實現redis的主從複製 在主節點,修改配置檔案 etc redis.conf sed ei.bak s ...

寬度優先搜尋第n遍

最近有種少年痴呆的感覺,停好幾次車然後每次走的時候,發現自行車不見了,後來在同伴驚愕與無語的表情中想起,原來是停到別的地方去了,但是還好,這幾次欠的飯錢準時還了,哈哈,今天把這道入門bfs小題研究的透透的,以後再忘,估計湊幾眼,也能想起來。迷宮的最短路徑 給定乙個大小為nm的迷宮。迷宮由通道和牆壁組...

21歲拿遍全世界程式設計大賽冠軍

程式設計師其實和多數的職業一樣,並不是一件特別的工作,只是程式設計師的許多小事被放大,關於程式設計師的段子太多,讓很多人對程式設計師產生了不小的誤解.程式設計師也成為了大多數人印象中的不修邊幅 不注意形象 每天揹著雙肩包 穿著工作t恤 月薪三萬 不愛說話 經常加班 木訥.其實大多數程式設計師要比普通...