Togetter/min.tを安心してお使い頂くためのガイドラインを公開しました。
編集可能

ジェネリクスと演算子オーバーロードの話

興味深い話が流れていたのでまとめましたがAPI上限に達してしまったので皆さん好きに加筆してください。
2
conf@UEC @confused_uec

演算子オーバーロードってオブジェクト志向というよりはジェネリクスの話ではないのか

2016-06-09 11:44:40
なぎせ ゆうき @nagise

単にコード中で+演算したいんだい、で演算子オーバーロードを求められると視野が狭いと言わざるをえない

2016-06-09 11:58:29
なぎせ ゆうき @nagise

プリミティブ型 / オブジェクト型があって、プリミティブ型には言語組み込みの演算子による演算があって、プリミティブとオブジェクトで同一コードに落とし込みたくて、となればオブジェクトの演算子オーバーロードに寄せるしかなかろう、という気がする

2016-06-09 12:16:12
kobake⛅🧋 @kobake_

??? 単に文字列インスタンスの結合ごときにappendみたいな冗長な書き方したくないからコード中で+演算出来るようにしたい、ってのは視野が狭い? twitter.com/nagise/status/…

2016-06-09 12:16:15
kobake⛅🧋 @kobake_

演算子オーバーロードの真骨頂は、たとえばベクトルクラスなんかでも、a = (b + c) / 2 みたいな直感的に意味のわかる書き方ができる点だと思う

2016-06-09 12:19:07
なぎせ ゆうき @nagise

それを言ってしまうと、C#も結局のところプリミティブ型/オブジェクト型というハイブリッドになったのでジェネリクスのためには演算子オーバーロードするしかない。 プリミティブが第一級オブジェクトじゃない言語は基本的にそうなるのでは

2016-06-09 12:20:55
なぎせ ゆうき @nagise

でもまあC++があったとはいえ、C#のジェネリックも後付けだから、演算子オーバーロードがそれを見据えたものだったのかはよく分からないが

2016-06-09 12:21:35
なぎせ ゆうき @nagise

時代背景を考えれば、Java のジェネリクスも検討がされていた時期だから、初期リリースに実装が乗らなくても将来的に載せるつもりでいたのかもしれないな

2016-06-09 12:22:21
なぎせ ゆうき @nagise

プリミティブ型のジェネリクスやろうとしたら、演算子オーバーロードかボクシングかの2択なのでは

2016-06-09 12:24:09
なぎせ ゆうき @nagise

同じ演算ルールが適用できる型に同じ演算記法を与えて、テンプレートによって統一的に扱えることを視野に入れることと比較すれば狭いと言わざるを得ないではないですか。 twitter.com/kobake_/status…

2016-06-09 12:34:43
なぎせ ゆうき @nagise

省略記法が欲しいだけならマクロという手も。表現には制限がありますけども

2016-06-09 12:37:13
kobake⛅🧋 @kobake_

演算子オーバーロード自体をクラス内に定義するのではなくジェネリックな汎用定義にするであれば許容、というスタンス? twitter.com/nagise/status/…

2016-06-09 12:38:10
STB a.k.a. さとまる @stb_nissie

「演算子の抽象化と糖衣構文を同一視するな」ということか。 twitter.com/nagise/status/…

2016-06-09 12:41:09
kobake⛅🧋 @kobake_

こちらも参照いただけるとありがたいです。 twitter.com/kobake_/status… 僕は過度な冗長さを取り除きたいというスタンスです。 twitter.com/nagise/status/…

2016-06-09 12:42:32
ぐるぐる系SQL @bleis

@nagise ジェネリクスのために演算子オーバーロードするしかない、の意味がよくわかりません。

2016-06-09 12:48:36
なぎせ ゆうき @nagise

@bleis プリミティブなint型みたいなのがメソッド持てる言語なら、同じ名前のメソッドを用意してintとオブジェクトをジェネリックに扱うって出来ると思うんですよ

2016-06-09 13:16:27
ぐるぐる系SQL @bleis

@nagise んー、同じ名前のメソッドを用意するのと、ジェネリックに扱うことは何か関係があるんですか?例えばintはToStringを持っていますが、それはobjectから派生しているというだけで、ジェネリックとは無関係だと思うのですが。

2016-06-09 13:19:58
なぎせ ゆうき @nagise

@bleis 主張したいこと整理してたんですけど、結局のところ、プリミティブ型の操作がもっぱら演算子に依るからプリミティブ型と一緒くたに扱いたいシチュエーションが演算子オーバーロードを必要とするってことなのかなという気がしてきました

2016-06-09 13:52:04
なぎせ ゆうき @nagise

@kobake_ はい。演算子には、例えば+であれば概念的に「足し算」を表すのに用いるべし、という規範があると思うんですが、その規範によって統一的に足し算のコードが同じ形に落とし込まれるわけです。その同形型違いをまとめるとジェネリクスですよね

2016-06-09 13:54:23
Takashi Miyamoto @tmiya_

@nagise オーバーローディングをジェネリクスと言ったのでいろんな人に突っ込まれてるのだと思います。オーバーローディングなどはad-hoc polymorphismだし、ジェネリクスはparametric p...、それとは別にsubtypin p... と多態には区別が。

2016-06-09 14:02:03
なぎせ ゆうき @nagise

@tmiya_ そこの区別は当然ついていて、一般にJavaで演算子オーバーロードがないことに依るジェネリクス上の不都合が何かという論点を問うてます

2016-06-09 14:03:41
なぎせ ゆうき @nagise

@tmiya_ というか、演算子オーバーロードが引き合いに出されるシチュエーションとしてはC++のテンプレートが多いわけですが、そちらを念頭に置くとプリミティブ型の操作がもっぱら演算子に依るので演算できるオブジェクトを設計しないとテンプレートに落とし込めないだろうと

2016-06-09 14:05:18
なぎせ ゆうき @nagise

@tmiya_ Javaはボクシングでプリミティブ型のジェネリクスを実現しましたが、ラッパー型は演算できないので、必然的にJavaのジェネリクスではプリミティブの演算はできないという制限がつきます

2016-06-09 14:06:56
なぎせ ゆうき @nagise

@tmiya_ ボクシング方式ではプリミティブ型のような「演算できるオブジェクト」のようなものを独自に追加して扱うという点では機能性に欠ける、という話になるのかなあ。

2016-06-09 14:08:47
残りを読む(16)

コメント

ぼんぼ%アマンド・フォーマルハウト組 @tm_bonvo 2016年6月9日
言語毎に事情が違ってるもんを一緒くたにしてないですかねコレ。
0
[UNMAINTAINED]らりお@旧垢 @L16777216 2016年6月10日
std::ops::Add - Rust https://doc.rust-lang.org/std/ops/trait.Add.html Rustなんか、まさに「plusなどのメソッドひとつひとつを関数型インターフェースとして用意して、Numericにはそれら演算子を全部implements」って感じになってるし、良い感じがする
0