CoffeeScriptがさらに拡張されたLiveScriptの紹介

2ヶ月ぐらい前にHackersNewsで見かけて、触ってみたらやたらかっこよかったので紹介。

LiveScript http://gkz.github.com/LiveScript/


LiveScriptはCoffeeScriptがさらに拡張された、JavaScriptコンパイルされる系言語。
JavaScriptが最初に名付けられた名前「livescript」に立ち返って、関数型の特色が色濃い言語のようです。
OOPと関数型のマルチパラダイムという点でScalaなどに近いのかもしれません。型が弱いScalaで、見た目はHaskell

インストール

npm install -g livescript

より関数型っぽくしたい人のための prelude-lsと一緒に使うのが推奨されているそうです

npm install prelude-ls

追加されるメソッドについては以下を参照
prelude.ls - a JavaScript functional programming library - the recommended base library for LiveScript http://gkz.github.com/prelude-ls/#installation


インタプリタで試してみる

$ livescript    
LiveScript 0.9.10
Usage: livescript [options] [files] [arguments]

Options:
  -i, --interactive    start REPL; use ^J for multiline input
  -c, --compile        compile to JavaScript and save as .js files
  -o, --output DIR     compile into the specified directory
  -w, --watch          watch scripts for changes, and repeat
  -s, --stdin          read stdin
  -e, --eval           read command line arguments as script
  -r, --require FILE+  require libraries before executing
  -b, --bare           compile without the top-level function wrapper
  -p, --print          print the result to stdout
  -l, --lex            print the tokens the lexer produces
  -t, --tokens         print the tokens the rewriter produces
  -a, --ast            print the syntax tree the parser produces
  -j, --json           print/compile as JSON
  -n, --nodejs ARGS+   pass options through to the "node" binary
  -v, --version        display version
  -h, --help           display this

livescript> global <<< require \prelude-ls
livescript> map (* 2), [1 to 5]
 [2, 4, 6, 8, 10]

ベースがCoffeeScriptなだけに環境周りは結構整っています。

とりあえず書いてみる

拡張子はls。以下のはサンプルをちょっと拡張したもの。

hoge.ls

# preludeをグローバル名前空間に適用
global <<< require \prelude-ls

# カリー化, パターンマッチ
take(n, [x, ...xs]:list) =
  | n <= 0     => []
  | empty list => []
  | otherwise  => x & take n - 1, xs

take 2, [1 2 3 4 5] #=> [1, 2]

takeThree = take 3
takeThree [3 to 8] #=> [3, 4, 5]

# Implicit argument
reverse = -> it.reverse!

# 関数合成
lastThree = reverse >> takeThree >> reverse
console.log lastThree [1 to 8] #=> [6, 7, 8]

(シンタックスハイライトはぱっとみ似てるのでHaskell借りてます)

$ livescript hoge.ls
[6,7,8]

CoffeeScriptのパーサを引き継いてるのでCoffeeっぽく書いてもなんとなく動きますね

CoffeeScriptから置き換える際の差分は http://gkz.github.com/LiveScript/#coffee-to-ls に書いてあります。


関数合成

even    = (x) -> x % 2 == 0
invert  = (x) -> not x
odd     = invert << even

(f << g) x は f(g(x)) と同じ
(f >> g) x は g(f(x)) と同じ

Piping

[1, 2, 3, 4, 5] |> filter even |> map (* 2) |> fold (+), 0 

匿名な引数

filter (-> it.length > 5), ['tiny', 'middle', 'longer'] 

リスト内包表記

r = [x + 1 for x in [2, 3, 4, 5] when x + 1 isnt 4] 
r #=> [3, 5, 6] 

OOP

ほとんどcoffee-scriptと同じ。コンストラクタ定義に略記が追加

class Item
  # constructor
  ->
    @id = Math.random!

  # properties and methods
  type   : \unknown
  getName: -> @name ? @id
 
class Box extends Item
  (@name) ->
    super ...

  type: \cube
 
  # any code
  priv    = \secret
  @static = -> priv

エディタ環境

textmate/SublimeText2用 をいれてみた

cd ~/Library/Application\ Support/Sublime\ Text\ 2/Packages
git clone git://github.com/paulmillr/LiveScript.tmbundle.git

Vim用もあるらしいです
gkz/vim-ls https://github.com/gkz/vim-ls

感想

Haskell風構文でCoffeeScriptJavaに対するScala的な拡張を施したもの。
やたら自由に書けてしまうので、小さいチームでの開発のほうが向いている気がする。
とりあえず練習にenchant.jsのミニゲームでも作ってみたい。

おまけ

Coffee/Coco/CocoっていうCoffee方言?の言語あるそうです。調べたらlivescriptはcocoのforkだった...)
satyr/coco https://github.com/satyr/coco