1. ホーム
  2. c++

[解決済み] Scalaの演算子オーバーロードが「良くて」、C++の演算子オーバーロードが「悪い」理由とは?[クローズド]

2022-04-27 07:01:01

質問

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"は単なるメソッドの一つです。