はじめに
D言語の公式コンパイラである dmd が更新され、最新バージョンである 2.106.0
が 2023/12/01 にリリースされました。
今回は前回からほぼ2ヶ月でのリリースで、コンパイラ周りの強化改善とDUBの強化が目玉になっているようです。
今回も一通りの内容ご紹介していきます。
より細かい内容は下記リンクからChangeLogをご覧ください。
- ChangeLog
また、前回である2月版のリリースまとめは以下になります。
- D言語の更新まとめ 2023年8月版(dmd 2.105.0)
変更点目次
コンパイラ変更点
-
catch
節は、const
またはmutable
な例外のみを受け付けるようになりました。 - C++ヘッダー生成が改善されました。
-
enum
ストレージクラスを持つ関数は、現在非推奨となりました。(エラーだったものが非推奨に戻されました) - コンパイラに
-nothrow
スイッチが追加されました。 - Intel CET(Control-flow Enforcement Technology)のIBT(Indirect Branch Tracking)保護がサポートされました。
- DIP1000による
scope class
インスタンスの生成時に、非スコープコンストラクタを使用することは@system
のみ可能になりました。 - グローバル
const
変数は、非shared static this
の静的コンストラクタからは初期化できなくなりました。 - グローバル変数として連想配列で初期化できるようになりました。
-
_d_newarray{U,T,iT}
はテンプレートに変換されました。
改善点
- Bugzilla 5445: DMDはHOMEディレクトリにある".dmd.conf"を探しません。
- Bugzilla 10532:
static foreach
の時に到達不能な文の警告を抑制します。 - Bugzilla 11070:
switch
式で宣言文を許可します。 - Bugzilla 15752: 不正な連想配列空値の割り当てに対するより良いエラーメッセージを出力します。
- Bugzilla 20522: 未定義の変数によって引き起こされる到達不能な文の警告を抑制します。
- Bugzilla 21520: dmdはNO_COLOR環境変数を尊重しません。
- Bugzilla 21852: -verrors=contextを使用すると、Locのフォーマットされた1行エラーがコンテキストを出力するようになります。
- Bugzilla 23958: ImportC: 未定義の識別子
__builtin__sprintf_chk
- Bugzilla 24060: "Cannot create instance of abstract class" エラーの改善
- Bugzilla 24084: コンパイラに
-nothrow
スイッチを追加 - Bugzilla 24173: ImportCにMicrosoftのiNN整数リテラルサフィックスを追加
ランタイム変更点
変更点
- 4つの
core.memory.GC
関数が@safe
とマークされました。
ライブラリ変更点
変更点
-
etc.c.odbc
の廃止が取り消され、非Windowsシステムで再度使用が可能になりました。 -
isInputRange
はオプションの要素型を受け取るようになりました。 -
std.traits
にUnshared
が追加されました。
改善点
- Bugzilla 24082: Int128.toStringを追加し、std.formatをサポートします。
- Bugzilla 24142: Int128を整数型および浮動小数点型にキャストできるようにします。
DUB変更点
-
dub build
に--deep=
オプションが追加されました。 -
dub describe
にdefault-config
、configs
、default-build
、builds
のデータが追加されました。 -
dub init
に、パッケージ形式とライセンスの選択メニューが追加されました。 - DUBに
--recipe=
スイッチが追加されました。
注目トピック
言語・コンパイラ変更点
コンパイラに -nothrow
スイッチが追加されました。
コンパイラに -nothrow
スイッチが新たに追加されました。今回の強化の中でもやや異色の強化と言えるかもしれません。
D言語(に限らず多くのプログラミング言語)のコンパイラでは、例外(Exceptions)を投げることを好まず、エラー処理に別の方法を用います。これは多くの場合、例外処理の処理コストが重いこと、例外処理のサポートだけでパフォーマンスが劣化し得る、とにかく性能を改善するためです。
例外をサポートすること自体のコストというと、例えば、RAII(Resource Acquisition Is Initialization)オブジェクトのためのスタックアンワインダーの追加や、try-catch
境界を越える際に起きるさまざまな最適化の阻害などがあります。これらのコストは、例外が一度も投げられない場合(要はエラーにならず正常に処理が終了する場合)でも発生します。
そこで、大規模で最適化が重要なプロジェクトでは、プロジェクト内の全てのコードに nothrow
修飾子を適用することで対処を試みることがあります。これは非常に労力を要する作業です。特に、モジュールのトップに nothrow:
を記述しても、クラスや構造体のメンバ関数には影響を与えないため、class
や struct
ごとに nothrow:
を繰り返さなければならないという問題があります。
この問題を解決するために、今回 -nothrow
スイッチが導入されました。このスイッチを使用すると、コンパイラはスタックアンワインダを追加せず、様々な最適化を有効にします。この機能は以前から -betterC
コードには存在していましたが、この変更により通常のDコードでも利用可能になります。
-nothrow
スイッチを使用することで、セマンティック解析には影響を与えず、コード生成のプロセスのみが変更されます。このスイッチはネームマングリングにも影響しません。
開発者は、このスイッチを使って、例外処理が実行可能ファイルのサイズやパフォーマンスにどのような影響を与えるかを容易に評価できます。特に例外を投げないコードのパフォーマンス改善に興味がある場合は、非常に有用です。
とはいえ、実際例外が発生するコードも多数あると思いますので、まずは例外処理によってどれくらい影響があるのか調べる目的で使うことになると思われます。
-nothrow
スイッチの追加によってこういった調査が行えるようになるので、今後はより高速なプログラムを開発できるようになるかもしれませんね。
Intel CET(Control-flow Enforcement Technology)のIBT(Indirect Branch Tracking)保護がサポートされました。
今回の注目トピック、IntelのCET(Control-flow Enforcement Technology)におけるIBT(Indirect Branch Tracking)保護のサポートです。
IntelのCETは、プログラムの制御フローを攻撃者が不正にリダイレクトするのを防ぐための技術です。IBTは、特に攻撃者が間接分岐を意図しない場所に送るのを防ぎます。
参考: https://gihyo.jp/article/2022/11/daily-linux-221107
IntelのIBTは、コンパイラが特別な命令(endbr32およびendbr64)を発行することを期待しており、IBTをサポートしていない古いプロセッサではこれらの命令はnop(何もしない)命令と同等になります。そのため、IBTがアクティブな状態でコンパイルされたプログラムは、任意のx86プロセッサで互換性があり、対応しているプロセッサ上であれば保護されます。
DMDでこのIBT保護を有効にするには、コンパイラに -fIBT
フラグを渡す必要があります。このフラグを渡すと、コンパイラはIBT用の命令発行を自動的に追加します。ただし、インラインアセンブラを使用する場合は注意が必要です。コンパイラはインラインアセンブラ内でのIBTまでは処理しません。
また、Dプログラム内でIBTが有効化されているかどうかを確認するには、getTargetInfo
トレイトを以下のように使用します。
// IBTがアクティブな場合
static assert(__traits(getTargetInfo, "CET") == 1); // CET == 1 はIBTがアクティブであることを示す
// IBTがアクティブでない場合
static assert(__traits(getTargetInfo, "CET") == 0); // CET == 0 はIBTがアクティブでないことを示す
プログラムのセキュリティに興味がある開発者は、この新機能の活用を検討してみてください。
グローバル変数として連想配列で初期化できるようになりました。
これまでのD言語では、グローバル変数を連想配列で初期化するには、モジュールのコンストラクタやenumを使用する必要がありました。しかし、2.106.0の更新により、連想配列を直接グローバル変数として初期化できるようになりました。
immutable string[string] table = ["key": "value"]; // shared static this()で初期化したり、enumにしていた。
void main()
{
assert(table["key"] == "value"); // そのまま使えるようになった。
}
このコードでは、table
というグローバル変数を連想配列で初期化し、main
関数内でその値を検証しています。特に言うこともありませんが、こういった簡便な記述が可能になりました。
ただし、連想配列のキーまたは値の型に toHash
、opEquals
、または ~this
メソッドが定義されている場合、これらのメソッドはコンパイル時に呼び出すことが可能である必要があります。実行時のみにデストラクタが実行されるようにするために、if (!__ctfe)
という記述で分岐する必要があるかもしれません。今後のアップデートで、このような回避策が不要になる可能性もあります。
今回の強化によって、コードの記述がよりシンプルになり、開発プロセスもよりスムーズになると期待されます。引き続き便利に使ってきましょう。
_d_newarray{U,T,iT}
はテンプレートに変換されました。
こちら、D言語の配列生成における内部実装の話です。
配列生成に関わる _d_newarray{U,T,iT}
などの内部関数群が大きく改善されました。これらの関数は、配列のメモリー割り当てと初期化を担う重要な役割を果たしています。具体的には、以下の変更が行われました。
簡単なコード例ですが、配列 S[] s = new S[10]
の生成は、以下のように変更されます。
S[] s = _d_newarrayT!S(10);
新たなテンプレートは、core.internal.array.construction
に追加され、core.internal.array.utils
には__arrayClearPad
、__arrayAlloc
、__arrayStart
、__setArrayAllocLength
のテンプレートが実装されています。
内部的に色々な操作があるためこのような関数群が整備されているわけですが、今回の強化で配列の扱いがより柔軟で効率的になります。
この変更は随分前から取り組まれていたと思うのですが、今回正式に入りました。
長らく検討された機能が入ったという意味で、大きな前進を意味していると思います。
ランタイムの変更点
4つの core.memory.GC
関数が @safe
とマークされました。
特に言うこともないのですが、以下の4つの関数が @safe
で修飾されました。つまり、安全になりました。
GC.enable
GC.disable
GC.collect
GC.minimize
個人的に何でも1回は @safe:
と書いておきたいタイプきたい人としては非常に助かる気がします。
ライブラリ変更点
etc.c.odbc
の廃止が取り消され、非Windowsシステムで再度使用が可能になりました。
どれほどの方が使われているか存じないのですが、 etc.c.odbc
というライブラリの扱いに重要な方針変更がありました。
ODBC(Open Database Connectivity)とは?
ODBCは、様々なデータベースシステムへの接続を統一的な方法で提供するAPIの標準です。この標準により、異なるデータベース間でのデータのやり取りが容易になります。Windowsだけでなく、LinuxやmacOSなど、他の主要なプラットフォームでもサポートされています。
D言語の標準ライブラリには元々このためのモジュールが存在しており、ODBCサポートがあったわけです。
(通常、各DBに向けて最適化されたクライアントもまた提供されていたりするわけですが…)
etc.c.odbc
の廃止予定の取り消し
以前のdmdバージョンにおいて、etc.c.odbc
バインディングは廃止予定とされており、その機能は core.sys.windows.odbc
に委譲されていました。しかも、core.sys.windows.odbc
に含まれるバインディングは version(Windows)
指定がされており、非Windowsプラットフォームでの使用が困難でした。
この問題に対処するために、dmd 2.106.0では etc.c.odbc
のバインディングが廃止予定から外され、非Windowsプラットフォームでの使用が再び可能になりました。これはODBCが全主要プラットフォームでサポートされていることを考慮した変更であり、D言語の幅広い利用の証左であると言えるかと思います。
この変更により、D言語の開発者はWindows以外のプラットフォームでもetc.c.odbc
を利用してデータベースにアクセスすることが可能になります。このことは、D言語によるアプリケーションが異なるプラットフォームでも動作するようにコードベースの移植性を高めることにつながります。
isInputRange
はオプションの要素型を受け取るようになりました。
まず、isInputRange
がどのような関数かを理解しましょう。D言語において、isInputRange
は範囲(コレクションやシーケンスなど)が特定の条件を満たしているかをチェックするテンプレート関数です。この関数は、いわゆるレンジが反復可能であるかどうか(例えば、foreach
ループで使用できるかどうか)を判断するために使用されます。
今回の変更により、isInputRange
関数に新しいテンプレート引数が追加されました。このオプションの2番目のテンプレート引数によって、プログラマーは範囲の要素型を指定できるようになります。具体的には、この引数が void
でない場合、範囲の要素の型が追加された引数の型と同一である(constを除いて)場合にのみ、関数は true
を返します。
例えば、isInputRange!(int[], const(int))
の場合、 int
型の配列が const(int)
型と互換性があるためtrue
を返します。
しかし、isInputRange!(int[], string)
の場合は、int
型の配列と string
型は互換性がないため false
を返します。
static assert(isInputRange!(int[], const(int))); // 要素のintはconst(int)? => is(int : const(int))
static assert(isInputRange!(int[], string)); // 要素のintはstring? => !is(int : string)
この変更によって、コンパイル時により精密な型チェックを行うことができるようになります。これは、プログラムの安全性を高め、意図しない型のデータが範囲内で使用されるのを防ぐのに役立ちます。
例えば、数値の配列に対して文字列を操作しようとする場合、この新しい isInputRange
のチェックを用いると簡単に static assert
を使った検証が書けるため、謎の型不一致のエラーメッセージを回避したりできます。
この変更は、D言語が提供する強力な型システムをさらに有効活用する手段をプログラマーに提供します。今後の開発で親切なエラーメッセージを出したい場合など、積極的に活用していきたいですね。
std.traits
に Unshared
が追加されました。
今回追加されたUnshared
は、プログラマが共有状態(shared
)のデータをより柔軟に、かつ安全に扱えるようにするための機能強化です。
Unshared
は、std.traits
モジュールに新たに追加された機能で、型から外側のshared
修飾子を取り除くために使用されます。これにより、プログラマは共有データに対する操作をより細かく制御することが可能になります。
公式のサンプルが分かりやすいので引用します。
static assert(Unshared!(shared int) == int);
static assert(Unshared!(shared(int[])) == shared(int)[]);
この例は、Unshared
がどのように動作するかを示しています。
最初の例では、shared int
から shared
を取り除くと単なる int
になります。
次に、shared(int[])
(sharedがintの配列全体にかかっている)から、配列の各要素が共有される状態(shared(int)[]
)に変換されます。
要するに、表面的な shared
を1階層分だけ外す、という操作になっています。
なぜこの機能が追加されたのかと考えると、元々 shared
を外すには cast()sharedObj;
のような空のキャストを書く必要があってわかりづらい、という話があるためかと思います。(型レベルで操作する分には is
式を使ったりする方法もありますが)
今回追加された Unshared
ですが、既存の類似機能として Unconst
や Unqual
といったものがあります。
Unconst
は const
, immutable
, inout
を取り除き、Unqual
は型から全ての修飾子を取り除きます。
合わせて覚えておくとメタプログラミングが捗るかと思います。
DUB変更点
dub build
に --deep=
オプションが追加されました。
今回DUBの dub build
コマンドに新たに追加された --deep=
オプションは、スタティックライブラリ(staticLibrary)の依存関係にある全てのライブラリをビルドすることを可能にします。従来では、DUBの設定ファイルが存在するルートディレクトリにあるライブラリのみがビルドされるという挙動でしたが、この新オプションにより、一括でのビルド管理が可能となります。要するに、作業効率の向上に貢献する新機能です。
使用方法は難しくありません。フラグを付けるだけです。
このコマンドを実行すると、プロジェクトの依存する全てのスタティックライブラリがビルドされます。
dub build --deep
様々な依存関係を持つ静的ライブラリを作っている場合には、大変便利な機能になるかもしれません。
順番にビルドしている、結局ビルドスクリプトを書いている、といったケースがあれば解決するかもしれませんのでぜひ試してみてください。
dub describe
に default-config
、configs
、default-build
、builds
のデータが追加されました。
dub describe
コマンドにいくつかの新たな機能が追加され、パッケージの管理および情報提供が強化されました。
ただし、これはIDE向けの情報を提供する側面が強いコマンドなので、日ごろ使う人は多くないかもしれません。
今回の強化により、追加で取れるようになった情報が4つあります。
-
default-config
: これは文字列で、特に設定が指定されなかった場合にDUBが選択する--config
設定を表します。例えば、dub build
コマンドを単純に実行した場合にDUBがどの設定を選ぶかがこの値になります。 -
configs
: これは、利用可能なすべての設定のリストを含みます。このリストには、デフォルトで生成されるアプリケーションやライブラリ、またはレシピで手動で指定された設定が含まれます。 -
default-build
: これは文字列で、特にビルドタイプが指定されていない場合にDUBが選択する--build
のビルドタイプを表します。現時点では、この値は常に"debug"です。 -
builds
: これは、利用可能なすべてのビルドタイプのリストを含みます。内蔵されているビルドタイプに加えて、カスタムで定義されたビルドタイプもこのリストに含まれます。
これらの新機能は、開発者が必要とする情報をIDEにより多く伝えたりすることを目的としています。ぜひとも今後の開発環境の進歩に活用してもらいたいと思う次第です。
dub init
に、パッケージ形式とライセンスの選択メニューが追加されました。
DUBのdub init
コマンドが強化され、ライセンス選択などのプロンプトが出るようになりました。
百聞は一見に如かずなので、実行してみるか下記実行例をご確認ください。
パッケージ形式とライセンスの選択
-
dub init
コマンドがアップデートされ、新しいプロジェクトを始める際にパッケージ形式(sdlまたはjson)とライセンスを選択する新機能が追加されました。これは、プロジェクトの初期セットアップをより柔軟にし、開発者が自分のニーズに合ったプロジェクト構成を簡単に定義できるようにするためのものです。(あとデフォルトをそろそろSDLにしてほしい)
選択できるライセンス
選択できるライセンスには、BSD、MIT、GPL、Apache、Mozilla、Boostなど、オープンソースコミュニティで広く使用されているものが含まれます。また、プロプライエタリなライセンスを選択するオプションも用意されており、商用プロジェクトに対応しています。(商用プロジェクトがDで書かれた事例はいくつもあります!)
実行例
以下は、dub init
を実行した際の例です。
PS C:\work\articles\dmd-2.106.0> dub init
Select a package recipe format:
1) sdl 2) json
#? [2]: 1
Name [dmd-2.106.0]:
Error Invalid name 'dmd-2.106.0', names should consist only of lowercase alphanumeric characters, dashes ('-') and underscores ('_').
Name [dmd-2.106.0]: dmd2106
Description [A minimal D application.]:
Author name [lempiji]:
Select or enter an SPDX license-identifier (https://spdx.org/licenses/):
1) BSL-1.0 (Boost) 8) BSD-
2) MIT 9) MPL- (Mozilla)
3) Unlicense (public domain) 10) EUPL-
4) Apache- 11) CC- (Creative Commons)
5) AGPL- 12) Zlib
6) GPL- 13) ISC
7) LGPL- 14) proprietary
? [14]: 2
Success created empty project in C:\work\articles\dmd-2.106.0
Package successfully created in .
この例では、設定ファイルに sdl
形式を選択し、プロジェクト名を dmd2106
に設定し、MITライセンスを選択しました。(が、LICENSEファイルは作られません。残念。)
使えるプロジェクト名の文字チェックなども行われるので、変に打ち損じることが無くて良さそうです。
ともかく、これで今までよりも新しいプロジェクトが細かい設定をしながらも素早く初期化できるようになります。
どんどんライブラリやアプリを作っていきましょう!
DUBに --recipe=
スイッチが追加されました。
通常、DUBはプロジェクトのルートディレクトリにあるdub.sdl
またはdub.json
ファイルをビルド設定のレシピとして使用します。これらのファイルは、プロジェクトの依存関係、ビルドオプション、その他の設定を定義してありますが、新たに追加された--recipe=
スイッチを使うことで、これらのデフォルトファイルの代わりに別のファイルをビルド設定として指定することができるようになりました。
使用例
例えば、ローカル開発環境専用の特別なビルド設定を持つ複数の dub.json
ファイルがある場合、以下のようにして特定の設定ファイルを選択してビルドを実行できます。
dub build --recipe=custom-dub.json
この機能は、同じディレクトリ内にdub.sdl
とdub.json
の両方が存在する場合に、どちらを使用するか選択する際にも便利です。しかし、このような状況は、他のDUBをサポートするツールとの互換性や一般的なユーザーの混乱を招くため、推奨されません。将来的には、このスイッチが指定されていない限り、複数のファイルがあるとエラーとする可能性も検討されています。
メリットと将来の影響
--recipe=
スイッチの導入により、設定の管理がより柔軟になります。開発者はプロジェクトごとに異なるビルド設定を容易に切り替えることができ、特定の作業や環境に最適化された設定を用意することが可能になります。大きくなりすぎたファイルの分割などもまた推奨されるかもしれません。
しかし、この新機能の利用には注意も必要です。特に、プロジェクトディレクトリ内にdub.sdl
とdub.json
の両方を保持することの潜在的な混乱や、未来におけるエラーにつながる可能性に注意して、慎重に設定を管理していきましょう。
非推奨または廃止される機能
今回は、非推奨が1件、廃止が3件で計4件の機能が非推奨および廃止となります。
ただし1件動作が確認できないものがあり、これを除外すると廃止は2件です。
余り影響のないものが多いですが、一部わかりづらいものもありますので一つ一つ解説していきます。
また今後の予定などは以下のページにまとまっていますので、こちらも参考としてみてください。
非推奨
-
enum
ストレージクラスを持つ関数は、現在非推奨となりました。(エラーだったものが非推奨に戻されました)
削除/エラー
- グローバル
const
変数は、非shared static this
の静的コンストラクタからは初期化できなくなりました。 -
catch
節は、const
またはmutable
な例外のみを受け付けるようになりました。
未確認
- DIP1000による
scope class
インスタンスの生成時に、非スコープコンストラクタを使用することは@system
のみ可能になりました。
非推奨 : enum
ストレージクラスを持つ関数は、現在非推奨となりました。(エラーだったものが非推奨に戻されました)
The error was introduced in 2.105.0.
2.105.0でエラーとされていたものが、なんと非推奨に格上げ?されました。
誰か猛烈に困ったユーザーがいたのでしょうか。今まで前例がなかったと思われ、ちょっと謎です。
見かけたら対処しておくに越したことはないので、前回記事も参照してください。対処方法も含めて記載してあります。
https://qiita.com/lempiji/items/badaff4d08f544864488#%E5%89%8A%E9%99%A4%E3%82%A8%E3%83%A9%E3%83%BC--%E9%96%A2%E6%95%B0%E3%81%AF-enum-%E3%82%B9%E3%83%88%E3%83%AC%E3%83%BC%E3%82%B8%E3%82%AF%E3%83%A9%E3%82%B9%E3%81%AE%E6%8C%87%E5%AE%9A%E3%81%8C%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%8F%E3%81%AA%E3%82%8A%E3%81%BE%E3%81%97%E3%81%9F
削除/エラー : グローバル const
変数は、非 shared static this
の静的コンストラクタからは初期化できなくなりました。
バージョン2.106.0以前では、グローバルなconst
変数を非shared static this
の静的コンストラクタから初期化することが可能でした。しかし、この更新により、そのような初期化はできなくなりました。
仕組みについて少し補足すると、グローバル変数の const
や immutable
なデータは、いわゆるスレッドローカルストレージ(TLS)に配置されないため、スレッドごとに異なる値を持つことができません。(本当にグローバルな変数になる)
この特性により、スレッドごとに実行されるスレッドローカルな静的コンストラクタ(static this() {}
)内でこれらの変数を初期化しようとすると、const
や immutable
の意図に反する動作を引き起こす可能性があります。
以下のコードは、古いバージョンのdmdでは許可されていましたが、2.106.0では非推奨またはエラーとなります。
int x;
const int y;
immutable int z;
static this()
{
x = 1; // これは変わらず許可されます。
y = 2; // 非推奨: const変数を変更することはできません。
z = 3; // エラー: immutable変数を変更することはできません(以前から同様)。
}
エラー例
source\app.d(14,5): Deprecation: const variable `y` initialization is not allowed in `static this`
source\app.d(14,5): Use `shared static this` instead.
source\app.d(15,5): Error: immutable variable `z` initialization is not allowed in `static this`
source\app.d(15,5): Use `shared static this` instead.
この問題に対する解決策は、エラーメッセージにもある通り単なる static this
から初期化処理を共有(shared
)静的コンストラクタ(shared static this
)に移動することです。
const int y;
shared static this()
{
y = 4; // OK: グローバルなconst変数の初期化は共有静的コンストラクタから行うだけ
}
Use ... instead.
というメッセージをみかけたら、それに従っておくのが吉となります。
削除/エラー : catch
節は、const
または mutable
な例外のみを受け付けるようになりました。
以下のような catch
で例外に修飾されているケースがエラーとなりました。
auto e = new Exception("first");
try {
throw e;
} catch(immutable Exception ie) { // now an error
e.msg = "second";
assert(ie.msg == "first"); // would fail
}
これは元々2.104.0で非推奨とされていたものがエラーになっただけです。
詳細や対応は以下の記事でも言及していますので、こちら参照ください。
前回記事: https://qiita.com/lempiji/items/badaff4d08f544864488#%E9%9D%9E%E6%8E%A8%E5%A5%A8--catch-%E7%AF%80%E3%81%AFconst-%E3%81%BE%E3%81%9F%E3%81%AF-mutable-%E3%81%AA%E4%BE%8B%E5%A4%96%E3%81%AE%E3%81%BF%E3%82%92%E5%8F%96%E3%82%8B%E5%BF%85%E8%A6%81%E3%81%8C%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99
まとめ
DUBの強化、ライブラリ強化、コンパイラ強化、と結構目白押しでした。
ODBCの復活や1回エラーになった問題が非推奨として復活?するなどやや不思議な活動も見られますが、ユーザー利便性に配慮した決断だったのだろうと思います。
いくつか性能に寄与しそうな部分含め、コンパイラスイッチなどは大規模開発だと注目しどころかと思います。
DUBについてもinitが面白い画面になっているので1回見てみることをおすすめします。
そのままライブラリ開発に取り組んでまいりましょう。
さて、この記事もリリースからだいぶ遅れて書いていますが、既に次のリリースが出ている状況でもありますので次の記事も書き進めていきたいと思います。
引き続きよろしくお願いします!