電柱商事

CHANGELOG v0.32.1

2019/12/18

[原文]

標準ライブラリ

コレクション

Enumerable#each_cons_pairIterator#cons_pair のドキュメントを修正(#8585

ネットワーク

HTTP::WebSocketon_close コールバックが、エラーが起きた際に必ず呼ばれるようになった(#8552

通信中、エラーで予期せず終了した場合に、on_close に記述した後処理がトリガされないの辛くネ?

OpenSSL 1.1 以上を使用する際に発生する spec の散発的なエラーを修正#8582

OpenSSL 側の TLS1.3 の挙動に対応するため。

コンパイラ

言語仕様

式展開の前に隣接する文字列リテラルを連結するようにした(#8581

おそらく v0.32.1 のリリースが急がれた直接の原因。

v0.32.0 で文字列リテラル内の式展開の内部実装が、String.build で逐次連結する方式から String.interpolation を使用する方式に変更になった。こうすると、コンパイラに手を入れなくても式展開の実装を変更できるようになる。

さてこの時、String.interpolation の引数は、文字列リテラルを地の文字列部分と展開式部分に分解したもの。

"I'm #{age} years old."
# ↓ 同じ
String.interpolation("I'm ", age, " years old.")

文字列リテラルの構成によって、この時の引数の数や型の組み合わせが変わってくるため、これを受けるメソッドの定義は def self.interpolation(*values : *T) forall T となっていて、上の例で ageInt32 型であれば、この場合の引数 values の型は Tuple(String, Int32, String) だとコンパイラは推定する。

Tuple(*T) 型は可変長の型引数を持つジェネリック型の1種で、この 可変長の型引数 は「指定できる個数が最大300」という制約があるらしい。1つのリテラルに150箇所近く式を埋め込まめる計算になるので、普通にクオータで括った文字列リテラルを使っている分にはほぼ顕在化しない制約なんだけど、問題はコンパイラがヒアドキュメントの各行をそれぞれ別の文字列リテラルとして認識する点。

行数の多いヒアドキュメントが存在すると、実用中にこの制約が顕在化してしまう可能性がある。

ということで、文字列リテラルの構成要素の中に連続する文字列リテラルがあったら、予め1つに結合してから String.interpolation に渡すよう変更された。