63

Scala には、単一引用符 ' で始まる名前で、一種の文字列定数であるシンボルがあります。

Ruby の記号 (コロンで始まる記号) を知っています。Ruby では、メンバー変数の getter と setter の生成 (たとえばattr_reader :name、 の getter の生成name) など、一部のメタプログラミング タスクに使用されます。

Scala コードでのシンボルの使用はまだあまり見たことがありません。Scala でのシンボルの実用的な用途は何ですか?

4

8 に答える 8

36

シンボルは本当に Scala に適合しますか?

Lisp のすばらしい世界では、コードは、それ自体 (文字列、数値など) を表すリテラル オブジェクトと、クラス、関数、変数などの識別子として使用されるシンボルのネストされたリストとして表されます。Lisp コードは非常に単純な構造を持っているため、Lisp ではプログラマーが (コンパイル時と実行時の両方で) それを操作できます。明らかに、これを行う場合、プログラマーは必然的にデータ オブジェクトとしてのシンボルに遭遇します。

どのような場合でも、シンボルは Lisp のオブジェクトです (また、そうである必要があります)。それで、シンボルをハッシュ テーブルのキーや列挙型としても使用しないのはなぜでしょうか? これは自然なやり方であり、特別な列挙型を定義する必要がないため、言語をシンプルに保ちます。

要約すると、シンボルはコード操作、列挙、およびキーイングに自然に使用されます。しかし、Java の人々は、デフォルトではハッシュ キー間の等価関係として ID を使用しないので (従来の Lisp はそうしています)、文字列をキーとして使用するだけです。列挙型は、Scala では個別に定義されます。最後に、データとしてのコードは、言語ではまったくサポートされていません。

いいえ、私の印象では、シンボルは Scala 言語に属していません。とは言っても、この質問への回答に注目していきたいと思います。それらは、私が今思いつくことのできない Scala でのシンボルの真の使い方をまだ示しているかもしれません。

(補遺: Lisp 方言によっては、Lisp シンボルも名前空間修飾されている場合があります。これはもちろん、コードを操作するときに非常に便利な機能であり、文字列にはない機能です。)

于 2009-08-25T08:12:47.957 に答える
19

Web を少し検索すると、文字列と比較した Scala (のような言語) のシンボル (シンボル リテラル) の意味はセマンティクスの問題であり、コンパイラの認識でさえあるようです。

「文字列」は一連の文字で構成されるデータ型です。文字列を操作して操作できます。文字列は意味的には、ファイル名から画面に出力されるメッセージ、CSV ファイルの行など、あらゆるテキスト データにすることができます。

コンパイラの場合、つまり IDE の場合、文字列はデータ型 String の値であり、数値 (数字のシーケンス) は Integer などのデータ型の値です。プログラムレベルでは、「foo」と「bar」に違いはありません。

OTOH シンボルは識別子です。つまり、プログラム内の項目を意味的に識別します。この点で、それらはクラス名、メソッド名、または属性名のようなものです。しかし、クラス名はクラス (つまり、クラスの構造と動作を宣言する一連のプロパティ) を識別し、メソッド名はメソッド (つまり、パラメーターとステートメント) を識別しますが、シンボル名はシンボル (つまり、それ自体) を識別します。 .

したがって、コンパイラーは、クラス Foo と Bar を区別するように、シンボル 'foo と 'bar を明示的に区別できます。コンパイラのシンボル テーブルの一部として、IDE で同じメカニズムを適用して、クラス Foo の使用法を検索するように、'foo の使用法 (つまり、このシンボルへの参照) を検索することができます。

比較すると、文字列「foo」を検索するには、全文スキャンなどの別のアプローチが必要になります。これは、プログラム コード内の 4711 のすべての出現を検索するのと同じセマンティクスに従います。

それが私がそれを理解する方法です、私が間違っていれば誰かが私を訂正するかもしれません.

于 2010-06-11T08:50:59.333 に答える
15

関数型言語がそれらを使用するので、Scalaがそれらを追加したと思います。

しかし、彼らは、シンボルを介して識別子を参照する機能を追加することを忘れていました。これは、彼らの存在の中心点の一種です。Scala 2.8には、その一部を提供する実験的な機能があります。APIドキュメントの関連部分を完全に引用します。


@experimental

object Invocation 
extends AnyRef

リフレクティブ呼び出しのより便利な構文。使用例:

    class Obj { private def foo(x: Int, y: String): Long = x + y.length }

次の2つの方法のいずれかを反映して呼び出すことができます。

    import scala.reflect.Invocation._
    (new Obj) o 'foo(5, "abc")                 // The 'o' method returns Any
    val x: Long = (new Obj) oo 'foo(5, "abc")  // The 'oo' method casts to expected type.

メソッドを呼び出してoo型推論に十分な助けを与えないと、おそらく推論Nothingされ、結果として。になりClassCastExceptionます。

著者ポールフィリップス

于 2009-08-25T22:59:10.443 に答える
15

Scala の本によると、シンボルはインターンされます。「同じシンボルを 2 回書くと、両方の式がまったく同じSymbolオブジェクトを参照します。

対照的に、Strings はリテラル形式で表示される場合にのみインターンされます (少なくとも Java ではインターンされますが、Scala については完全にはわかりません)。したがって、Stringコレクションに入れられる s のシリアル化を大量に行う場合は、代わりにシンボルを使用してメモリを節約できると思います。

しかし、私はスカフマンに同意します。私はそれらの使用について完全に確信しているわけではありません.

(Rubyでは、Symbolsは、あなたが与えたメタプログラミングの例とは別に、esのキーとしてよく使用されます.Rubyでは、 sがインターンされることはないHashため、これは便利です.everyは新しいメモリを割り当てます.Scalaでは、 Javaが同様にインターンされないように、多くの (デ) シリアライゼーションと組み合わせると、前述しました。)StringStringString

于 2009-08-24T20:29:24.027 に答える
5

シンボル間の比較はより高速だと思います。Erlang を使用したことがある場合、メッセージをやり取りするときにシンボルが大量に使用され、マシンの境界を越えてうまく機能する安価で高速なものが必要になります。Scala や IIRC でリモート アクターがどのような状態にあるのかはわかりませんが、どちらかというと怪しげでしたが、将来、それらが実装されれば、Erlang と同じようにシンボルが非常に役立つ可能性があります。また、ケース クラスについては、利点のいくつかは明らかではありませんが、シンボルは依然として安価です。

于 2009-08-24T23:48:00.430 に答える
3

コード内の既存の識別子ではないものの名前を参照したい場合に使用すると思います。Scala book は、データベース列の名前を参照する例を示しています。これは任意の文字列ではなく、実際には物の名前です。

それは少し希薄ですが、私は完全に確信していません。

于 2009-08-24T20:11:33.830 に答える
1

すでに述べたように、シンボルは他の (より多くの) 関数型言語から引き継がれます。他の人が言及していないことは、それらがシンボルの役割を果たすだけでなく、キーワードに最も近いものでもあるということです (おそらくパフォーマンス上の利点を差し引いたものです)。私の意見では、それらは明示的な識別子を意味するキーワードとしてより有用です。

以下に、キーワードとシンボルのClojure ドキュメントからの法廷の説明を含めます。

シンボル

シンボルは、通常、何かを参照するために使用される識別子です。関数パラメータ、let バインディング、クラス名、およびグローバル変数を参照するためにプログラム形式で使用できます。名前とオプションの名前空間があり、どちらも文字列です。シンボルにはメタデータを含めることができます (with-meta を参照)。

キーワード

キーワードは、それ自体に評価される記号識別子です。それらは非常に高速な等価テストを提供します。シンボルと同様に、名前とオプションの名前空間があり、どちらも文字列です。先頭の「:」は、名前空間または名前の一部ではありません。

一部の言語では、Scala シンボルはシンボルほど強力ではありません。したがって、それらもそれほど有用ではありません。しかし、キーワードと同じメタプログラミングとパフォーマンスの利点を提供できなかった理由がわかりません。少なくとも、コードを読みやすくすることができます。

于 2015-12-24T18:30:57.150 に答える