web-dev-qa-db-ja.com

Clojureに「シンボル」に加えて「キーワード」があるのはなぜですか?

私は、他のLisp(特にScheme)についての深い知識を持っています。最近、私は Clojure について読んでいます。 「シンボル」と「キーワード」の両方があることがわかります。私がよく知っているシンボルですが、キーワードはよくありません。

他のLispにはキーワードがありますか?キーワードは、異なる表記法(つまり、コロン)以外の記号とどのように異なりますか?

124

キーワードとシンボルの Clojureドキュメント を次に示します。

キーワードは、それ自体に評価されるシンボリック識別子です。彼らは非常に高速な同等性テストを提供します...

シンボルは通常、他の何かを参照するために使用される識別子です。これらは、プログラムのフォームで使用して、関数パラメーターを参照したり、バインディング、クラス名、グローバル変数を使用したりできます...

キーワードは通常、軽量の「定数文字列」として使用されます。ハッシュマップのキーまたはマルチメソッドのディスパッチ値。通常、シンボルは変数や関数に名前を付けるために使用され、マクロなどを除き、それらをオブジェクトとして直接操作することはあまり一般的ではありません。ただし、キーワードを使用するすべての場所でシンボルを使用することを妨げるものは何もありません(常に引用することを気にしない場合)。

違いを確認する最も簡単な方法は、Keyword.JavaおよびSymbol.JavaはClojureソースにあります。いくつかの明らかな実装の違いがあります。たとえば、Clojureのシンボルにはメタデータを含めることができ、キーワードにはできません。

シングルコロン構文に加えて、ダブルコロンを使用して名前空間で修飾されたキーワードを作成できます。

user> :foo
:foo
user> ::foo
:user/foo

Common LISPにはキーワードがあります。doRubyおよびその他の言語。もちろんこれらの言語ではわずかに異なります。CommonLISPキーワードとClojureキーワードの違いは次のとおりです。

  1. Clojureのキーワードはシンボルではありません。

    user> (symbol? :foo)  
    false
    
  2. キーワードは、特に限定しない限り、どのネームスペースにも属しません。

    user> (namespace :foo)
    nil
    user> (namespace ::foo)
    "user"
    

(ありがとう Rainer Joswig 見るもののアイデアをくれてありがとう。)

131
Brian Carper

Common LISPにはキーワードシンボルがあります。

キーワードも記号です。

(symbolp ':foo) -> T

キーワードが特別な理由:

  • :fooは、Common LISPリーダーによってシンボルキーワードとして解析されます:: foo
  • キーワードは自分自身に評価されます::foo->:foo
  • キーワードシンボルのホームパッケージはKEYWORDパッケージです:keyword:foo->:foo
  • キーワードはパッケージKEYWORDからエクスポートされます
  • キーワードは定数であり、異なる値を割り当てることはできません

それ以外の場合、キーワードは通常のシンボルです。そのため、キーワードは関数に名前を付けたり、プロパティリストを持つことができます。

注意:一般的なLISPのシンボルはパッケージに属します。これは次のように記述できます。

  • foo、現在のパッケージでシンボルにアクセスできる場合
  • foo:bar、シンボルFOOがパッケージBARからエクスポートされるとき
  • foo :: bar、シンボルFOOがパッケージBARにある場合

キーワードシンボルの場合、:foo、keyword:fooおよびkeyword :: fooはすべて同じシンボルであることを意味します。したがって、通常、後者の2つの表記は使用されません。

したがって、シンボル名の前にパッケージ名を指定しないと、デフォルトでKEYWORDパッケージを意味すると仮定して、:fooはパッケージKEYWORDにあると解析されます。

29
Rainer Joswig

キーワードはそれ自体に評価されるシンボルであるため、それらを引用するのを忘れる必要はありません。

6
Greg Hewgill

:keywordsも多くのコレクションで特別に扱われ、本当に便利な構文を可能にします。

(:user-id (get-users-map))

と同じです

((get-users-map) :user-id)

これは物事をもう少し柔軟にします

4
Arthur Ulfeldt

キーワードの場合、ハッシュ値が計算され、キーワードが最初に構築されたときにキャッシュされます。キーワードをハッシュキーとして検索する場合、単純に事前計算されたハッシュ値を返します。文字列とシンボルの場合、ハッシュはルックアップごとに再計算されます。

同じ名前のキーワードが常に同一である理由には、独自のハッシュ値が含まれています。マップおよびセットの検索はハッシュキーから作成されるため、検索自体ではなく、多数の検索の場合の検索効率が向上します。

4
Ivan Pierre