Як створити: ключові слова?


16

З: Як створювати та використовувати :keywords?

Розглянемо (наївну, мабуть) спробу отримати доступ до наступного іграшкового списку:

(setf alist '((:key-1 "Key no. 1")
              (:key-2 "Key no. 2")))

(assq :key-1 alist)                 ; => (:key-1 "Key no. 1")
(assq (make-symbol ":key-1") alist) ; => nil

Перший ключ працює так, як очікувалося, а другий - ні. Наскільки явна make-keywordфункція не існує , як створювати та використовувати ключове слово?

Оригінальна мотивація: Мені потрібно перетворити рядок у ключ пошуку, який є символом, на який я можу мати putвластивості.

У процесі формулювання цього питання я отримав принаймні частину відповіді, яку я публікую окремо. Я сподіваюся, що яскравіші розуми, ніж мій, можуть покращитись.


1
(eq :foo (read ":foo"))
або-або

Відповіді:


9

Ви маєте рацію, що make-symbolстворить ключове слово, яке не eqвідповідає жодному існуючому ключовому слову, і internможе забруднити глобальний оберіг новим символом. Між тим, у вас є intern-soft, який повертає символ, якщо він вже був створений, або nilякщо він ще ні:

ELISP> (intern-soft ":key-1")
nil
ELISP> :key-1
:key-1
ELISP> (intern-soft ":key-1")
:key-1

Це повинно відповідати вашим цілям: якщо ключове слово не існує, воно не може бути присутнім у списку, тому немає необхідності створювати його лише для того, щоб перевірити, чи існує воно. Щось на зразок:

(let ((maybe-keyword (intern-soft ":key-1")))
  (and maybe-keyword (assq maybe-keyword alist)))

Розумний - Я бачив, intern-softале не думав використовувати це таким чином.
День

6

Можливо, я неправильно не розумію питання. Але якщо ви хочете ключове слово (тобто, ви хочете задовольнити keywordp) , то ви хочете , щоб символ інтернований в глобальній obarray , obarray.

Він повинен бути інтернований там, щоб задовольнити keywordp, AFAICT, і це C-h f keywordpговорить.

Тож відповідь на ваше запитання, AFAICT, просто використовуватиintern .

Я відчуваю, що ти, можливо, не задаєш свого справжнього запитання - здається, питання XY. Що ви насправді намагаєтесь зробити? (Можливо, поставити це як окреме запитання.)

[У відповідь на ваш коментар, що інтернування " не є :keywordконкретним, оскільки воно стосується всіх символів ": Правильне, інтернування не характерне для ключових слів. Але стажування (in obarray) та використання, symbol-nameяке починається з :, характерне для ключових слів.]


Це, звичайно, XY питання в тому сенсі, що я намагаюся Y, але мене дуже зацікавив X у моїй спробі дістатися до Y. Дозвольте трохи подумати, як поставити питання про Y таким чином, що це корисний і іншим.
День

Чудово. Це буде корисно. Дякую.
Дрю

2

Ось часткова відповідь на це питання. Короткий і не зовсім задовольняючий варіант, здається,: використання intern.

:key-1 задовольняє обом:

(symbolp :key-1)                    ; => t
(keywordp :key-1)                   ; => t

Хоча (make-symbol ":key-1")задовольняє перше, але не друге:

(symbolp (make-symbol ":key-1"))    ; => t
(keywordp (make-symbol ":key-1"))   ; => nil

Тепер, docstring для make-symbolговорить, що це:

Поверніть щойно виділений безперебійний символ, ім'я якого - NAME.

Mmmkay, і docstring для keywordpговорить, що це:

Поверніть, tякщо OBJECT є ключовим словом. Це означає, що це символ із назвою друку, що починається з : інтернованого в початковому підкреслі.

Отже, виходить, що internспрацює:

(assq (intern ":key-1") alist)      ; => (:key-1 "Key no. 1")

Тому що intern:

Поверніть канонічний символ, ім'я якого - STRING. Якщо його немає, один створюється за допомогою цієї функції та повертається. Другий необов’язковий аргумент вказує використовувати тепловир; він за замовчуванням дорівнює значення obarray.

Але це не здається :keywordспецифічним, оскільки це стосується всіх символів. За замовчуванням воно також видає забруднення глобального obarray, що може бути, а може і не бути великою угодою.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.