Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

target-typed #243

Closed
ufcpp opened this issue Apr 23, 2019 · 5 comments
Closed

target-typed #243

ufcpp opened this issue Apr 23, 2019 · 5 comments
Labels

Comments

@ufcpp
Copy link
Owner

ufcpp commented Apr 23, 2019

switch 式と条件演算子?:の target-typed 型推論が実装されそう。

ラムダ式とかも target-typed 型推論なんだけど、そういうのは「左辺からの型推論」って書き方してきてるんだけど、この言葉もしっくりこず。
今後、 target-typed new もあるはずだし。
あと、 default リテラルが target-typed。
string interpolation が string になるか FormattableString になるかも target-typed。

これまでの「左辺から」って言い方でまずいのが、
target type ⊃ { 左辺, メソッド呼び出しの引数 }
とかな関係で、不正確(一部分しかさせない)だから。

target-typed な機能がすでに docs にドキュメントのある範囲であるかどうか、
あるなら日本語訳もされてるかどうか、
されてればそれではどう書かれてるかとか調べる。

@ufcpp
Copy link
Owner Author

ufcpp commented Apr 29, 2019

https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/proposals/csharp-7.1/target-typed-default
default リテラルでページ自体はあった。
翻訳はまだだった。

@ufcpp
Copy link
Owner Author

ufcpp commented Apr 29, 2019

class Base { }
class A : Base { }
class B : Base { }

class Program
{
    static void Main()
    {
        Base[] x = { new A(), new B() }; // これは行ける(target-typed)
        var y = new Base[] { new A(), new B() }; // これも行ける
        Base[] z = new[] { new A(), new B() }; // これはダメ(提案は出てる)
    }
}

@ufcpp
Copy link
Owner Author

ufcpp commented May 6, 2019

target-typed new 自体は 9.0 行き。
とはいえ、target-typed switch expressions は 8.0 で入りそうな感じだったけど気配なし。

@ufcpp ufcpp added the C# 8.0 label Sep 8, 2019
@ufcpp
Copy link
Owner Author

ufcpp commented Nov 5, 2019

セクションは「その他」配下かな。
タイトルは「型の決定」みたいなのにして、以下の話題とまとめて扱う。

ページ名

ページ名で悩んでる。「型決定」辺りがいい気はしつつ、あんまりそういう呼び方はされておらず。
型決定にするなら determination?
C# 仕様書に「every variable has a type that determines what values can be stored 」って文章はある。

inference は意外と少ない C# 3.0 世代の機能にしか使われてないし、「var declaration」とかは多くあっても Inference って単語は意外とない。
仕様書上明示的に Type Inference ってタイトルが入ってる章はジェネリックメソッドの型引数決定くらいだったり。

resolution (解決)を使ってるのはメソッドオーバーロードくらい。
type inference と overload resolution が並んでる文章は見かけた。

たいていのもの、例えば null から任意の参照型とか、ラムダ式からデリゲートとかは「implicit conversion」のセクションに並んでる。
軽く roslyn 内を眺めてる感じ、 Target-Typed switch 式も内部的には IsImplicitConversion とかの中に並んでた。

「型推論」系で行くなら、すでに「型推論と匿名型」ってページがあったりするんだけど… これのリニューアルにする?
「基礎」に並んでるからちょっと時期尚早?

導入

例として以下のようながたがあったとして

class A { }
class B : A { }

推論のない書き方

両辺の型が一致

A x = new A();
  • A x のところで x の型が確定して、x は A である
  • new A() の型は A である
  • 両辺の型が一致しているのでコンパイルできる

暗黙の型変換

A x = new B();
  • A x のところで x の型が確定して、x は A である
  • new B() の型は B である
  • B から A への変換は認められているのでコンパイルできる

エラーになる例

A x = new object();
  • A x のところで x の型が確定して、x は A である
  • new object() の型は object である
  • object から A への変換は認められていないのでコンパイルできない

推論あり

暗黙的な型推論

よくある向き

var x = new A();
  • var x の型は初期化式から決定する
  • new A() の型は A である
  • x の型は A になる

逆向き(ターゲット型)

A x = default;
  • A x のところで x の型が確定して、x は A である
  • default の型はターゲット(この場合 A x)から決定する
  • default の型は A になる

ソース/ターゲット

var x = new A(); みたいな型決定の仕組みは昔から一般的なので名前ついてなくて
単に「暗黙的な型推論」っていうとこっちの向き。
しいて言うなら「ソース型からの(source-typed)型推論」

A x = default; みたいながた決定の仕組みは徐々に増え始めてて、
これのことを「ターゲット型からの(terget-typed)型推論」って呼ぶ。

= が典型例で、その場合 = の左右どちらにあるかで、
ソース型の方を「右辺」、ターゲット型の方を「左辺」って言ったりもする。
ただ、ソース・ターゲットは代入だけじゃなくてメソッド呼び出しの引数とかでもあって、その場合に「どっちが右でどっちが左かわからない」のでソース・ターゲットの方が。

ソース型から

  • 暗黙的型付け
    var, new[]

  • オーバーロード解決

    • 特にジェネリクス
static object M(object x) => x;
static T M<T>(T x) => x;

static void Main()
{
    var x = M(1);
}

ターゲット型から

  • target-typed
  • 整数リテラル
  • 文字列リテラル(formattable)
  • ラムダ式/メソッド グループのデリゲート化
  • default リテラル

整数

単純そうで案外複雑なのが整数リテラル。
1 って書いた場合、実はターゲット型から型を決定してる。
byte x = 1; みたいなの。
「byte リテラル」は C# にはないので。

文字列

特殊なリテラルのとこにリンク張って終わり?

ラムダ式

ラムダ式+オーバーロード解決の型決定は中身まで追う
static T N(Func f) => f();
static int X() => 1;
N(() => 1);
N(X); // これは確か C# 6 か 7 から

switch

このノリで、switch 式には target-typed な型決定が実装された

今後(C# 9.0 以降)の予定として

  • target-typed new
  • target-typed conditional expression

default が target-typed なんだから new

switch 式が target-typed なんだから条件演算子も

共通型

以下の場合、

  • 配列初期化の暗黙的型推論 new[] { a, b }
  • switchx switch { A => a, B => b }
  • 条件演算子 x ? a : b

ab の型が違う場合どう扱うべきか。
以下のような場合、型の決定が案外面倒。

  • b ? 1 : null
  • b ? 1.0 : (int?)null

target-typed で決定できる場合もある。
それでも決定できない場合、「1 と null の共通の型」(int? であるべき)を見つける作業が必要。

C# 8.0 時点ではそんなに賢くない。

x ? new Base() : new Derived() みたいなのの時に Base にはなる。
x ? new Derived1() : new Derived2() みたいなのの時にはエラー(Base にはできない)。

おまけ: 型変換じゃないけど

dotnet/csharplang#2926
target-typed で識別子検索も改善

@ufcpp
Copy link
Owner Author

ufcpp commented Dec 8, 2019

@ufcpp ufcpp closed this as completed Dec 8, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant