scheme

Pipe-Function in scheme


I am enthusiastic about scheme but I'm missing a "fast-to-type-and-easy-to-read" way (without parantheses) to create a "pipeline", like in F#. Something like

(pipe x
      f1 y
      f2 z1 z2
      f3
      ...)

The main problem is that the functions (f1, f2, f3, ...) can have different numbers of parameters. The best solution would probably be to create a macro. But I don't work with macros yet. The best solution I have so far is as follows:

(define c ;currying a one parameter function
  (lambda (x)
    (lambda (f)
      (lambda (y) (f y x)))))

(define cc ;currying a two parameter function 
  (lambda (x)
    (lambda (f)
      (lambda (y)
    (lambda (z) (f y z x))))))

(define (pipe x . y)
  (let loop ((x x) (y y))
    (cond ((null? y) x)
      ((procedure? x) (loop (x (car y)) (cdr y)))
      (else (loop ((car y) x) (cdr y))))))
 
;; Testing: 
(pipe 10
    cc + 1 22
    c + 2
    c * 10
    ) ; returns 350

I would be grateful for any suggestions for improvement. Preferably without the auxiliary functions "c" and "cc". Perhaps with a pipe operator like "|" in F#?


Solution

  • Thanks for your comments.

    I think it would be best to use a simple fold left here. Functions with multiple parameters would then have to be passed via a lambda function:

    ;; chez scheme
    (define (p x . y) (fold-left (lambda (a x) (x a)) x y))
    
    ;; racket
    (define (p x . y) (foldl (lambda (x a) (x a)) x y))
    
    ;; usage
    (p 9
       add1
       (lambda (x) (- x 2))
       )