用JavaScript實現一門程式語言 2 (λanguage語言簡介)

繆宇發表於2019-01-14

在開始之前,應該對我們要是現實什麼有清晰的認識。

我們新語言(λanguage)的大概語法如下:

# 這是註釋

println("Hello World!");

println(2 + 3 * 4);

# `lambda` 或者 `λ`可以定義函式
fib = lambda (n) if n < 2 then n else fib(n - 1) + fib(n - 2);

println(fib(15));

print-range = λ(a, b)             # `λ` 和 `lambda` 功能相同
                if a <= b then {  # `then` 關鍵字是可省略的(看下面)
                  print(a);
                  if a + 1 <= b {
                    print(", ");
                    print-range(a + 1, b);
                  } else println("");
                };
print-range(1, 5);複製程式碼

注意上面的識別符號(print-range)可以包含減號。從個人喜好來講:我喜歡用空格把運算子隔開。我不喜歡駝峰命名法,比起下劃線我更喜歡用橫槓。所以說自己創造語言最爽的就是可以完全按照自己的喜好來設計。:)

控制檯輸出:

Hello World!
14
610
1, 2, 3, 4, 5複製程式碼

λanguage看起來有點像JavaScript,但其實並不是。首先,沒有申明,只有表示式。一個表示式返回一個值也可以替換其他表示式。分號用來間隔表示式。花括號用來建立表示式序列,並且它本身也是一個表示式。如下:

a = {
  fib(10);  # 沒有副作用, 但總會執行
  fib(15)   # 最後一個分號可以省略
};
print(a); # 列印出 610複製程式碼

函式被lambda 或者 λ 關鍵字定義,兩個關鍵字作用一樣。關鍵字後面必須跟上括弧,括號裡變數名用逗號分隔,和JavaScript類似。函式體是一個單一的表示式,也可以是包裹在{…}中的序列。最後一個表示式的計算得到的值會被返回。

這裡沒有var來建立新的變數,你可以用IIFE(立即執行函式表示式),用一個lambda,宣告變數作為引數。變數擁有函式作用域,函式是閉包 — 和JavaScript一樣。

儘管if它本身就是一個表示式。也可以得到和JavaScript三元運算子類似的效果。

a = foo() ? bar() : baz();           // JavaScript
a = if foo() then bar() else baz();  # λanguage複製程式碼

當分支通過花括號({)開始,那個then關鍵字是可以省略的(你可以看上面print-range的例子),其他情況then就不能省略了。else關鍵字用來創造分支。thenelse作為一個單一表示式,當然你也可以通過花括號和分號組合多個表示式。

λanguage中false是關鍵詞,也是唯一表示錯誤的值:

if foo() then print("OK");複製程式碼

如果foo() 的返回值不是false,將列印出”OK”。當然也有一個true關鍵詞表示完成,所有不等於false的都是true(包括數字0和空字串"")。

上面還有需要注意的就是,if條件語句不需要括號,當然加了也不會報錯。

一個完整的程式被編譯,就像嵌入在大括號裡一樣,因此你需要在每個表示式後面加分號,最後一個表示式除外。


這就是我們小巧的λanguage,它未必是一個好的語言,它有它的缺陷。有很多特性缺失,比如物件、陣列;我們不會把經歷放在這些上面,因為它們對於接下來的旅程沒有什麼幫助。如果這些都搞懂了,那麼你也可以很輕鬆的實現所有的特性。

在下個章節我們將開始寫λanguage的解析器了。

原文:lisperator.net/pltut/

相關文章