Что именно является символом в lisp / схеме? - PullRequest
34 голосов
/ 13 января 2012

Ради любви всемогущего, мне еще предстоит понять назначение символа 'iamasymbolЯ понимаю числа, логические значения, строки ... переменные.Но символы - это слишком много для моего маленького умственного мышления.Для чего именно я их использую?Как они должны использоваться в программе?Мое понимание этой концепции просто неудачно.

Ответы [ 5 ]

29 голосов
/ 13 января 2012

Символ - это объект с простым строковым представлением, которое (по умолчанию) гарантированно будет interned ; то есть любые два символа, которые записаны одинаково, являются одним и тем же объектом в памяти (ссылочное равенство).

Почему в Лиспе есть символы? Что ж, во многом это артефакт того факта, что Лиспы встраивают свой собственный синтаксис в качестве типа данных языка. Компиляторы и интерпретаторы используют символы для представления идентификаторов в программе; поскольку Lisp позволяет вам представлять синтаксис программы в виде данных, он предоставляет символы, потому что они являются частью представления.

Чем они полезны помимо этого? Ну и несколько вещей:

  • Lisp обычно используется для реализации встроенных доменных языков. Многие из методов, используемых для этого, происходят из мира компиляторов, поэтому здесь полезны символы.
  • Макросы в Common Lisp обычно включают в себя работу с символами более подробно, чем этот ответ. (Хотя, в частности, генерация уникальных идентификаторов для расширений макросов требует возможности генерировать символ, который гарантированно никогда не будет равен любому другому.)
  • Фиксированные типы перечисления лучше реализованы в виде символов, чем строк, поскольку символы можно сравнивать по ссылочному равенству.
  • Существует множество структур данных, которые вы можете создать, где вы можете получить выигрыш в производительности, используя символы и равенство ссылок.
28 голосов
/ 13 января 2012

В схеме и ракетке символ похож на неизменную строку, которая оказывается интернированной, так что символы можно сравнивать с eq? (быстрое, по существу, сравнение указателей).Символы и строки являются отдельными типами данных.

Одно из применений символов - упрощенные перечисления.Например, можно сказать, что направление: 'north, 'south, 'east или 'west.Конечно, вы можете использовать строки для той же цели, но это будет немного менее эффективно.Использование чисел было бы плохой идеей;представлять информацию как можно более наглядно и прозрачно.

В другом примере SXML - это представление XML с использованием списков, символов и строк.В частности, строки представляют символьные данные, а символы представляют имена элементов.Таким образом, XML <em>hello world</em> будет представлен значением (list 'em "hello world"), которое можно записать более компактно '(em "hello world").

Другое использование символов - это ключи.Например, вы можете реализовать таблицу методов в виде словаря, отображающего символы в функции реализации.Чтобы вызвать метод, вы ищите символ, который соответствует имени метода.Lisp / Scheme / Racket делает это действительно простым, потому что язык уже имеет встроенное соответствие между идентификаторами (часть синтаксиса языка) и символами (значениями в языке).Это соответствие облегчает поддержку макросов , которые реализуют пользовательские синтаксические расширения языка.Например, можно реализовать систему классов как библиотеку макросов, используя неявное соответствие между «именами методов» (синтаксическим понятием, определенным системой классов) и символами:

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

(В других Лиспах,то, что я сказал, в основном верно, но есть еще кое-что, о чем нужно знать, например, пакеты и функции в сравнении со слотами переменных, IIRC.)

7 голосов
/ 13 января 2012

Символы в lisp являются удобочитаемыми идентификаторами.Они все одинокие.Поэтому если вы объявите «foo» где-то в своем коде, а затем снова будете использовать «foo», это будет указывать на одно и то же место в памяти.

Пример использования: разные символы могут представлять разные фигуры на шахматной доске.

5 голосов
/ 13 января 2012

Символ - это просто специальное имя для значения. Значением может быть что угодно, но символ используется для ссылки на одно и то же значение каждый раз, и такого рода вещи используются для быстрых сравнений. Поскольку вы говорите, что вы мыслите императивно, они похожи на числовые константы в C, и именно так они обычно реализуются (внутренне хранимые числа).

3 голосов
/ 23 сентября 2017

Из Структура и интерпретация компьютерных программ. Второе издание Гарольда Абельсона и Джеральда Джея Суссмана, 1996 год:

Чтобы манипулировать символами, нам нужен новый элемент в нашем языке:возможность процитировать объект данных.Предположим, мы хотим построить список (ab).Мы не можем сделать это с помощью (list ab), потому что это выражение создает список значений a и b, а не сами символы.Эта проблема хорошо известна в контексте естественных языков, где слова и предложения могут рассматриваться как семантические объекты или как строки символов (синтаксические объекты).Обычная практика в естественных языках заключается в использовании кавычек, чтобы указать, что слово или предложение следует рассматривать буквально как строку символов.Например, первая буква «Джон» явно «J.» Если мы скажем кому-то «произнесите ваше имя вслух», мы ожидаем услышать имя этого человека.Однако, если мы скажем кому-то «произнести« ваше имя »вслух», мы ожидаем услышать слова «ваше имя». Обратите внимание, что мы вынуждены вкладывать кавычки, чтобы описать то, что может сказать кто-то другой. Мы можем следовать этой же практике, чтобы идентифицировать списки и символы, которые должны рассматриваться как объекты данных, а не как выражения для оценки. Однако наш формат цитирования отличается от формата естественных языков тем, что мы помещаемкавычка (традиционно символ одинарной кавычки ') только в начале цитируемого объекта.Мы можем избежать этого в синтаксисе Схемы, потому что мы используем пробелы и скобки для разделения объектов.Таким образом, значение символа одинарной кавычки заключается в том, чтобы заключить следующий объект в кавычки.Теперь мы можем различать символы и их значения:

(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)))))

Пример: символьная дифференциация

...