[Scheme] Scheme怎么实现串型宏?

不得不说,学了sicp后对编程有了很多理解,也越来越喜欢Scheme,不过我觉得Clojure中的一些工具宏挺好用,但到了Scheme我不会重写一遍 (Scheme中的宏sicp里没有讲) 现在我想在Scheme中实现->>和->,不怎么熟悉Scheme中的宏,请教各位,谢谢 :grin:

论坛有关于 threading 宏的讨论: 分享:让 Common Lisp 代码更简洁可读性高一些~

Racket 里有一个 threading 的实现:https://github.com/lexi-lambda/threading,不过可能实现得有点复杂了。

(define (~>> arg list-of-funcs)
  ((fold-left compose (lambda (x) x) list-of-funcs) arg))

不过我实在看不懂这里为什么有两层括号,有Scheme宏的教程链接能给我发一个吗

因为这不是宏,是函数

1 个赞
(define-syntax ~>
  (syntax-rules ()
    ((_ value)
     value)
    ((_ value (subr args ...) others-clauses ...)
     (~> (subr value args ...) others-clauses ...))
    ((_ value subr other-clauses ...)
     (~> (subr value) other-clauses ...))))

(~> 1 (+ 2) (- 1) (* 3))
;; (* (- (+ 1 2) 1) 3)
;; => 6


(define (add1 rhs) (+ 1 rhs))

(~> 1 add1 (+ 2) (* 3))
;; (* (+ (add1 1) 2) 3)
;; => 12

(~> 1 (* 3) add1 (+ 2))
;; (+ (add1 (* 1 3)) 2)
;; => 6

楼上给的lexi-lambda的实现用的syntax-parse只有Racket有

谢谢大佬
顺便问下thread-last怎么实现

照葫芦画瓢,改插入value的位置

还是写一下吧,Scheme的宏实在看不懂 :stuck_out_tongue:

(define-syntax ~>>
  (syntax-rules ()
    ((_ value)
     value)
    ((_ value (subr args ...) other-clauses ...)
     (~>> (subr args ...  value) other-clauses ...))
    ((_ value subr other-clauses ...)
     (~>> (subr value) other-clauses ...))))

应该是这样,谢谢大佬指点 :grin:

哪有两层括号。。。

最后的那个)对应的是define

foldl / fold-left 之前有两个左括号啊

kuohao

哪有两层,这里黄色标出的部分是一个函数。

绿色 vs 黄色不是两层嘛,我的理解里楼主是想说这个

今天逛 SRFI 里发现有这个 SRFI 197: Pipeline Operators

Lisp里两个括号、甚至N个括号在左边或者在右边,都是再正常不过了。

不太常见的情况是,直接两层括号,比如:

((foo bar))

即使是这样也是有可能的,(foo bar) 返回一个无参lambda

实现Anaphoric threading

(define-syntax athread
    (lambda (x)
      (syntax-case x ()
        ((_ expr)
         #'expr)
        ((_ expr other-clauses ...)
         (with-syntax ((it (datum->syntax x 'it)))
           #'(let ((it expr))
               (athread other-clauses ...)))))))
(athread 3 (+ 1 it)) ;; => 4

Racket 7.5 Guile 2.2.0通过,Chez 9.5.2不通过,俺暂且蒙在鼓里。

Chez 的报错信息很明显了: Exception in datum->syntax: #<syntax (athread ...)> is not an identifier

(datum->syntax x 'it) 里的 x 换成一个 identifier 就好了,比如可以

...
(syntax-case stx ()
  ...
  [(athreading expr more ...)
   (with-syntax ([it (datum->syntax #'athreading 'it)])
    #'(let ([it expr]) (athreading more ...))])
...

另附 r6rs 里 datum->syntax 的文档:r6rs-lib


另外,即使之前 (datum->syntax x 'it) 的解法可以跑通 (athread 3 (+ 1 it)) 的例子,但只要子句多一点就会发现问题:

> (athread 3 (+ 1 it) (- it 4))
-1

正常情况它应该得到 0 的结果。

1 个赞