0

我目前正在学习一些 r7rs,我正在尝试实现一个宏“开始”,如下所示:

(begin0 expr0 expr1 ... expr2)

expr 是一个正则表达式(Like (set!x (+ x 1)))

begin0 作为一个宏,它计算所有表达式但只返回 expr1 结果。

例如 :

(let ((year 2017))
(begin1 (set! year (+ year 1))
  year
  (set! year (+ year 1))
  year)) 

它必须返回 2018

我首先创建了一个开始函数:

(define-syntax begin0
 (syntax-rules ()
  ((begin-0 body-expr-0 body-expr-1 ...)
   (let ((tmp body-expr-0)) body-expr-1 ... tmp))))

现在,我试图了解如何返回 "body-expr-1" 的值?我已经完成了以下代码,但它说我遗漏了一些省略号,我不明白该怎么做。

(define-syntax begin1
  (syntax-rules ()
    ((begin1 body-expr-0 body-expr-1 ... body-expr-2)
     (let ((tmp body-expr-0) body-expr-1 ... tmp)
       (cond (eq? tmp body-expr-1)
              (begin . tmp))))))

我希望它是可以理解的,谢谢你的回答。

4

2 回答 2

2

这是可以做到的,但是宏会干扰,以至于你不能begin1像 with 那样做所有的事情begin

(define-syntax begin1
   (syntax-rules ()
     ((_ expr0 expr1 exprn ...)
      (begin
        expr0
        (let ((result expr1))
          exprn ...
          result)))))

不起作用的代码是这样的:

(begin1
  (define global1 10)
  test3
  (define global2 20))

原因很明显。它扩展为:

(begin1
  (define global1 10)
  (let ((result~1 test3))
    (define global2 20)
    result~1))

第二个define将更改为 aletrec使得该变量global2仅在let. 我对此没有解决办法,因为它要求您能够define从关闭中执行全局操作。

begin1是比较奇怪的功能。在 Racket 和其他 Scheme 方言中,我们有begin0返回第一个表达式的结果。这非常有用。例如。这是一个计数器:

(define (get-counter from)
  (lambda ()
    (let ((tmp from))
      (set! from (+ from 1))
      tmp)))

并与begin0

(define (get-counter from)
  (lambda ()
    (begin0 
      from
      (set! from (+ from 1)))))

在 Racketbegin0中是一个原始的。所以它是完全扩展的程序支持的一种形式,因此用 C 实现,就像begin..

于 2018-11-27T22:22:41.083 回答
-1

因此,我找到了一种可能的方法,尽管我们可以只询问即时值的条件,但我没有:

(define-syntax begin1
  (syntax-rules ()
    ((begin1 body-expr-0 body-expr-1 body-expr-2 ...)
       (if body-expr-1
          (write body-expr-1)))))
于 2018-11-27T16:12:10.823 回答