web-dev-qa-db-ja.com

LISP /スキームのシンボルとは正確には何ですか?

全能者の愛のために、私はシンボルの目的をまだ理解していません'iamasymbol。数値、ブール値、文字列...変数を理解しています。しかし、シンボルは私の小さな命令的思考の心を取るには多すぎます。正確に何に使うのですか?それらはプログラムでどのように使用されることになっていますか?この概念の私の理解は失敗です。

39
dotnetN00b

SchemeとRacketでは、シンボルは、シンボルが_eq?_と比較できるようにインターンされた不変の文字列のようなものです(高速で、基本的にはポインタの比較)。シンボルと文字列は別々のデータ型です。

シンボルの用途の1つは、軽量の列挙です。たとえば、方向は_'north_、_'south_、_'east_、または_'west_のいずれかであると言えます。もちろん、同じ目的で文字列を使用することもできますが、少し効率が悪くなります。数字を使うのは悪い考えです。可能な限り明確かつ透明な方法で情報を表現します。

別の例として、SXMLは、リスト、シンボル、および文字列を使用したXMLの表現です。特に、文字列は文字データを表し、記号は要素名を表します。したがって、XML _<em>hello world</em>_は値_(list 'em "hello world")_で表され、よりコンパクトに記述できる'(em "hello world")になります。

記号の別の用途はキーとしてです。たとえば、メソッドテーブルを、シンボルを実装関数にマッピングする辞書として実装できます。メソッドを呼び出すには、メソッド名に対応するシンボルを検索します。 LISP/Scheme/Racketはreallyを簡単にします。言語には、識別子(言語の構文の一部)と記号(言語の値)の間の組み込みの対応があるためです。その対応により、ユーザー定義の構文拡張機能を言語に実装するmacrosのサポートが容易になります。たとえば、「メソッド名」(クラスシステムによって定義された構文上の概念)とシンボルの間の暗黙的な対応を使用して、クラスシステムをマクロライブラリとして実装できます。

_(send obj meth arg1 arg2)
=>
(apply (lookup-method obj 'meth) obj (list arg1 arg2))
_

(他のLispでは、私が言ったことはほとんどが大げさですが、パッケージや関数と可変スロット、IIRCなど、知っておくべきことが他にもあります。)

28
Ryan Culpepper

シンボルは、単純な文字列表現を持つオブジェクトであり、(デフォルトで)internedであることが保証されています。つまり、同じように書かれた2つのシンボルはメモリ内の同じオブジェクト(参照の等価性)です。

Lispにシンボルがあるのはなぜですか?まあ、それは主にLispが言語のデータ型として独自の構文を埋め込んでいるという事実のアーチファクトです。コンパイラーとインタープリターはシンボルを使用してプログラム内のIDを表します。 LISPではプログラムの構文をデータとして表現できるため、シンボルは表現の一部であるため、シンボルを提供します。

それ以外に何が役に立つのですか?まあ、いくつかのこと:

  • LISPは一般に、埋め込みドメイン固有の言語を実装するために使用されます。そのために使用されるテクニックの多くはコンパイラの世界から来ているので、シンボルはここでは便利なツールです。
  • Common LISPのマクロは通常、この回答が提供するよりも詳細にシンボルを処理する必要があります。 (特に、マクロ展開用の一意の識別子を生成するには、他のシンボルと決して等しくないことが保証されているシンボルを生成できる必要があります。)
  • シンボルは参照の等価性によって比較できるため、固定列挙型は文字列よりもシンボルとして実装するほうが適切です。
  • シンボルと参照の等価性を使用することでパフォーマンスの利点を得ることができる多くのデータ構造を構築できます。
31
Luis Casillas

LISPのシンボルは、人間が読める識別子です。それらはすべてシングルトンです。そのため、コードのどこかに 'fooを宣言してから、' fooを再び使用すると、メモリ内の同じ場所を指します。

使用例:異なるシンボルは、チェス盤上の異なる部分を表すことができます。

7

シンボルは、単なる値の特別な名前です。値はどのようなものでもかまいませんが、記号は毎回同じ値を参照するために使用され、この種のものは高速比較に使用されます。あなたが命令的思考であるとあなたが言うように、それらはCの数値定数のようなものであり、これはそれらが通常実装される方法です(内部に保存された数値)。

5
Tom

Harold AbelsonおよびGerald Jay Sussman 1996によるStructure and Interpretation of Computer Programs Second Editionから:

シンボルを操作するには、言語に新しい要素、つまりデータオブジェクトを引用する機能が必要です。リスト(a b)を作成するとします。これは(リストa b)では実現できません。この式は、シンボル自体ではなく、aとbの値のリストを作成するためです。この問題は、自然言語のコンテキストではよく知られています。自然言語では、単語や文は、意味的エンティティまたは文字列(構文エンティティ)と見なされます。自然言語の一般的な慣習では、引用符を使用して、単語または文を文字列として文字列として処理することを示します。たとえば、「ジョン」の最初の文字は明らかに「J」です。 「あなたの名前を声に出して」誰かに言うと、その人の名前を聞くことが期待されます。しかし、誰かに「あなたの名前を声に出して言って」と言うと、「あなたの名前」という言葉が聞こえるはずです。他の誰かが言うかもしれないことを説明するために引用符をネストすることを余儀なくされていることに注意してください。 これと同じ方法に従って、評価される式ではなくデータオブジェクトとして扱われるリストとシンボルを識別できます。ただし、引用の形式は、配置する自然言語の形式とは異なります。引用するオブジェクトの先頭のみにある引用符(通常、単一引用符 ')。オブジェクトを区切るために空白と括弧に依存しているため、Scheme構文でこれを回避できます。したがって、一重引用符の意味は次のオブジェクトを引用することです。これで、シンボルとその値を区別できます。

(define a 1)

(define b 2)

(list a b)
(1 2)

(list ’a ’b)
(a b)

(list ’a b)
(a 2)

記号を含むリストは、私たちの言語の表現のように見える可能性があります:

(* (+ 23 45) (+ x 9)) 
(define (fact n) (if (= n 1) 1 (* n (fact (- n 1)))))

例:記号による微分

4
Sergiu Starciuc