10個驚豔的CoffeeScript單行程式碼

2016-04-21    分類:WEB開發、程式設計開發、首頁精華0人評論發表於2016-04-21

本文由碼農網 – 小峰原創翻譯,轉載請看清文末的轉載要求,歡迎參與我們的付費投稿計劃

你可能已經讀過Marcus Kazmierczak部落格中的《10 Scala One Liners to Impress Your Friends》。雖然我不懂Scala(以及Java),但是它看上去真心不錯,所以我決定也要驚豔我的朋友一番——人家從Java到Scala,我從Javascript到CoffeeScript。假設所有例子使用node.js作為環境。

【譯者注】:譯者對CoffeeScript不太瞭解,只是覺得這種單行程式碼還挺有藝術感的,於是粗糙地翻譯出來分享給大家,有不對的地方還請指出來: )

1.陣列中的每個元素乘以2

Marcus從炫耀 map 函式開始。我們可以使用字面範圍和匿名函式做到完全相同的事情:

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

更多表現形式

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

2.陣列中的元素求和

Javascript(以及CoffeeScript的擴充套件),也有本地map和reduce函式:

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

(reduce == reduceLeftreduceRight 也可)

3.驗證word在字串中是否存在

非常容易,因為方法不止一種。如果陣列中的任何元素滿足函式的話就返回true:

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

返回匹配的word:

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

~ 在CoffeeScript中不是一個特殊的運算子,只是一個鬼把戲而已。它是一個按位取非運算子,即反轉運算元的二進位制數字。在實踐中它相當於-X-1。這裡它的工作原理是檢查索引是否大於-1,並且 – ( – 1)-1 == 0計算為false。

4.讀取檔案

JavaScript框架的客戶端使用者熟悉這個一種思路:

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

你也可以使用同步版本:

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

在Node.js中,這僅接受應用程式的啟動程式。你應該在你的程式碼中使用非同步版本。

5.生日快樂

首先,輸出一個1對1的對映集合,並在中間混合插入一小段字串:

[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.過濾陣列中的數字

過濾陣列中的數字分為兩類。有文化的方式:

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

(感謝@giacecco幫助縮短了此處的程式碼)

以及函式式方法:

[passed, failed] = [49, 58, 76, 82, 88, 90].reduce ((p,c,i) -> p[+(c < 60)].push c; p), [[],[]]

7.獲取並解析一個XML Web服務

XML是什麼?不曾聽說過。那麼不妨使用requst庫獲取JSON:

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

更新(6月/5日):@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版本,你可以看到:

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

編輯:通過一個小提示使之更簡單,但更有技巧:

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

當你在陣列中使用 + 運算子時,它會轉換為字串。[].toString()[].join(',')相同,它在陣列值undefinednull情況下,給出一個空的字串。這也適用於Javascript([undefined] + "b" === "b")。

結論

現代程式語言的表達令人驚訝。同樣我令我驚訝的是,這些對映中的一些語法是如此相似於Scala,但這兩種語言卻遠隔萬水千山。

譯文連結:http://www.codeceo.com/article/10-coffeescript-oneline-code.html
英文原文:ricardo
翻譯作者:碼農網 – 小峰
轉載必須在正文中標註並保留原文連結、譯文連結和譯者等資訊。]

相關文章