この記事はCrystal Advent Calendar 2018の1日目です。え? 今日は12/5だって?
うるせー、知らねー、Crystal Advent Cale
ndar 2018
あまりに盛り上がらなくて寂しいので書いていきます。
まえがき
2018年が始まった当初はバージョンが0.24.1だったCrystalも、12月現在ではバージョン0.27.0までリリースされ、様々な変化がありました。
構文の追加や、それに伴う標準ライブラリの拡充などなど。
それらをCHANGELOG.mdから拾いつつ説明していきたいと思います。
バージョン
0.24.2 (2018-03-08)
記念すべき2018年初のリリースです。
このバージョンはパッチバージョンしか上がっていないことからも分かるように、後方互換性のある変更しか入っていません。
強いて上げるなら面白い変更としてはskip_file
というマクロが新しく追加されたことでしょうか。
これは名前の通り、呼び出されるとそのファイルのコンパイルをスキップするというマクロです。これを使うと、特定の環境のみでコンパイルされてほしいようなソースコードがあるときに、従来ならその部分を丸ごとマクロのif
で囲っていたものを、ファイルに切り出して、そのファイルを早々にskip_file
する、ということができます。
例えば、このようにファイルがあったとすると、Foo.foo
はDarwin (macOS)向けにコンパイルした場合:darwin
を返して、Linuxの場合は:linux
を返すメソッドとして定義されて、それ以外の場合はFoo.foo
は定義されなくなります。
$ tree src
src
├── env
│ ├── foo_darwin.cr
│ └── foo_linux.cr
└── foo.cr
1 directory, 3 files
module Foo
end
require "./env/*"
{% skip_file unless flag?(:darwin) %}
module Foo
def self.foo
:darwin
end
end
{% skip_file unless flag?(:linux) %}
module Foo
def self.foo
:linux
end
end
0.25.0 (2018-06-11)
2018年最初のマイナーバージョンの上がったリリースです。Semantic Versioningでは0.x.x
台のバージョンは、後方互換性に影響のあるリリースでマイナーバージョンを上げるらしいので、ここではいくつかbreaking changeがあります。
しかしbreaking changeと言っても基本的にはそこまで影響があるものではなくて、例えばshards
コマンドへのエイリアスだったcrystal deps
コマンドが削除されたり、loop
メソッドのブロックにカウンタが渡されなくなったりしたことで影響を受ける人は少ないでしょう。
特徴的な変更点としてはヒアドキュメントの実装が見直されて、Rubyやシェルスクリプトと同様に、一行に複数のヒアドキュメントを置いたり、ヒアドキュメントからメソッドを続けたりできるようになりました。
これによって、このようなQuineが書けるようになりました。
puts (<<-'String'+"\n")*2, String
puts (<<-'String'+"\n")*2, String
String
よく分かんないけどなんかすごいですね。ちなみに、諸事情でstring interpolationの中ではヒアドキュメントは使えません。いや、誰か実装してくれたらいいんだけど、そもそも何が正しい仕様なのか分かんないよね‥‥。
加えて、ユーザーがアノテーションを新しく定義して、マクロから参照できるようになりました。
annotation FooAnn
end
@[FooAnn(value: 42)]
class Foo
end
pp {{ Foo.annotation(FooAnn)[:value] }} # => 42
いくつかのライブラリではこのアノテーションを使って、いい感じのシンタックスを提供していたりします。その辺の紹介が今後Crystal Advent Calendarであるといいですね。
標準ライブラリでもJSON::Serializable
やYAML::Serializable
というものが追加されて、アノテーションを使ってJSONやYAMLにシリアライズされるオブジェクトを楽に書くことができるようになりました。その辺の紹介も(略。
あと{% verbatim do %}...{% end %}
という構文が追加されたり、色々ありました。
他にもバグ修正とかメソッドの追加とかがあります。詳しくはCHANGELOG.mdを見てください。
0.25.1 (2018-06-27)
0.25.0の二週間後くらいにリリースされたバージョンです。
このリリースがバグ修正ばかりでそんなに面白い変更は無い気がします。
0.26.0 (2018-08-09)
二度目の後方互換性に影響のあるリリースです。
が、このリリースはそこまで大きな変更は無いかと思います。
というのも、このリリースではパーサーが新しい演算子(//
, &+
, &-
, &*
, &**
)をパースできるようになったりしましたが、それらの実装は加えられていなかったり、全体的に大きな変更のための準備をしている感が強いからです。
細かな修正や変更ばかりで面白そうなのが無いので飛ばします。
0.26.1 (2018-08-27)
0.26.0のマイナーチェンジです。マイナーチェンジなのに一番上に**(breaking-change)**ってマークされてる変更点が上げられてるのが面白いですね。これに関しては色々あったような気がするのですが、語るほどは覚えていないです。破壊的ではあるけど、現実的にはほとんど問題ないと思います。
0.27.0 (2018-11-02)
三度目のbreaking changeのあるリリースです。
そして、現状の最新版です。
これはそれなりに大きな変更のあるバージョンだと思います。
まず、0.26.0で追加された演算子に対して実装が追加されました。
&+
, &-
, &*
という演算子は、これまでの+
, -
, *
と同様の振舞いをします。
1 &+ 2 # => 3
1 &- 2 # => -1
1 &* 2 # => 2
そして、現在はまだ導入されていませんが、次のバージョン(0.28.0)以降は、従来の+
, -
, *
の挙動が変わって、オーバーフローをチェックするようになります。
Int32.MAX + 1 # raises OverflowError ?
Int32.MIN - 1 # raises OverflowError ?
Int32.MAX * 2 # raises OverflowError ?
これは地味に大きな変更だと思うので気を付けた方がいいかもしれません。
あまり詳しくないんですが、Swiftとかもこんな感じなんでしょうか?
(参考: crystal-lang/crystal#6223)
//
という演算子は、計算結果がfloor
で丸めこまれる/
になりました。これは整数を浮動小数点数で割っても整数のままにしたいときに使えます。
10 / 3.0 # => 3.33333333...
10 // 3 # => 3
確かこれはPythonと同じだった気がします。ちょっと自信がありません。
他にもHash#dig
が追加されたり、色々便利になっています。
まとめ
この一年、Crystalのコンパイラがものすごく進化したというわけではありませんが、着実に成長しているということを感じてもらえたら幸いです。
また、そこまで大きな変更が無いのも、Crystalが安定しつつある証左となるかもしれません。
あまり語りませんでしたがWindowsサポートやマルチスレッド対応も着実に進んでおり、2018年の頭には希望も無かった1.0.0への道も少しづつ明くなってきているのではないかと思います。
Crystalに興味を持ってもらえたら嬉しい限りです。
さてそれでは、この長い記事を最後まで読んでいただきありがとうございました。
あとCrystal Advent Calendarは執筆者を募集中です。というか足りなくてヤバい。頼む!!!