CoffeeScriptを知らない友人にCoffeeScriptを紹介する10のワンライナーテクニック

って、日本のギークならそういうんだろうなー

みなさんCoffeeScript使ってますか?ちょっとjsわかる人ならすぐ覚えられて、文法が平易で、かつRubyPythonぽく拡張されてるので非常にストレスが少ないです

しかも、元のJSの特性をほとんど妨げないようになってるので、jsでできてcoffeeでできないことはほとんどない。(まったくない、かはちゃんと確かめてませんが… ないと思います)


雰囲気、インデントブロックのRuby記法のような印象。


というわけで元ネタは 10 CoffeeScript One Liners to Impress Your Friends | ricardo.cc です


CoffeeScriptインストール済なら、$ coffee -i、もしくは $ coffee で対話インタプリタ起動します

1. リストに含まれるアイテムを2倍に

coffeescriptはレンジのリテラルと無名関数を使って配列操作ができます

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

あるいはこのように書くことも。

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

前者はRubyっぽい。Pythonistaには後者かな。

2. リストの中身を足し合わせる

javascriptに元からある機能ですが、map、reduce的なことができます。
1でmap使ってますね

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

(reduce == reduceLeft, reduceRight is also available)

3. ある単語が文の中に存在するか確認する

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

リストを返す

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

~ はCoffeeScriptにだけ存在する汚いトリックじゃないです。 thx:@uasi
~ は CoffeeScript にだけ存在する演算子ではなく、ただの汚いトリックである、云々

It is the bitwise NOT operator, which inverts the bits of it's operand. In practice it equates to -x-1. Here it works on the basis that we want to check for an index greater than -1, and -(-1)-1 == 0 evaluates to false.

4. ファイルを読む

これはnode.js使ってる場合ですが…
ファイルを扱うfs関数をrquireして使います

非同期でやる

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

同期でやる

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

node.js使う限り非同期が推奨。だけどワンライナーなら同期のほうが便利かも。
coffeescriptの対話インタプリタは補完が効かないのでやりづらいですが…

5. Happy Birthday

3のときだけ Robert へ。

[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]

後置の for 便利。

6. 数を分類

リストに入ってる数を二つに分類します

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

(could also use filter but then it wouldn't be a one-liner...)

7. XMLをとってきてパースする

requestっていうライブラリを使ってJSONに置き換えちゃいます。

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

これはPythonのrequestsライブラリのインスパイアかなー
シンプルで覚えやすい仕様,パワフルなPythonのWebアクセスモジュール request | TRIVIAL TECHNOLOGIES on CLOUD

8. リストから最大もしくは最小の数を探す

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

CoffeeScriptでは @ はthisのことです

9. 並列処理

WebWorkersのAPI使って並列処理できます。できるっていってるだけでコードは例示されてないですね…。
そりゃWebWorker使えばできるでしょうけど。

Not there yet. You can create child processes on your own and communicate with them, or use the WebWorkers API implementation. Skipping over.

10. エラトステネスの篩

素数判定アルゴリズムの1つ、エラトステネスの篩です

Couldn't get this down to one line. Ideas?

最初に書いた版

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

@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]

5の応用ですね


シンプルだが、若干トリッキーなもの

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

Arrayに+演算子を使うと、文字列に変換されます
.toString() は .join(',') と同じ。
これは Javascirptでも ([undefined] + "b" === "b") です


原文ここまで

12. jsf**k

っていうので思い出したんですが… id:voqnの人がjsで何やら楽しそうなことをやってまして

_=-~-~-~[];__=[][(![]+[])[_-_]+([][[]]+[])[_+_-_/_]+(![]+[])[_-_/_]+(!![]+[])[_-_]+(!![]+[])[_]+(!![]+[])[_/_]]+[];___=__[_]+__[_+_]+__[_-_/_]+(![]+[])[_]+(!![]+[])[_-_]+(!![]+[])[_/_]+(!![]+[])[_-_/_]+__[_]+(!![]+[])[_-_]+__[_+_]+(!![]+[])[_/_];___[___][___]((![]+[])[_/_]+(![]+[])[(_+_)/_]+(!![]+[])[_]+(!![]+[])[_/_]+(!![]+[])[_-_]+"(\""+'\\'+(([][[]]+[])[_-_])+(_)+(_-_)+(_+_/_)+(_+_)/_+"\");")(); 

これで、utf8の「あ」が返ってきます
coding as drawing: wtf!? JavaScript Empty Array Programming

いやーワンライナーって奥が深いですね(白目)