首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Racket:局部扩展递归定义

Racket:局部扩展递归定义
EN

Stack Overflow用户
提问于 2016-09-05 02:55:53
回答 1查看 537关注 0票数 4

我正在尝试编写一个宏,它的行为就像球拍定义一样,但以某种方式处理完全扩展的球拍过程(在下面的示例中,只是为了简单起见而扩展):

代码语言:javascript
运行
复制
(define-syntax (define/expand stx)
  (syntax-case stx ()
    [(_ (head args ...) body body-rest ...)
       (let* ([define/racket (syntax/loc stx (define (head args ...) body body-rest ...))]
              [fully-expanded (local-expand define/racket 'top-level (list))])
           fully-expanded)]
    [(_ id expr) (syntax/loc stx (define id expr))]))

除非满足递归定义,否则一切都很好:

代码语言:javascript
运行
复制
(define/expand (sum n)
  (if (<= n 0)
      0
      (+ n (sum (- n 1)))))

运行它会引发错误。

sum:模块中的未绑定标识符: sum

指向sum的调用(而不是定义)。显然,本地扩展程序没有捕获sum的定义。我尝试过一种简单的修复方法:创建新的本地定义上下文并将head绑定到其中:

代码语言:javascript
运行
复制
(define-syntax (define/expand stx)
  (syntax-case stx ()
    [(_ (head args ...) body body-rest ...)
       (let* ([ctx (syntax-local-make-definition-context)]          ; <- These two lines added 
              [_ (syntax-local-bind-syntaxes (list #'head) #f ctx)] ; <--/
              [define/racket (syntax/loc stx (define (head args ...) body body-rest ...))]
              [fully-expanded (local-expand define/racket 'top-level (list) ctx)])
           fully-expanded)]
    [(_ id expr) (syntax/loc stx (define id expr))]))

它解决了这个问题(本地扩展成功地将过程扩展为define-values),但是创建了另一个:

模块:用于定义的上下文外标识符,在: sum中

指出和的定义。原因可能是扩展程序将标识符绑定到ctx中的标识符,而不是当前上下文中的head

从直觉上看,这似乎不是一个罕见的问题,但我无法通过网络找到解决方案。我认为我应该以某种方式使用local-expand/capture-liftssyntax-local-lift-expression,但是我不知道如何正确地使用它。有人能澄清正在发生的事情和/或提供一个如何解决它的提示吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-09-05 11:36:53

让我们在顶级(Repl)中尝试您的第一个程序:

代码语言:javascript
运行
复制
#lang racket
(define-syntax (define/expand stx)
  (syntax-case stx ()
    [(_ (head args ...) body body-rest ...)
     (let*
         ([define/racket  (syntax/loc stx (define (head args ...) body body-rest ...))]
          [fully-expanded (local-expand define/racket 'top-level (list))])
       fully-expanded)]
    [(_ id expr)
     (syntax/loc stx (define id expr))]))

然后在书斋里:

代码语言:javascript
运行
复制
Welcome to DrRacket, version 6.6.0.3--2016-07-28(-/f) [3m].
Language: racket, with debugging [custom]; memory limit: 1024 MB.
> (define/expand (sum n)
  (if (<= n 0)
      0
      (+ n (sum (- n 1)))))
.#<syntax:3:2 (define-values (sum) (lambda ...>
> (sum 5)
15

这表明您的程序在顶层工作。

同样的方法在模块上下文中不起作用的原因是,#%module-begin在展开表达式之前使用表单的部分展开来检测定义。换句话说,定义/展开必须告诉#%module-begin它扩展为sum的定义,但必须将local-expand的使用推迟到#%module-begin检测到模块级别上的所有绑定标识符为止。

这表明采取两步办法:

代码语言:javascript
运行
复制
#lang racket

(define-syntax (delay-expansion stx)
  (syntax-case stx ()
    [(_delay-expansion more ...)
     (let ([fully-expanded (local-expand #'(lambda () more ...) 'module (list))])
       (display fully-expanded)
       fully-expanded)]))

(define-syntax (define/expand stx)
  (syntax-case stx ()
    [(_ (head args ...) body body-rest ...)
     (syntax/loc stx
       (define (head args ...)
         ((delay-expansion
           body body-rest ...))))]
    [(_ id expr)
     (syntax/loc stx
       (define id expr))]))


(define/expand (sum n)
  (if (<= n 0)
      0
      (+ n (sum (- n 1)))))

(sum 5)

请参阅这里的更多内容:https://groups.google.com/d/msg/racket-users/RB3inP62SVA/54r6pJL0wMYJ

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39323337

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档