Синтаксис |...|
только один из способов, которыми Лисп принтер может печатать символы, которые имеют символы в имени, которые должны быть экранированы (и что читатель может прочитать символов с этими видами символов в именах) :
(print (intern "foo"))
;=> |foo|
есть и другие способы тоже, в том числе вылетающих отдельных персонажей:
(print '|FOO|)
;=> FOO
(print '\f\o\o)
;=> |foo|
Что вы пытаетесь сделать, это просто создать символ, название которого включает в себя нижний регистр пусть Ослабляет. Это достаточно просто, как показано выше. Часть вашего вопроса, однако, является то, что вы получаете в качестве входных данных символа, имя которого полно заглавных букв, так что вам нужно downcase первого:
CL-USER> (symbol-name 'FOO)
;=> "FOO"
CL-USER> (intern (symbol-name 'FOO))
;=> FOO
CL-USER> (string-downcase (symbol-name 'FOO))
;=> "foo"
CL-USER> (intern (string-downcase (symbol-name 'FOO)))
;=> |foo|
В самом деле, потому что строки-downcase принимает строковые обозначения, а не только строки, вы можете передать символ непосредственно:
CL-USER> (intern (string-downcase 'BaR))
;=> |bar|
Итак, после всего, что обработки строк, мы можем перейти к макро.
Похоже, что вы ищете что-то вроде этого:
(defmacro defmal (name lambda-list &body body)
(let ((mal-name (intern (concatenate 'string "MAL-" (symbol-name name))))
(mal-norm (intern (string-downcase name))))
`(progn
(defun ,mal-name ,lambda-list
,@body)
(register-function ',mal-norm #',mal-name))))
CL-USER> (pprint (macroexpand-1 '(defmal list? (arg)
(eq (mal-type arg) 'list))))
(PROGN
(DEFUN MAL-LIST? (ARG) (EQ (MAL-TYPE ARG) 'LIST))
(REGISTER-FUNCTION '|list?| #'MAL-LIST?))
Это вообще хорошая идея, чтобы избежать использования формата в создании символа имена, поскольку конкретный вывод может изменяться в зависимости от других переменных. Например .:
(loop for case in '(:upcase :downcase :capitalize)
collect (let ((*print-case* case))
(format nil "~a" 'foo)))
;=> ("FOO" "foo" "Foo")
Вместо этого, вы можете использовать СЦЕПИТЬ со строкой (или имя символа символа).Поскольку читатель также может иметь различные настройки чувствительности к регистру, иногда я даже делать (но не все это нравится):
(concatenate 'string (symbol-name '#:mal-) (symbol-name name))
Таким образом, если читатель делает ничего необычного (например, сохраняет случай, так что имя символа mal-
равно "mal-
), вы можете сохранить его и в своем собственном сгенерированном символе.
У символов есть имена. По умолчанию, когда читатель встречается, например, 'foo', он получает строку' 'foo'', увеличивает ее, чтобы получить' 'FOO" ', и стажеров, чтобы получить символ' FOO'. Но символы не должны иметь расширенные имена. Если вы станете '' foo'' (в отличие от '' FOO "'), вы получите символ, который, вероятно, будет напечатан '\ f \ o \ o' или' | foo | '. –
'(format nil" ~ {~ a ~} "' непредсказуем, потому что '* print-case *' может быть задан для множества вещей. '(Format nil" ~ a "'foo)' может возвращать' foo »,« FOO »или« Foo ». –