Lisp 如何使Racket reader宏将一个角色的任何实例转换为其他两个角色?

Lisp 如何使Racket reader宏将一个角色的任何实例转换为其他两个角色?,lisp,scheme,racket,Lisp,Scheme,Racket,更具体地说,我需要将\的任何实例转换为\\\\。我试着阅读有关reader宏的文档,但我完全迷路了。有人能用可以理解的术语来解释这一点吗?或者最好能告诉我如何编写这样一个宏 找到了!下面是调整(read)功能以将的所有实例更改为\\\\的代码: (define rt2 (make-readtable #f #\| 'non-terminating-macro (lambda (c in . _)

更具体地说,我需要将
\
的任何实例转换为
\\\\
。我试着阅读有关reader宏的文档,但我完全迷路了。有人能用可以理解的术语来解释这一点吗?或者最好能告诉我如何编写这样一个宏

找到了!下面是调整
(read)
功能以将
的所有实例更改为
\\\\
的代码:

(define rt2 (make-readtable #f #\| 'non-terminating-macro
                            (lambda (c in . _)
                              '\|)))

(parameterize ([current-readtable rt2]
               [current-namespace ns])
  (eval (read)))

实际上,您正在破坏通常语法中的
|
的通常含义,因此您应该以某种统一的方式这样做,以尽量减少意外。您的解决方案不能做到这一点——它会根据是否是第一件事而对
|
进行不同的处理,这是不好的。例如,
xxx | xxx
将其作为整个符号中的一个字符来读取,这意味着您将获得一个名称为“xxx | xxx”的符号,但输入为
| xxx
时,您将得到两个名称分别为
“|”
“xxx”
的符号。因此,最好只是让语法将
|
视为其他字符,以获得更一致、更易于解释的行为

代码的另一个可能问题是将
#f
用作可读表,这意味着阅读器不会与可能被修改的阅读器进行组合

最后,您应该真正注意额外的参数,并在给定它们时返回语法对象。原因很明显,我猜你不这么做的原因是你对阅读这样的代码感兴趣。但你们真的应该有一只眼睛去看潜在的扩展,而且在Racket中,这种代码的明显未来将是编写一种合适的语言,而不是一种读+评估的黑客。诚然,这似乎有些过分,但在本例中,有一个简单的解决方案,即使用“与其他字符相同”的快捷方式来避免编写冗长的代码

以下内容涉及所有这些问题:

(define rt (let ([c (current-readtable)]) (make-readtable c #\| #\a c)))

问题:您能解释一下为什么需要这个吗?这里有一些关于readtables的潜在相关文档:扩展reader。但是,如果我们能更多地了解您正在考虑的转换的特定用途,也许我们可以在这里做一些更好的事情。@dyoo我真的很想做一个名为
|
的函数。事实上,我以前曾访问过该页面,但我将仔细查看。如果我弄明白了,我会把答案贴在这里让你知道。接下来:你为什么想要一个名为
|
的函数?没有更多的上下文,这似乎有点奇怪。你能再说一次你为什么要这个吗?您可以在没有读卡器宏的情况下使用如下转义:
(define(\\\124; x)(list“pipe”x))
@dyoo是的,我将调用函数
\\\124;
,但我使用
(read)
读入代码,然后对其求值。我正在阅读的代码确实需要能够调用一个函数,比如
(\124;废话)
,然后我会将它翻译成
(\ \124;废话)