博客 / 詳情

返回

Y 分鐘速成 LiveScript

源代碼下載: learnLivescript-cn.ls

LiveScript 是一種具有函數式特性且編譯成 JavaScript 的語言,能對應 JavaScript 的基本語法。 還有些額外的特性如:柯里化,組合函數,模式匹配,還有借鏡於 Haskell,F# 和 Scala 的許多特點。

LiveScript 誕生於 Coco,而 Coco 誕生於 CoffeeScript。 LiveScript 目前已釋出穩定版本,開發中的新版本將會加入更多特性。

非常期待您的反饋,你可以通過 @kurisuwhyte 與我連繫 :)

# 與 CoffeeScript 一樣,LiveScript 使用 # 單行註解。

/*
 多行註解與 C 相同。使用註解可以避免被當成 JavaScript 輸出。
*/
# 語法的部份,LiveScript 使用縮進取代 {} 來定義區塊,
# 使用空白取代 () 來執行函數。


########################################################################
## 1. 值類型
########################################################################

# `void` 取代 `undefined` 表示未定義的值
void            # 與 `undefined` 等價但更安全(不會被覆寫)

# 空值則表示成 Null。
null


# 最基本的值類型數據是羅輯類型:
true
false

# 羅輯類型的一些別名,等價於前者:
on; off
yes; no


# 數字與 JS 一樣,使用倍精度浮點數表示。
10
0.4     # 開頭的 0 是必要的


# 可以使用底線及單位後綴提高可讀性,編譯器會自動略過底線及單位後綴。
12_344km


# 字串與 JS 一樣,是一種不可變的字元序列:
"Christina"             # 單引號也可以!
"""Multi-line
   strings
   are
   okay
   too."""

# 在前面加上 \ 符號也可以表示字串:
\keyword                # => 'keyword'


# 數組是值的有序集合。
fruits =
  * \apple
  * \orange
  * \pear

# 可以用 [] 簡潔地表示數組:
fruits = [ \apple, \orange, \pear ]


# 你可以更方便地建立字串數組,並使用空白區隔元素。
fruits = <[ apple orange pear ]>

# 以 0 為起始值的數組下標獲取元素:
fruits[0]       # => "apple"


# 對象是無序鍵值對集合(更多給節將在下面章節討論)。
person =
  name: "Christina"
  likes:
    * "kittens"
    * "and other cute stuff"

# 你也可以用更簡潔的方式表示對象:
person = {name: "Christina", likes: ["kittens", "and other cute stuff"]}

# 可以通過鍵值獲取值:
person.name     # => "Christina"
person["name"]  # => "Christina"


# 正則表達式的使用跟 JavaScript 一樣:
trailing-space = /\s$/          # dashed-words 變成 dashedWords

# 你也可以用多行描述表達式!(註解和空白會被忽略)
funRE = //
        function\s+(.+)         # name
        \s* \((.*)\) \s*        # arguments
        { (.*) }                # body
        //


########################################################################
## 2. 基本運算
########################################################################

# 數值操作符與 JavaScript 一樣:
1 + 2   # => 3
2 - 1   # => 1
2 * 3   # => 6
4 / 2   # => 2
3 % 2   # => 1


# 比較操作符大部份也一樣,除了 `==` 等價於 JS 中的 `===`,
# JS 中的 `==` 在 LiveScript 裏等價於 `~=`,
# `===` 能進行對象、數組和嚴格比較。
2 == 2          # => true
2 == "2"        # => false
2 ~= "2"        # => true
2 === "2"       # => false

[1,2,3] == [1,2,3]        # => false
[1,2,3] === [1,2,3]       # => true

+0 == -0     # => true
+0 === -0    # => false

# 其它關係操作符包括 <、<=、> 和 >=

# 羅輯值可以通過 `or`、`and` 和 `not` 結合:
true and false  # => false
false or true   # => true
not false       # => true


# 集合也有一些便利的操作符
[1, 2] ++ [3, 4]                # => [1, 2, 3, 4]
'a' in <[ a b c ]>              # => true
'name' of { name: 'Chris' }     # => true


########################################################################
## 3. 函數
########################################################################        

# 因為 LiveScript 是函數式特性的語言,你可以期待函數在語言裏被高規格的對待。
add = (left, right) -> left + right
add 1, 2        # => 3

# 加上 ! 防止函數執行後的返回值
two = -> 2
two!

# LiveScript 與 JavaScript 一樣使用函式作用域,且一樣擁有閉包的特性。
# 與 JavaScript 不同的地方在於,`=` 變量賦值時,左邊的對象永遠不用變量宣告。

# `:=` 操作符允許*重新賦值*父作用域裏的變量。


# 你可以解構函數的參數,從不定長度的參數結構裏獲取感興趣的值。
tail = ([head, ...rest]) -> rest
tail [1, 2, 3]  # => [2, 3]

# 你也可以使用一元或二元操作符轉換參數。當然也可以預設傳入的參數值。
foo = (a = 1, b = 2) -> a + b
foo!    # => 3

# 你可以以拷貝的方式傳入參數來避免副作用,例如:
copy = (^^target, source) ->
  for k,v of source => target[k] = v
  target
a = { a: 1 }
copy a, { b: 2 }        # => { a: 1, b: 2 }
a                       # => { a: 1 }


# 使用長箭號取代短箭號來柯里化一個函數:
add = (left, right) --> left + right
add1 = add 1
add1 2          # => 3

# 函式裏有一個隱式的 `it` 變量,意謂着你不用宣告它。
identity = -> it
identity 1      # => 1

# 操作符在 LiveScript 裏不是一個函數,但你可以簡單地將它們轉換成函數!
# Enter the operator sectioning:
divide-by-2 = (/ 2)
[2, 4, 8, 16].map(divide-by-2) .reduce (+)


# LiveScript 裏不只有應用函數,如同其它良好的函數式語言,你可以合併函數獲得更多發揮:
double-minus-one = (- 1) . (* 2)

# 除了普通的數學公式合併 `f . g` 之外,還有 `>>` 和 `<<` 操作符定義函數的合併順序。
double-minus-one = (* 2) >> (- 1)
double-minus-one = (- 1) << (* 2)


# 説到合併函數的參數, LiveScript 使用 `|>` 和 `<|` 操作符將參數傳入:
map = (f, xs) --> xs.map f
[1 2 3] |> map (* 2)            # => [2 4 6]

# 你也可以選擇填入值的位置,只需要使用底線 _ 標記:
reduce = (f, xs, initial) --> xs.reduce f, initial
[1 2 3] |> reduce (+), _, 0     # => 6


# 你也能使 _ 讓任何函數變成偏函數應用:
div = (left, right) -> left / right
div-by-2 = div _, 2
div-by-2 4      # => 2


# 最後,也很重要的,LiveScript 擁有後呼叫特性, 可以是基於回調的代碼
# (你可以試試其它函數式特性的解法,比如 Promises):
readFile = (name, f) -> f name
a <- readFile 'foo'
b <- readFile 'bar'
console.log a + b

# 等同於:
readFile 'foo', (a) -> readFile 'bar', (b) -> console.log a + b


########################################################################
## 4. 模式、判斷和流程控制
########################################################################

# 流程控制可以使用 `if...else` 表達式:
x = if n > 0 then \positive else \negative

# 除了 `then` 你也可以使用 `=>`
x = if n > 0 => \positive
    else        \negative

# 過於複雜的流程可以用 `switch` 表達式代替:
y = {}
x = switch
  | (typeof y) is \number => \number
  | (typeof y) is \string => \string
  | 'length' of y         => \array
  | otherwise             => \object      # `otherwise` 和 `_` 是等價的。

# 函數主體、宣告式和賦值式可以表式成 `switch`,這可以省去一些代碼:
take = (n, [x, ...xs]) -->
                        | n == 0 => []
                        | _      => [x] ++ take (n - 1), xs


########################################################################
## 5. 推導式
########################################################################

# 在 JavaScript 的標準函式庫裏有一些輔助函數能幫助處理列表及對象
#(LiveScript 則帶有一個 prelude.ls ,作為標準函式庫的補充 ), 
# 推導式能讓你使用優雅的語法且快速地處理這些事:
oneToTwenty = [1 to 20]
evens       = [x for x in oneToTwenty when x % 2 == 0]

# 在推導式裏 `when` 和 `unless` 可以當成過濾器使用。

# 對象推導式在使用上也是同樣的方式,差別在於你使用的是對象而不是數組:
copy = { [k, v] for k, v of source }


########################################################################
## 6. OOP
########################################################################

# 雖然 LiveScript 是一門函數式語言,但具有一些命令式及面向對象的特性。
# 像是 class 語法和一些借鏡於 CoffeeScript 的類別繼承語法糖:
class Animal
  (@name, kind) ->
    @kind = kind
  action: (what) -> "*#{@name} (a #{@kind}) #{what}*"

class Cat extends Animal
  (@name) -> super @name, 'cat'
  purr: -> @action 'purrs'

kitten = new Cat 'Mei'
kitten.purr!      # => "*Mei (a cat) purrs*"

# 除了類別的單一繼承模式之外,還提供了像混入 (Mixins) 這種特性。
# Mixins 在語言裏被當成普通對象:
Huggable =
  hug: -> @action 'is hugged'

class SnugglyCat extends Cat implements Huggable

kitten = new SnugglyCat 'Purr'
kitten.hug!     # => "*Mei (a cat) is hugged*"

延伸閲讀

LiveScript 還有許多強大之處,但這些應該足夠啓發你寫些小型函數式程式了。 LiveScript 有更多關於 LiveScript 的資訊 和線上編譯器等着你來試!

你也可以參考 prelude.ls,和一些 #livescript 的網絡聊天室頻道。


有建議?或者發現什麼錯誤?在 Github 上開一個 issue,或者發起 pull request!

原著 Christina Whyte,並由 0 個好心人修改。
© 2022 Christina Whyte
Translated by: ShengDa Lyu
本作品採用 CC BY-SA 3.0 協議進行許可。

user avatar yiiouo 頭像 carloslab 頭像 seu_duter 頭像 pulangte 頭像 kinfuy 頭像
5 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.