球拍中的管道

Piping in Racket

是否可以在 Racket 中使用管道将一个函数的输出转到下一个。例如,是否可以重写以下代码:

(define (safestr sentstr)
   (list->string
    (remove*
     (list   #\| #\;  #\:  #\/ #\ #\' #\")
     (string->list sentstr) )))

(define  (safestr sentstr)
  sentstr | 
  (string->list .) |
  (remove* (list #\: #\;) .) |
  (list->string .) )

其中“.”表示前一条语句的输出。

这也显示了正常的流动方向和进度,而不是反向流动。

Racket 是创造语言的语言,应该可以做到这一点。我在这里查看 https://docs.racket-lang.org/reference/pipeports.html 但找不到如何执行此操作。

感谢您的comments/answers。

是的,实际上,虽然语法与您列出的有很大不同。 threading package implements precisely this sort of thing, borrowed from Clojure’s threading macros. Using threading,您的函数将如下所示:

(require threading)

(define (safestr sentstr)
  (~>> sentstr
       string->list
       (remove* (list #\| #\; #\: #\/ #\ #\' #\"))
       list->string))

查看 ~>> 的文档了解更多信息。

您也可以使用 λ~>> 来消除完全命名参数的需要:

(require threading)

(define safestr
  (λ~>> string->list
        (remove* (list #\| #\; #\: #\/ #\ #\' #\"))
        list->string))

还有 point-free package, which implements similar functionality using higher-order functions rather than macros. When paired with a lambda shorthand package like curly-fn,结果看起来与使用 threading 的版本非常相似,无需使用宏:

#lang curly-fn racket/base

(require point-free)

(define safestr
  (λ~> string->list
       #{remove* (list #\| #\; #\: #\/ #\ #\' #\")}
       list->string))