Java7 のダイアモンドオペレータと型推論について。

『Java7 ジェネリクスのダイアモンド・オペレータ』プログラマーの脳みそ(http://d.hatena.ne.jp/Nagise/20110729/1311950039) で解説されている内容から派生した、Java のジェネリクスや型推論まわりの話など。 ・・・話のレヴェル高いお(´Д` )
15
なぎせ ゆうき @nagise

@kmizu そうですね。疑問点としてダイアモンドの推論が観測できないこと。それと「非実用的な話」で挙げたいくつかの例が僕の中では釈然としないわけです http://t.co/f2FoRa0

2011-08-01 00:41:39
なぎせ ゆうき @nagise

@kmizu バイトコードには痕跡が残らないので、コンパイルの過程で何か推論が確かに行われていることが確認できる例が欲しいわけです。僕は今の所みつけれてなくて、単にraw型でコンパイルしてるだけじゃないの説に至っているわけですが

2011-08-01 00:43:11
なぎせ ゆうき @nagise

List<String> list = new ArrayList<>().subList(0, 0); のような例はコンパイルできない。この時、コンパイルエラーは期待値:List<String>検出値:List<Object>と出てくる

2011-08-01 00:46:57
kmizu @kmizu

@nagise 推論が行われているかどうか確認できそうな例はちょっと考えて見ます。ただ、状況証拠的に、「raw型でコンパイルしてるだけ」なら、引数で使用できない、とか変な制約があるのは不自然ですよね。概ね、制約条件が、型パラメータの推論の場合とほぼ同じなので、

2011-08-01 00:48:24
kmizu @kmizu

@nagise 自分は、diamond operatorはほとんどシンタックスシュガーのようなものであって、内部的には型パラメータ推論器に処理をそのまま渡してるだけなんじゃないかと思っています。

2011-08-01 00:49:24
なぎせ ゆうき @nagise

@kmizu そうですね。メソッド呼び出しなどもraw型で矛盾は起きないと思うのですけど、これはできないことになっている。何の不都合があるのか、疑問ですね。

2011-08-01 00:49:46
なぎせ ゆうき @nagise

@kmizu とすれば、メソッドスコープの型変数の型推論の挙動を元に何らかの形で同等の挙動を引き出せるかもしれませんね

2011-08-01 00:50:49

■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

Kazunori Otani @katzchang

<>オペレータは型推論じゃないだろー。

2011-08-01 00:52:07
なぎせ ゆうき @nagise

.@katzchang 仕様上は型推論と書かれてるけど、本当かいなというのを何で確かめるかが難しい…

2011-08-01 00:53:30
Kazunori Otani @katzchang

@nagise マジですか…。あれは単に、newするオブジェクトを変数に結びつける場面での簡易な記法、としか思えなかった。メソッドパラメータで直接宣言できないのに型推論とかおかしい。

2011-08-01 00:59:52

■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

なぎせ ゆうき @nagise

List<String> list;(list = new ArrayList<>()).subList(0, 0);ならコンパイルできる。代入演算では推論できるけどメソッド呼び出しの結果の代入までは波及しないということ

2011-08-01 00:52:18
Suguru ARAKAWA @ashigeru

@nagise "List<String> list = new ArrayList<>(Arrays.asList(1));"

2011-08-01 00:52:55
なぎせ ゆうき @nagise

@ashigeru 面白い例ですね。期待値: List<String>検出値: ArrayList<Integer>ってなりますね。これは引数の推論がダイアモンドに勝ってるという例でしょうか

2011-08-01 00:56:41
Suguru ARAKAWA @ashigeru

@nagise Arrays.asList()のようにメソッドに型引数を指定できる場合もそうですが、引数から型推論できない場合に、代入対象の変数から逆向きの推論を行う仕組みがJava1.5からあります(メソッド起動ではしない)。たぶん従来の型推論と同じ仕組みだと思います。

2011-08-01 00:59:22
なぎせ ゆうき @nagise

.@ashigeru 確かに、戻り値の型で推論は行われましたが…。ダイアモンドで同じロジックを通しているか、通していないのかの証拠が欲しいんですよね。同じようなものがあって流用しているだろうというのは推測ですからね

2011-08-01 01:03:31
なぎせ ゆうき @nagise

疑問点をまとめるのも難しいな…

2011-08-01 01:04:33
なぎせ ゆうき @nagise

<T> T hoge(){return null;} としてString s = true ? hoge() : hoge();としたときの挙動がList<String> l2 = b ? new ArrayList<>() : new LinkedList<>();と同じっぽい

2011-08-01 01:06:41
なぎせ ゆうき @nagise

んー。この挙動は推論器流用説に有利なポイントだな

2011-08-01 01:07:56
Suguru ARAKAWA @ashigeru

@nagise 実装の話ですので推定ですが、私がやるならnew ArrayList<T>()のように一時的に未解決の型変数を置いて、まずコンストラクタ引数について解析します。Tに推論上の制約がなければ、List<String> :> ArrayList<T> の制約で推論します

2011-08-01 01:09:28
なぎせ ゆうき @nagise

<T> T hoge(){return null;} と void hoge2(String s){} としたときのhoge(hoge2());の挙動もダイアモンドと同じでNGっぽい

2011-08-01 01:09:52
なぎせ ゆうき @nagise

.@ashigeru ただ、そこがそもそも推論する必要ないんじゃないかという疑問があるんですよね。整合性が取れないケースがあるのかなあ…

2011-08-01 01:11:14
Suguru ARAKAWA @ashigeru

@nagise 上限境界とか指定する場合まで考慮したら、推論したほうが楽そうな気がしますけど。

2011-08-01 01:12:41
なぎせ ゆうき @nagise

メソッドスコープの型変数を戻り値にもつ<T> T hoge()みたいなメソッドが型推論できて書ける箇所ってのと、ダイアモンド演算子が書ける箇所ってのが一致するような感触を得ている

2011-08-01 01:12:43