10

Scala は、簡潔でスケーラブル (多くの機能がコンパイラーではなくライブラリーで指定されているため) であり、DSL をサポートしていると主張する興味深い言語です。これを実現するために、多くの演算子とコンパイラの微調整があります (たとえば、中置演算子をサポートするため、およびシーケンスを平坦化するための : _* など)。

多くの演算子 ('Programming in Scala' インデックスの 2.5 ページ) とコンパイラの微調整がわかりにくいと思います。公平を期すために、演算子の多くは、 C などから借用した従来の算術/ブール演算子です)。

これを支える基本的な構文規則がいくつかあると言われましたが、これらを知っていれば、私の認知負荷が軽減されると思います。

いくつかのルールがありますか (もしそうなら、それらは何ですか)、それともライブラリで多くの「演算子」メソッドと暗黙を学ぶ運命にあるのでしょうか?

4

3 に答える 3

7

演算子に関する質問を理解するには、次の 2 つの方法があります。

  1. Scala コンパイラによる演算子の処理方法を規定する規則は何ですか? (言語規則)
  2. ライブラリでの演算子の定義方法を管理するルールは何ですか? (演算子の定義)

言語規則

実はルールがあります。それらが「少ない」と思うかどうかは、あなたが判断してください。ほとんどの Scala と同様に、それらはLanguage Referenceのセクション 6.12 にあります。

最も重要なビット:

  • 受け入れられる前置演算子は+、、、およびのみ-です。!~

  • 引数を取らないメソッドは、後置演算子として使用できます。

  • 引数を 1 つ取るメソッドはすべて、中置演算子として使用できます。ただし、これらの演算の優先順位は特定の規則に従います。おそらく、ほとんどの場合、算術およびその他の式が期待どおりに処理されるようにするためです。優先順位は、演算子/メソッド名の最初の文字によって決定され、C または Java に期待されるものと一致します。

  • で終わるものを除いて、すべての中置演算子は左結合:です。典型的な例としては、::および があり+:ます。

つまり、基本的には 4 つのルールです。詳細については、仕様をお読みになることをお勧めします。

演算子の定義

演算子の定義の選択は、ライブラリの設計者次第です。たとえば、Scala コレクション ライブラリは、比較的小規模で一貫した一連の演算子 ( ++--**+=-=++=など) を--=使用します。+:パーサー・コンビネーターにはより風変わりなセットが付属しており、一部のライブラリーは、独自のオペレーター定義のために、最初は不敬な人には完全に理解できない場合があります (これは私の個人的な意見ですが、sbt や Lift が思い浮かびます)。

これは潜在的な問題の原因として認識されており、Scala スタイル ガイドではシンボリック メソッド名 (カスタム オペレーター) について次のように述べられています

避ける!Scala が API 設計のこの領域を容易にする程度にかかわらず、特にシンボル自体が非標準 (たとえば>>#>>) である場合は、シンボリック名を使用したメソッドの定義を軽々しく行うべきではありません。原則として、シンボリック メソッド名には 2 つの有効なユース ケースがあります。

  • ドメイン固有の言語 (例: actor1 ! Msg)
  • 論理的な数学演算 (例:a + bまたはc :: d)
于 2012-11-10T14:04:11.140 に答える
1

Scala には演算子に対する特別な扱いはありません

書籍「Programming in Scala 2ed」より抜粋

どのメソッドも演算子になることができます

Scala では、演算子は特別な言語構文ではありません。任意のメソッドを演算子にすることができます。メソッドを演算子にするのは、それをどのように使用するかです。「s.indexOf('o')」と書いた場合、indexOfは演算子ではありません。しかし、「 s indexOf 'o' 」と書くと、indexOf は演算子表記で使用しているため、演算子です。

あなたが参照している 2 1/2 ページがインデックスに見つかりません。

Scala 演算子は、何らかのオブジェクトで定義されたメソッドとして一貫して利用できます。これは、プリミティブ型に対する Java の特別なレガシー処理とは異なり、scala では任意の値がオブジェクトとして表されるという事実とも一致しています。

scala の基礎となる実装は、バイトコード レベルでパフォーマンスを向上させるためにプリミティブを利用できますが、これはエンド ユーザーに対して透過的です。

オペレーター

したがって、ここでのルールは単純です。すべての演算子は、実際には何らかの型で定義されたメソッドです。演算子中置記法は読みやすさの問題です。

val sum = 1 + 2

よりもはるかによく読みます

val sum = 1.+(2)

この表記法は、「自然な感じ」で DSL を構築するためのベースでもあります。テスト ライブラリScalaSpecsは、これを明確に示しています。

特別なコンパイラ規則

あなたが言ったように、より明確で理解しやすいコードを可能にするという前述の目的のために利用できる「コンパイラの微調整」の数は限られています。

これらの「微調整」の関連する概要は、ここにあります

于 2012-11-10T11:35:05.103 に答える
1

すべての情報は、stackoverflowおよびspecで入手できます。

どこから始めるべきかについての私の推奨事項は次のとおりです。

  1. 一連の識別子をオペランドと演算子に解析する方法を学びます。このトピックに関するの回答を参照してください。
  2. 演算子の優先順位リストを十分に覚えておいてください。個人的には、算術, , ,の文字の優先順位が最も低く、奇妙な Unicode の優先順位が最も高いことを覚えています。残りについては、括弧を追加するか、優先順位が DSL 設計者が意図したとおりに、または Java のように「うまくいく」と推測します。+-*/
  3. x :: xsリストのandxs ::: ys演算子は非常に普及しているため、右に関連付けるために学習してください:
  4. 必要に応じて、興味がある場合は、仕様のセクション6.12 Prefix、Infix、および Postfix Operationsをざっと見てください。これにより、演算子の持つ演算子=と前置演算子に関する詳細があることを脳の片隅で知ることができます。

最後に一言アドバイスを。すべての演算子を学ぼうとしないでください。言語を効果的に使用するためにすべての演算子の意味を知っている必要があると思い込まないでください。これは、完全な API を読んで覚えることによって他の言語を学習した場合を除きます。

于 2012-11-10T19:02:48.193 に答える