プログラミング言語理論において、フローに敏感な型付け(フロー型付けまたはオカレンス型付けとも呼ばれる) は、式の型が制御フロー内の位置によって決まる型システムです。
静的に型付けされた言語では、式の型は、それを構成するサブ式の型によって決まります。ただし、フロー依存の型付けでは、型の検証を行う操作の後に式の型が続く場合、式の型はより具体的な型に更新されることがあります。検証操作には、型述語、命令型更新、および制御フローが含まれます。
例
セイロン
この概念を説明する セイロンの次の例をご覧ください。
// Object? は、変数 "name" が Object 型であるか、そうでない場合は null
void であることを意味します。 hello ( Object ? name ) { if ( is String name ) { // このブロックでは、 "name" の型は String になりました。print ( "Hello, ``name``!" ); // 変数に対して String メソッドを呼び出すことができます。print ( " String.size is ``name.size``" ); } else if ( exists name ) { // このブロックでは、 "name" の型は Object になりました。 print ( "Hello, object ``name``!" ); } else { print ( "Hello, world!" ); } }
hello ( null );
hello ( 1 );
hello ( "John Doe" );
そして出力は次のようになります:
こんにちは世界! こんにちは、オブジェクト1です! こんにちは、ジョン・ドゥさん! 文字列のサイズは8です
コトリン
Kotlinのこの例を参照してください:
fun hello ( obj : Any ) { // `obj` が文字列でない場合、型キャストは失敗しますobj as String
// 型キャストが失敗していないので、`obj` は文字列である必要があります
。val l = obj . length
println ( "' $ obj ' は長さ$ lの文字列です" ) } hello ( "Mooooo" )
利点
この手法を型推論と組み合わせると、ダックタイピングを使用する動的言語で見られるように、すべての変数に型注釈を記述したり、型キャストを行う必要性が減ります。冗長性が軽減され、コードが簡潔になり、読みやすく、変更しやすくなります。
また、オブジェクトの型を静的に予測することで、言語実装者が動的言語をより高速に実行する実装を提供するのにも役立ちます。[1]
最後に、型の安全性が向上し、ヌル参照の発明者であるCAR Hoareが「10億ドルの間違い」と名付けたヌルポインタによる問題を防ぐことができます[どのように? ] [2]
プログラミング言語の観点から見ると、フローセンシティブな型付けは、ユニオン型を持ち、過度な動的チェックを行わずに、使用可能な型安全なプログラミング言語の構築を最終的に可能にした機能であると言っても過言ではありません。この時点まで、Scheme などの言語にこの機能を追加しようとすると、通常、手に負えないほど大きな型表現が生まれていました。ユニオン型のサポートが限定されているシステムの 1 つの例として、Wright と Cartwright の「Soft Scheme」があります。[3]
実装
Schemeの型システムである Typed Scheme は、この機能を備えた最初の型システムでした。[4]その後継である Typed Racket ( Racketの方言) も、オカレンス型付けに基づいています。[5] Typed Scheme の直後、David J. Pearce はWhileyでフロー型付けを独自に再発明しました。[6] [7]
Typed JavaScriptは、「スクリプト」言語では、フロータイピングは条件述語だけでなく、状態と制御フローにも依存することを観察しました。[8]このスタイルはその後、 Ceylon、[9] TypeScript [10] Facebook Flowなどの言語に採用されました。[11]
また、ユニオン型はないが、 null許容型を持つ言語もいくつかあり、 C#、[12] 、 Kotlin、[13]、[14]、Lobsterなど、この機能の限定された形式はnull許容型にのみ適用されます。[15]
代替案
パターン マッチングは、フロー センシティブな型付けと同じ目的、つまり冗長性を減らして簡潔なコードを実現し、読みやすく変更しやすくします。これは別の方法で実現され、構造体の型を一致させ、同時に新しい変数を宣言してそこからデータを抽出できます。そのため、型キャストと値の抽出に関する形式が軽減されます。パターン マッチングは、すべてのケースを列挙してコンパイラで静的にチェックできるため、 代数データ型と組み合わせて使用すると最も効果的です。
Javaのモックの例を参照してください: [16]
int eval ( Node n ) { return switch ( n ) { // "Node" を "IntNode" に型キャストして、型 "int" の変数 "i" を作成します。// これが機能する場合は、"i" の値を返します。case IntNode ( int i ) -> i ; // "Node" を "NegNode" に型キャストして、型 "Node" の変数 "n" を作成します。// これが機能する場合は、"n" ノードの評価の否定を返します。 case NegNode ( Node n ) -> - eval ( n ); // "Node" を "AddNode" に型キャストして、型 "Node" の変数 "left" と "right" を作成します。// これが機能する場合は、"left" ノードと "right" ノードの評価の加算を返します。case AddNode ( Node left , Node right ) -> eval ( left ) + eval ( right ); // 「Node」を「MulNode」に型変換し、「Node」型の変数「left」と「right」を作成します。// それが機能する場合は、「left」ノードと「right」ノードを評価する乗算を返しますcase MulNode ( Node left , Node right ) -> eval ( left ) * eval ( right ); // コンパイラはすべての可能なケースが列挙されていることを認識しているため、「default」はありません}; }
静的に型付けされた言語では、フローに敏感な型付けに対するパターン マッチングの利点は、変数の型が常に同じままであることです。つまり、制御フローに応じて変化しません。一致させるパターンを記述すると、新しい型を持つ新しい変数が宣言されます。
参考文献
- ^ Lukas Eder (2014 年 12 月 11 日). 「動的型付けと静的型付けに関する不都合な真実」. blog.jooq.org . 2016 年3 月 11 日閲覧。
- ^ Tony Hoare (2009-08-25). 「Null 参照: 10 億ドルのミス」. InfoQ.com.
私はこれを 10 億ドルのミスと呼んでいます。それは 1965 年の Null 参照の発明でした。当時、私はオブジェクト指向言語 (
ALGOL W
) における参照の最初の包括的な型システムを設計していました。私の目標は、すべての参照の使用が絶対に安全で、チェックはコンパイラによって自動的に実行されるようにすることでした。しかし、実装が非常に簡単であるという理由だけで、Null 参照を入れたいという誘惑に抗うことができませんでした。これにより、無数のエラー、脆弱性、システム クラッシュが発生し、過去 40 年間でおそらく 10 億ドルの苦痛と損害が発生しました。
- ^ Wright, Andrew; Cartwright, Robert (1997 年 1 月 1 日). 「Scheme の実用的なソフト型システム」. ACM Transactions on Programming Languages and Systems . 19 (1): 87--152. doi :10.1145/239912.239917 . 2024 年 5 月 4 日閲覧。
- ^ 「Typed Scheme の設計と実装 | POPL、2008」。dl.acm.org。
- ^ 「5 出現タイピング」。docs.racket-lang.org。
- ^ David J. Pearce (2010年9月22日). 「WhileyにおけるFlow-Sensitive型について」 whiley.org. 2016年3月11日時点のオリジナルよりアーカイブ。 2016年3月11日閲覧。
- ^ David J. Pearce (2012年4月8日). 「Whiley - Flow Typing」. whiley.org. 2016年3月11日時点のオリジナルよりアーカイブ。 2016年3月11日閲覧。
- ^ 「フロー分析を使用したローカル制御と状態のタイピング」。2016年11 月 14 日閲覧。
- ^ 「Ceylon - クイック紹介 - 型安全な null とフローセンシティブな型付け」。ceylon-lang.org。2016年3 月 11 日閲覧。
- ^ Ryan Cavanaugh (2014 年 11 月 18 日)。「TypeScript 1.4 のプレビュー: 共用体型、型ガードなど」。blogs.msdn.microsoft.com。2016年3 月 11 日閲覧。
- ^ Avik Chaudhuri、Basil Hosmer、Gabriel Levi (2014 年 11 月 18 日)。「Flow、JavaScript 用の新しい静的型チェッカー」。code.facebook.com。2016年3 月 11 日閲覧。
- ^ 「null 許容参照型を使用した設計」。docs.microsoft.com。
- ^ 「Null Safety」. kotlinlang.org . 2016年3月11日閲覧。
- ^ 「型チェックとキャスト」 kotlinlang.org . 2016年3月11日閲覧。
- ^ 「ロブスター型システム」aardappel.github.io。
- ^ Gavin Bierman と Brian Goetz (2023 年 9 月 19 日)。「JEP 441: switch のパターン マッチング」。openjdk.org。2023年11月 14 日閲覧。
