gpt4 book ai didi

racket - 如何编写一个新的 #%datum 函数来捕获所有字符串?

转载 作者:行者123 更新时间:2023-12-04 13:42:38 27 4
gpt4 key购买 nike

我想编写一种新的 Racket 语言,以某种特殊的方式捕获和处理字符串。我编写了以下示例代码:

#lang racket

(provide #%top #%app #%top-interaction #%module-begin
(rename-out [datum #%datum]))

(define big-string "")

(define (add-string x)
(set! big-string (string-append big-string x)))

(define-syntax (datum stx)
(syntax-case stx ()
[(_ . x)
#'(if (string? x)
(#%datum . (add-string x))
(#%datum . x))]))

当我尝试使用目标语言时,它给了我一个内存不足的错误。它是递归调用自己吗?我原以为卫生会阻止这种情况。

也许问题是 #%datum 返回语法,而不是数据?

最佳答案

首先让我们看一下上面datum版本的问题。
假设程序包含字符串 "a" .
扩展器看到字符串 "a"并将其转为 (#%datum . "a") .
由于#%datum绑定(bind)到 datum定义为:

(define-syntax (datum stx)
(syntax-case stx ()
[(_ . x)
#'(if (string? x)
(#%datum . (add-string x))
(#%datum . x))]))

语法 (#%datum . "a")将扩大到
       (if (string? "a")
(#%datum . (add-string "a"))
(#%datum . "a"))

然后扩展器将开始扩展上述表达式。
说到第一个 "a"它将扩展为 (#%datum . "a")变成 (datum . "a")然后成为另一个副本
       (if (string? "a")
(#%datum . (add-string "a"))
(#%datum . "a"))

等等

意向 datum将使用两个不同的扩展 (add-string x)(#%datum . x) .然而,由于 datum 的输出是 #'(if (string? x) ...) if不在编译时评估,而是在运行时评估。

解决方法是移动 if .
#lang racket

(provide #%top #%app #%top-interaction #%module-begin
(rename-out [datum #%datum]))

(define big-string "")

(define (add-string x)
(set! big-string (string-append big-string x))
x)

(define-syntax (datum stx)
(syntax-case stx ()
[(_ . x)
(if (string? (syntax-e #'x))
#'(add-string (#%datum . x))
#'(#%datum . x))]))

除了移动 if我已更改 add-string结果。

注意:如果宏使用扩展为相同宏的使用,
那么你很可能会遇到这个无限膨胀的问题。
找到罪魁祸首的最简单方法是使用宏步进器。
将“宏隐藏:”设置为“禁用”。然后一步直到你
看到循环。

关于racket - 如何编写一个新的 #%datum 函数来捕获所有字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37045195/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com