Scheme 宏r7rs:返回第二个表达式值

Scheme 宏r7rs:返回第二个表达式值,scheme,racket,r6rs,define-syntax,r7rs,Scheme,Racket,R6rs,Define Syntax,R7rs,我目前正在学习一些R7R,并尝试实现宏“begin”,如下所示: (begin0 expr0 expr1 ... expr2) expr是正则表达式(如(set!x(+x1))) 和begin0作为一个宏,该宏计算所有表达式,但仅返回expr1结果 例如: (let ((year 2017)) (begin1 (set! year (+ year 1)) year (set! year (+ year 1)) year)) 它必须在2018年回归 我首先创建了一个begin函数

我目前正在学习一些R7R,并尝试实现宏“begin”,如下所示:

(begin0 expr0 expr1 ... expr2)
expr是正则表达式(如(set!x(+x1)))

和begin0作为一个宏,该宏计算所有表达式,但仅返回expr1结果

例如:

(let ((year 2017))
(begin1 (set! year (+ year 1))
  year
  (set! year (+ year 1))
  year)) 
它必须在2018年回归

我首先创建了一个begin函数:

(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))))))

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

所以,我找到了一种可能的方法,我没有想到我们可以问一个关于立即值的条件:

(define-syntax begin1
  (syntax-rules ()
    ((begin1 body-expr-0 body-expr-1 body-expr-2 ...)
       (if body-expr-1
          (write body-expr-1)))))

这是可以做到的,但宏会产生干扰,使您无法像使用
begin
一样使用
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
将更改为
letrec
,这样变量
global2
仅在
let
期间可用。我对此没有解决方案,因为它要求您能够从闭包中执行全局
define

begin1
是一个相当奇怪的特性。在Racket和其他Scheme方言中,我们有
begin0
,它返回第一个表达式的结果。这是非常有用的。这是一个柜台:

(define (get-counter from)
  (lambda ()
    (let ((tmp from))
      (set! from (+ from 1))
      tmp)))
使用
开始0

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

在Racket
begin0
中是一个原语。因此,它是完全扩展程序中支持的一种形式,因此用C实现,就像
begin

在这里,除了第二个表达式之外,您不需要计算任何其他表达式。我假设
(begin1(display“h”)(display“I”)(display“!”)
应该打印“hi!”,结果是
#
,但事实并非如此。感谢您的回答,这正是我所需要的!非常感谢你的解释,我不知道该怎么做,但它似乎更清楚!