10個讓朋友對你另眼相看的CoffeeScript單行代碼絕技

或許你已經看過了Marcus Kazmierczak的這篇在HN上頗受歡迎的「10個讓朋友對你另眼相看的Scala單行代碼絕技」了, 儘管我對Scala並不瞭解(Java也是),可是這看起來還真不錯,因而我也有點手癢, 想讓個人朋友們也對我另眼相看一小下——不過不是從Java到Scala,我是從Javascript到CoffeeScript, 下面的例子都是基於node.js環境的。javascript

1. 列表中的每項乘2

Marcus的第一個例子演示了map函數,咱們可使用range語法以及一個匿名函數來完成一樣的事情:html

[1..10].map (i) -> i*2

咱們還有下面這個更易讀的版本:java

i * 2 for i in [1..10]

2. 數列求和

Javascript(以及CoffeeScript擴展)一樣有原生的map以及reduce函數:node

[1..1000].reduce (t, s) -> t + s  

(reduce == reduceLeft, 還有reduceRight)

3. 檢查字符串是否包含某個單詞

這實在是再簡單不過了,由於咱們有some方法,只要數組中的任何元素知足條件它就會返回true:git

wordList = ["coffeescript", "eko", "play framework", "and stuff", "falsy"]  
tweet = "This is an example tweet talking about javascript and stuff."  

wordList.some (word) -> ~tweet.indexOf word

下面的語句會返回匹配到的單詞:github

wordList.filter (word) -> ~tweet.indexOf word

~在CoffeeScript中並非什麼特別的操做符,這裏咱們使用了一個小技巧,它實際上就是按位取反操做符, 會對數值按位進行取反操做,在上面的例子裏它至關於-x-1,這裏咱們用它來檢查數組的下標是否大於-1, 由於-(-1)-1 == 0,會返回false。web

4. 讀取文件

使用客戶端Javascript框架的用戶會對下面的代碼感到很親切:算法

fs.readFile 'data.txt', (err, data) -> fileText = data

你還可使用同步版本:編程

fileText = fs.readFileSync('data.txt').toString()

不過在node.js中,你只有在程序啓動時纔可使用同步版本,其它時間你都應該使用異步版本。json

5. 生日快樂

首先,先來一個Scala版本的映射版,不過我對字符串作了一點篡改:

[1..4].map (i) -> console.log "Happy Birthday " + (if i is 3 then "dear Robert" else "to You")

下面再來一個優化版,這個讀起來更像僞代碼了:

console.log "Happy Birthday #{if i is 3 then "dear Robert" else "to You"}" for i in [1..4]

6. 過濾數列

將一個數字序列過濾爲兩種類型,這已經很接近了:

passed = []  
failed = []  
(if score > 60 then passed else failed).push score for score in [49, 58, 76, 82, 88, 90]

(也可使用filter,可是那樣就不是一行了。。。)

7. 讀取並解析一個XML Web service

XML是個神馬東東?從沒聽過,讓咱們把它換成json,你可使用request庫:

request.get { uri:'path/to/api.json', json: true }, (err, r, body) -> results = body

8. 找到一個數列的最小(最大)值

咱們有很是棒的apply函數,它可讓你經過一個數組來調用擁有可變參數的函數:Math.max以及Math.min, 這兩個函數都接受可變長度參數,好比Math.max 30, 10, 20返回30,讓咱們試試下面的代碼:

Math.max.apply @, [14, 35, -7, 46, 98] # 98  
Math.min.apply @, [14, 35, -7, 46, 98] # -7

9. 並行處理

這個還不行,你能夠建立子進程並本身和它們進行通信, 或者使用WebWorkers API實現,讓咱們跳過這個。

10. 埃拉託斯特尼篩法

(譯者注:埃拉託斯特尼篩法是古希臘數學家埃拉託斯特尼所提出的一種簡單的斷定素數的算法,詳細介紹請參見維基百科)

一行能夠搞定?

sieve = (num) ->  
    numbers = [2..num]  
    while ((pos = numbers[0]) * pos) <= num  
        delete numbers[i] for n, i in numbers by pos  
        numbers.shift()  
    numbers.indexOf(num) > -1

更新 (06/05): @dionyziz 發給了我這個更簡潔的版本:

primes = []  
primes.push i for i in [2..100] when not (j for j in primes when i % j == 0).length

如今咱們能夠像原始版同樣用一行來完成斷定了:

(n) -> (p.push i for i in [2..n] when not (j for j in (p or p=[]) when i%j == 0)[0]) and n in p

或者是下面這樣:

(n) -> (p.push i for i in [2..n] when !(p or p=[]).some((j) -> i%j is 0)) and n in p

11. 獎勵

最後,再獎勵大家一個你確定沒見過的最易讀的fizzbuzz(數3,數5遊戲)版本:

"#{if i%3 is 0 then 'fizz' else ''}#{if i%5 is 0 then 'buzz' else ''}" or i for i in [1..100]

更新:基於satyr的提示,這裏是一個更簡單,也更取巧的版本:

['fizz' unless i%3] + ['buzz' unless i%5] or i for i in [1..100]

若是你對數組使用+操做符,它會變成一個字符串,當數組中包含undefined或是null時,[].toString()和[].join(',')是一個效果,這在Javascript中也一樣有效([undefined] + "b" === "b")

結論

我很吃驚這些例子中的一些語法竟然和Scala如此接近,而我原覺得它應該是屬於另一個星球的編程語言。

你能夠在這裏瞭解更多關於CoffeeScript的知識, 以及代碼片斷, 也歡迎在Twitter上Follow @ricardobeat.

相關文章
相關標籤/搜索