1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
|
---
language: LiveScript
filename: learnLivescript-cn.ls
contributors:
- ["Christina Whyte", "http://github.com/kurisuwhyte/"]
translators:
- ["ShengDa Lyu", "http://github.com/SDLyu/"]
lang: zh-cn
---
LiveScript 是一种具有函数式特性且编译成 JavaScript 的语言,能对应 JavaScript 的基本语法。
还有些额外的特性如:柯里化,组合函数,模式匹配,还有借镜于 Haskell,F# 和 Scala 的许多特点。
LiveScript 诞生于 [Coco][],而 Coco 诞生于 [CoffeeScript][]。
LiveScript 目前已释出稳定版本,开发中的新版本将会加入更多特性。
[Coco]: http://satyr.github.io/coco/
[CoffeeScript]: http://coffeescript.org/
非常期待您的反馈,你可以通过
[@kurisuwhyte](https://twitter.com/kurisuwhyte) 与我连系 :)
```coffeescript
# 与 CoffeeScript 一样,LiveScript 使用 # 单行注解。
/*
多行注解与 C 相同。使用注解可以避免被当成 JavaScript 输出。
*/
```
```coffeescript
# 语法的部份,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](http://livescript.net/)有更多关于 LiveScript 的资讯
和线上编译器等着你来试!
你也可以参考
[prelude.ls](http://gkz.github.io/prelude-ls/),和一些 `#livescript`
的网络聊天室频道。
|