最近のCrystal

昨年末に「Ruby脳にはCrystalつらい Advent Calendar 2015」というのを書きました。

qiita.com

当時の Crystal のバージョンは 0.10 だったのですが、その後バージョンがあがって改善されてたりするので、紹介します。

カレントディレクトリに .crystal を作らなくなった

tmtms.hatenablog.com

Crystal 0.16 で、CRYSTAL_CACHE_DIR 環境変数を設定しなくても、デフォルトで $HOME の下にキャッシュディレクトリを作るようになりました。

$HOME/.cache/crystal または $HOME/.crystal が使用されます。

否定条件でも型の絞り込みができるようになった

tmtms.hatenablog.com

もともと次のように書けば nil かそれ以外かで条件分岐できたのですが、

def hoge(str_or_nil)
  if str_or_nil
    p str_or_nil.size
  else
    puts "nil"
  end
end
hoge("abc") #=> 3
hoge(nil)   #=> nil

条件を反転させると、コンパイル時に型チェックでエラーになってしまってました。

def hoge(str_or_nil)
  if !str_or_nil
    puts "nil"
  else
    p str_or_nil.size  #=> undefined method 'size' for Nil
  end
end
hoge("abc")
hoge(nil)

Crystal 0.15 で後者の例もエラーにならなくなりました。地味に嬉しいです。

デフォルト値を持たない引数も名前付き引数として扱える

tmtms.hatenablog.com

Crystal は Ruby と異なり、メソッド定義時に名前付き引数を受けつけるための専用の構文はなく、デフォルト値つきの引数は名前付き引数として扱うことができていました。

def hoge(a, b=1, c=2)
  p [a, b, c]
end

hoge(123)                  #=> [123, 1, 2]
hoge(123, b: 456)          #=> [123, 456, 2]
hoge(123, c: 789)          #=> [123, 1, 789]
hoge(123, b: 456, c: 789)  #=> [123, 456, 789]
hoge(123, 456)             #=> [123, 456, 2]
hoge(123, 456, c: 789)     #=> [123, 456, 789]
hoge(123, 456, 789)        #=> [123, 456, 789]
hoge(a: 123)               #=> wrong number of arguments for 'hoge' (given 0, expected 1..3)

最後の行はデフォルト値を持たない引数を名前付き引数として使おうとしてコンパイル時エラーになります。

Crystal 0.16 から、デフォルト値がない引数でも名前付き引数として扱うことができるようになりました。

def hoge(a, b=1, c=2)
  p [a, b, c]
end

hoge(123)                  #=> [123, 1, 2]
hoge(123, b: 456)          #=> [123, 456, 2]
hoge(123, c: 789)          #=> [123, 1, 789]
hoge(123, b: 456, c: 789)  #=> [123, 456, 789]
hoge(123, 456)             #=> [123, 456, 2]
hoge(123, 456, c: 789)     #=> [123, 456, 789]
hoge(123, 456, 789)        #=> [123, 456, 789]
hoge(a: 123)               #=> [123, 1, 2]

Ruby の Hash 構文がタプルになってつらい!

Crystal 0.17 から、タプルリテラルが導入されました。Ruby の新し目の Hash リテラルと同じ表記です。

Crystal で Hash をリテラルで書こうとすると、シンボルをキーとする場合でも Ruby の古い表記で記述する必要があります。

hoge = {a: 123, b: "abc"}        #=> タプル
hoge = {:a => 123, :b => "abc"}  #=> Hash

ちょっとRuby脳にはつらいです。

ということで「Ruby脳にはCrystalつらい Advent Calendar 2015」26日目の記事でした!