如何通过符号宏定义将像(和)一样工作的符号? [英] How to define symbols that will work like ( and ) by symbol macro?

查看:157
本文介绍了如何通过符号宏定义将像(和)一样工作的符号?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过以下方式定义符号a和b

I am trying define symbols a and b in following way

a + 1 1 b
2

我正在尝试通过使用define-symbol-macro

I am trying to do this by using define-symbol-macro

(define-symbol-macro a '( )
(define-symbol-macro b ') )

但是这种方式不起作用.

but this way is not working.

推荐答案

Lisp对源代码的作用

Common Lisp是一种非常灵活的语言,部分原因是它的源代码可以使用该语言中使用的相同数据结构轻松表示.宏扩展的最常见形式将这些结构转换为其他结构.您可以使用define-symbol-macrodefine-compiler-macrodefmacromacrolet定义这些宏.但是,在执行任何此类宏扩展之前,系统首先需要从输入流(通常是文件或交互式提示)中读取源.那是读者的责任.当读取器遇到某些字符(例如(')时,它也可以执行一些特殊的操作.如果您想执行某些操作,可能需要在阅读器级别进行,例如,(read-from-string "a + 1 1 b")返回 list (+ 1 1),这是您想要的.想要(eval (read-from-string "a + 1 1 b"))返回2.也就是说,您还可以定义一种特殊的自定义语言(如loop一样),其中对ab进行特殊处理.

What Lisp does with source code

Common Lisp is an incredibly flexible language, in part because its source code can be easily represented using the same data structures that are used in the language. The most common form of macro expansion transforms the these structures into other structures. These are the kind of macros that you can define with define-symbol-macro, define-compiler-macro, defmacro, and macrolet. Before any of those kind of macroexpansions can be performed, however, the system first needs to read the source from an input stream (typically a file, or an interactive prompt). That's the reader's responsibility. The reader also is capable of executing some special actions when it encounters certain characters, such ( and '. What you're trying to do probably needs to be happening down at the reader level, if you want to have, e.g., (read-from-string "a + 1 1 b") return the list (+ 1 1), which is what you want if you want (eval (read-from-string "a + 1 1 b")) to return 2. That said, you could also define a special custom language (like loop does) where a and b are treated specially.

这不是使用符号宏来执行的操作,而是使用宏字符.您可以使用适当命名的 set-macro-character 设置宏字符.例如,在下面的示例中,我使用

This isn't something that you would do using symbol-macros, but rather with macro characters. You can set macro characters using the aptly named set-macro-character. For instance, in the following, I set the macro character for % to be a function that reads a list, using read-delimited-list that should be terminated by ^. (Using the characters a and b here will prove very difficult, because you won't be able to write things like (set-macro-character ...) afterwards; it would be like writing (set-m(cro-ch(r(cter ...), which is not good.)

CL-USER> (set-macro-character #\% (lambda (stream ignore)
                                    (declare (ignore ignore))
                                    (read-delimited-list #\^ stream)))
T
CL-USER> % + 1 1 ^
2

相关的set-syntax-from-char

这里有一个相关的功能几乎可以满足您的需求,

The related set-syntax-from-char

There's a related function that almost does what you want here, set-syntax-from-char. You can use it to make one character behave like another. For instance, you can make % behave like (

CL-USER> (set-syntax-from-char #\% #\()
T
CL-USER> % + 1 1 )
2

但是,由于与(关联的宏字符不是在寻找与)语法相同的字符,而是 actual )字符,因此您不能只需用相同的方式将)替换为^:

However, since the macro character associated with ( isn't looking for a character that has the same syntax as ), but an actual ) character, you can't simply replace ) with ^ in the same way:

CL-USER> (set-syntax-from-char #\^ #\))
T
CL-USER> % + 1 1 ^
; Evaluation aborted on #<SB-INT:SIMPLE-READER-ERROR "unmatched close parenthesis" {1002C66031}>.

当现有角色本身要模仿时,

set-syntax-from-char会更有用.例如,如果您想为!附加一个引号字符:

set-syntax-from-char is more useful when there's an existing character that, by itself does something that you want to imitate. For instance, if you wanted to make ! an additional quotation character:

CL-USER> (set-syntax-from-char #\! #\')
T
CL-USER> (list !a !(1 2 3))
(A (1 2 3))

或将%用作注释字符,就像在LaTeX中一样:

or make % be a comment character, like it is in LaTeX:

CL-USER> (set-syntax-from-char #\% #\;)
T
CL-USER> (list 1 2 % 3 4
               5 6)
(1 2 5 6)

但是考虑一下为什么要这么做……

现在,即使您可以完成所有这些工作,对于任何碰到它的人来说,这似乎都是完全令人惊讶的. (也许您正在参加一个混乱的编码竞赛?;).由于上面显示的原因,使用ab这样的常用字符进行此操作也将使编写更多的源代码变得非常困难.最好定义一个完全可以执行您想要的操作的全新readtable,甚至编写一个新的解析器.即使(通用)Lisp lets 您重新定义了语言,但仍有一些事情可能会让您保持孤独.

But consider why you're doing this at all…

Now, even though you can do all of this, it seems like something that would be utterly surprising to anyone who ran into it. (Perhaps you're entering an obfuscated coding competition? ;)) For the reasons shown above, doing this with commonly used characters such as a and b will also make it very difficult to write any more source code. It's probably a better bet to define an entirely new readtable that does what you want, or even write a new parser. even though (Common) Lisp lets you redefine the language, there are still things that it probably makes sense to leave alone.

这篇关于如何通过符号宏定义将像(和)一样工作的符号?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆