Common lisp Lisp:如何映射汽车#x";为了一张十六进制的列表?
使用#x。。。如下图所示,可以获得十六进制值的小数Common lisp Lisp:如何映射汽车#x";为了一张十六进制的列表?,common-lisp,Common Lisp,使用#x。。。如下图所示,可以获得十六进制值的小数 > #xB1 177 > #xA5 165 > #xFF 255 假设我们有一个十六进制列表,使用mapcar#x的正确语法是什么。。。超过名单?以下内容不起作用: > (mapcar #'(lambda (hex) `(#x,hex)) '(B1 A5 FF)) 读卡器错误:a#b/#o/#x/#r宏中的数字格式错误。 [简单错误类型的条件] 谢谢 x是所谓的“读取器宏”。它非常类似于使用引号(即“”)来表示字符
> #xB1
177
> #xA5
165
> #xFF
255
假设我们有一个十六进制列表,使用mapcar#x的正确语法是什么。。。超过名单?以下内容不起作用:
> (mapcar #'(lambda (hex) `(#x,hex)) '(B1 A5 FF))
读卡器错误:a#b/#o/#x/#r宏中的数字格式错误。
[简单错误类型的条件]
谢谢 x是所谓的“读取器宏”。它非常类似于使用引号(即“”)来表示字符串。它们在读取/编译代码时执行。实际上,您需要的是一个可以在运行时从十六进制字符串转换而来的过程。您正在寻找的过程是parse integer,它接受一个字符串并返回它所表示的值。带有它的mapcar应该如下所示:
(mapcar (lambda (hex)
(parse-integer hex :radix 16))
'("B1" "A5" "FF"))
(mapcar (lambda (hex)
(parse-integer (symbol-name hex) :radix 16))
'(B1 A5 FF))
请注意,这是使用字符串,如果您想使用建议中的符号,您必须执行以下操作:
(mapcar (lambda (hex)
(parse-integer hex :radix 16))
'("B1" "A5" "FF"))
(mapcar (lambda (hex)
(parse-integer (symbol-name hex) :radix 16))
'(B1 A5 FF))
如果您不知道符号和字符串之间的区别,我建议您阅读以下内容:我突然想到,虽然解决这个问题的最佳方法可能是使用中提到的解析整数,但从某种意义上说,这可以通过基于映射的方法来解决 当我们编写类似于
#xB1
的东西时,我们并没有显式地调用函数。相反,我们使用的是一个事实,即#
是一个分派读取宏字符,并且为子字符x
安装了一个函数,该函数读取十六进制写入的数字。这意味着,当计算器或编译器获取表单时,数字已经存在。但是,我们可以使用访问处理十六进制字符串的函数。即:
当然,如果你真的想写#x
,你当然可以定义一个版本,只从长度为2的字符串中提取字符,这样你就可以:
CL-USER> (map-dispatch-macro-character* "#x" '(B1 A5 FF))
(177 165 255)
我发现这也能起作用:>(mapcar#’(lambda(hex)(eval(从string(concatenate'string“#x”(string hex‘‘‘)’)))(B1 A5 FF))所示的尝试显示了对代码如何在Lisp中表示和读取的一个非常基本的误解。请尝试理解读取时间、宏扩展时间、编译时间和运行时间之间的差异。
#x..
无法获取十六进制字符串的十进制值;这是写数字的符号。当读卡器读取#xB1
时,它返回数字177。然后,REPL对表单177进行求值,表单177对自身进行求值,然后打印表单177。它的印刷方式取决于许多因素。例如,查看如果(setf*print base*16)
然后评估#xB1
会发生什么。您将看到打印的B1
。谢谢#x是reader宏,我知道mapcar的功能,但mapcar到宏这样的概念我不确定;所以我通常可以使用:lambda(macro-thing)(eval(从字符串“…computed macro-thing…”读取)这样就可以实现mapcar-over-reader宏,是正确的吗?它确实可以工作,但效率极低,也是一个巨大的安全漏洞。早期的Lisp有一流的宏(fexpr),但将宏发送到mapcar
时会出现问题。编译过程非常复杂,最终导致了defmacro
,它们不是第一类对象。@malisper我完全同意在这里使用(eval(从字符串读取…)
是非常危险的。不过,可以获得reader宏函数,并使用已知的输入直接调用它。对于这种特定的情况,这并没有那么好,但它可能有助于一般地分派宏字符,所以我添加了这种方法。不过,正如前面提到的,它更脆弱,因为实现不能保证在调用这些函数时所做的假设。
CL-USER> (funcall (get-dispatch-macro-character #\# #\x)
(make-string-input-stream "B1")
#\x
nil)
; Evaluation aborted on #<SB-INT:SIMPLE-READER-ERROR "~A was invoked
; with RECURSIVE-P being true outside of a recursive read operation."
; {1005F245B3}>. ; in SBCL
(defun map-dispatch-macro-character (disp-char
sub-char
list
&optional (readtable *readtable*))
"Retrieve the dispatch macro character for DISP-CHAR and SUB-CHAR and
map it over the elements in LIST. Each element in LIST is either a
string designator or a two-element list of a string-designator and a
prefix argument."
(flet ((to-list (x)
(if (listp x) x
(list x))))
(let ((fn (get-dispatch-macro-character disp-char sub-char readtable)))
(mapcar (lambda (x)
(destructuring-bind (str &optional prefix) (to-list x)
(with-input-from-string (in (string str))
(funcall fn in sub-char prefix))))
list))))
CL-USER> (map-dispatch-macro-character #\# #\x '(B1 "A5" (FF nil)))
(177 165 255)
CL-USER> (map-dispatch-macro-character* "#x" '(B1 A5 FF))
(177 165 255)