How can this racket code be improved for anaphoric & # 8594; or - >> macro?

I want to create a Racket macro that includes the functionality of one of the Clojure macros for streaming, but additionally requires an anaphoric argument (for example it), allowing me to specify where each previous value should be inserted in the next function call.

Start with a macro ->>(ported to a circuit or racket), where each call to a new function implicitly inserts the value of the previous function as the last argument:

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

>> : , , it ( 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))))  

, it , (range 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 ...)))]))  
+4
3

. → , ( → > ). → → > .

#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

. .

+4

, >> :

(define (>> it . fs)
  ((apply compose
          (reverse fs))
   it))

(>> 5 add1 even?) ;; => #t

, , , it. , , . , fancy-app, , _ :

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

, , >> , , , . fancy-app raco pkg install fancy-app (require fancy-app)

+4

, , , . (, , ). >>=, ; -)

? , , ( >>, )

syntax-cases ( , ). Petrofsky plain syntax-rules:

(define-syntax >>= (syntax-rules ()
 ([_ th fa] fa)
 ([_ th fa . fb]
  (let-syntax ([K (syntax-rules () ([_ (this) ts]
     (let ([this fa])
       (>>= this . ts)))
   )])
   (extract* (th)
      fb (K [] fb))
   ))
 ))

:

(>>= _
    (range 10)  
    (map add1 _)  
    (take _ 5)   
    (apply + _)) ;; => 15

PS Hint: to get >>(the rewriting version >>=) you need to change only one form in the definition >>=; -)

PPS Here syntax-rulesfor extract*, kindly provided by Al-Petrofsky and Oleg Kiselev

(define-syntax-rule [extract symb body _k]
   (letrec-syntax ([tr (syntax-rules (symb)
     ([_ x symb tail (k symb-l . args)]
      (k (x . symb-l) . args))
     ([_ d (x . y) tail k]
      (tr x x (y . tail) k))
     ([_ d1 d2 () (k  symb-l . args)]
      (k (symb . symb-l) . args))
     ([_ d1 d2 (x . y) k]
      (tr x x y k)))])
      (tr body body () _k))
   )
(define-syntax extract* (syntax-rules ()
    ([_ (symb) body k]
     (extract symb body k))
    ([_ _symbs _body _k]
     (letrec-syntax ([ex-aux
       (syntax-rules ()
         ([_ found-symbs () body k]
          (reverse () found-symbs k))
         ([_ found-symbs (symb . symb-others) body k]
          (extract symb body
             (ex-aux found-symbs symb-others body k)))
         )]
      (reverse  
       (syntax-rules ()
         ([_ res () (k' () . args)]
          (k' res . args))
         ([_ res (x . tail) k]
          (reverse (x . res) tail k)))))
       (ex-aux () _symbs _body _k)))))
0
source

All Articles