[解決済み] Scalaの演算子オーバーロードが「良くて」、C++の演算子オーバーロードが「悪い」理由とは?[クローズド]
質問
C++における演算子のオーバーロードは、多くの人がA Bad Thing(tm)であり、新しい言語では繰り返されてはならない間違いだと考えています。確かに、Javaを設計する際に特に削除された機能の1つです。
今、Scala を読み始めたところ、Scala には演算子のオーバーロードによく似たものがあることがわかった(厳密には演算子を持たず、関数だけなので演算子のオーバーロードはないのだけれども)。しかし、C++の演算子オーバーロードとは質的に違うようだ。私の記憶では、演算子は特殊な関数として定義されている。
そこで質問ですが、Scala で "+" を定義するアイデアは、C++ で定義したアイデアよりも優れていると言えるのでしょうか?
どのように解決するのですか?
C++はCからtrue blue演算子を継承しています。つまり、6 + 4の"+"は非常に特殊だということです。 例えば、その+関数へのポインタを取得することはできません。
一方、Scalaにはそのような演算子はありません。 メソッド名の定義が非常に柔軟で、さらに単語以外のシンボルにはちょっとした優先順位が組み込まれているだけです。 だから技術的には、Scalaには演算子のオーバーロードはないんだ。
どう呼ぼうと、演算子のオーバーロードは、C++でも本質的には悪いものではありません。 問題は、悪いプログラマーがそれを乱用した場合だ。 しかし、率直に言って、プログラマーが演算子オーバーロードを悪用する能力を奪うことは、プログラマーが悪用しうるすべてのものを修正するためのバケツには一滴も入らないというのが私の意見だ。 本当の答えは、メンタリングなのです。 http://james-iry.blogspot.com/2009/03/operator-overloading-ad-absurdum.html
しかし、C++の演算子オーバーローディングとScalaの柔軟なメソッド命名には違いがあり、Scalaはより悪用されにくく、より悪用されやすいと思います。
C++では、インフィクス表記を得るには演算子を使うしかありません。 それ以外の場合は、object.message(argument)やpointer->message(argument)、function(argument1, argument2)を使う必要があります。 ですから、もしあなたのコードにある種のDSL的なスタイルを求めるなら、演算子を使わざるを得ないのです。
Scalaでは、どんなメッセージ送信でもinfix記法が使えます。 "オブジェクトメッセージ引数"は完全にOKで、infix記法を得るためだけに単語以外の記号を使う必要はないってことです。
C++の演算子オーバーロードは、基本的にCの演算子に限定されています。 演算子のみがinfixで使用できるという制限とあいまって、無関係な広範囲の概念を"+"や">"といった比較的少数のシンボルにマッピングしようとする人々にプレッシャーを与えているのです。
Scalaでは、メソッド名として有効な非単語記号の範囲が非常に広いのです。 例えば、私はProlog的なDSLを組み込んでいて、以下のように書くことができます。
female('jane)! // jane is female
parent('jane,'john)! // jane is john's parent
parent('jane, 'wendy)! // jane is wendy's parent
mother('Mother, 'Child) :- parent('Mother, 'Child) & female('Mother) //'// a mother of a child is the child's parent and is female
mother('X, 'john)? // find john's mother
mother('jane, 'X)? // find's all of jane's children
シンボル:-、!、?、&は通常のメソッドとして定義されています。 C++では&のみ有効なので、このDSLをC++にマッピングしようとすると、すでに非常に異なる概念を想起させるいくつかのシンボルが必要になります。
もちろん、これはScalaが別の種類の悪用にさらされる可能性もあります。 Scalaでは、メソッドに$!&^%という名前を付けようと思えば付けられるのです。
Scalaのように、言葉以外の関数やメソッドの名前を柔軟に使える他の言語については、Smalltalkを参照してください。Smalltalkでは、Scalaのように、すべての"operator"は単なるメソッドの一つです。
関連
-
[解決済み】クラステンプレートの引数リストがない
-
[解決済み】関数名の前に期待されるイニシャライザー
-
[解決済み】クラステンプレートの使用にはテンプレート引数リストが必要です
-
[解決済み】エラー:free(): 次のサイズが無効です(fast)。
-
[解決済み] Scalaのcase classとclassの違いは何ですか?
-
[解決済み] なぜJavaには演算子のオーバーローディングがないのですか?
-
[解決済み】C/C++の"-->"演算子とは何ですか?
-
[解決済み】Scalaの記号演算子にはどんな意味があるの?
-
[解決済み】Scalaのyieldとは何ですか?
-
[解決済み] Javaにおける演算子のオーバーローディング
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] テスト
-
[解決済み】C++ 式はポインタからオブジェクトへの型を持っている必要があります。
-
[解決済み】関数名の前に期待されるイニシャライザー
-
[解決済み】c++でstd::vectorを返すための効率的な方法
-
[解決済み】Visual Studio 2013および2015でC++コンパイラーエラーC2280「削除された関数を参照しようとした」が発生する
-
[解決済み] 式はクラス型を持つ必要があります。
-
[解決済み】クラステンプレートの使用にはテンプレート引数リストが必要です
-
[解決済み] 非静的データメンバの無効な使用
-
[解決済み】CMakeエラー at CMakeLists.txt:30 (project)。CMAKE_C_COMPILER が見つかりませんでした。
-
[解決済み】VC++の致命的なエラーLNK1168:書き込みのためにfilename.exeを開くことができません。