宏 – 如何改进回指 – >或 – >>宏的球拍代码?

我想创建一个包含其中一个功能的Racket宏
Clojure的线程宏,但另外需要一个回指的论点
(例如它),允许我具体指出每个先前值应插入下一个函数调用的位置.

我将从 – >>开始macro(移植到scheme或racket),其中每个新函数调用隐式地将前一个函数的值作为其最后一个参数插入:

(define-syntax ->>  
  (syntax-rules ()  
    [(_ x) x]  
    [(_ x (y ...) rest ...)  
     (->> (y ... x) rest ...)]))  

(->> (range 10)  
     (map add1)  
     (apply +)  
     (printf "the sum is: ~a\n"))  

; "the sum is: 55"

我现在定义一个名为>>的宏使用语法大小写:
当然,我只需要这个新的宏,当它不一定是
最后一个参数(当使用Clojure时,也不总是第一个参数 – >
宏).

(define-syntax (>> stx)  
  (syntax-case stx ()  
    [(_ x) #'x]  
    [(_ x (y ...) rest ...)  
     (with-syntax ([it (datum->syntax stx 'it)])  
       #'(let ([it x])  
           (>> (y ...) rest ...)))]))  

(>> (range 10)  
    (map add1 it)  
    (take it 5)  ; 'it' is not the last argument  
    (apply + it))

不幸的是,在评估时,宏返回45而不是15.

DrRacket的宏步进器显示扩展为:

(let ([it (range 10)])  
  (let ([it (map add1 it)])  
    (let ([it (take it 5)]) (apply + it))))

步进器还表示最终它被绑定到了
返回的值(范围10).鉴于此信息,返回
值45解释.但为什么会这样呢?任何人都可以
帮我纠正这个词汇范围问题?

顺便说一句,宏写的略有不同
语法参数化工作正常:

(require racket/stxparam)  
(define-syntax-parameter it  
  (lambda (stx)  
    (raise-syntax-error #f "can only be used inside '>>'" stx)))  

(define-syntax >>  
  (syntax-rules ()  
    [(_ x) x]  
    [(_ x (y ...) rest ...)  
      (let ([val x])  
        (syntax-parameterize ([it (make-rename-transformer #'val)])  
          (>> (y ...) rest ...)))]))
这是一种方法.首先定义>>的版本使用显式的(在它下面称为>>>). >>的定义只需生成一个标识符并将其交给>>>.

#lang racket
(define-syntax (>>> stx)  
  (syntax-case stx ()  
    [(_ it x) #'x]  
    [(_ it x (y ...) rest ...)
     #'(let ([it x])  
         (>>> it (y ...) rest ...))]))

(>>> it
    (range 10)  
    (map add1 it) 
    (take it 5)  
    (apply + it))

(define-syntax (>> stx)
  (with-syntax ([it (datum->syntax stx 'it)])
    (syntax-case stx ()
      [(_ . more)
       #'(>>> it . more)])))

(>> (range 10)  
    (map add1 it) 
    (take it 5)  
    (apply + it))

输出是:

15
15

注意:我更喜欢你的语法参数化版本.

相关文章
相关标签/搜索