可变版本的cadr,caddr等

Rob*_*ail 4 macros scheme racket

我想知道如何在Racket中实现可变版本的cadr,caddr等,而不是分别定义每一个?即.不

(define (mcadr exp)
    (mcar (mcdr exp)))
Run Code Online (Sandbox Code Playgroud)

似乎对于可变列表或对,Racket仅支持mcar和mcdr,但不支持"扩展"版本.我是否需要知道并擅长宏才能做到这一点?

Eli*_*lay 9

这是一个宏观解决方案:

#lang racket/base

(require racket/mpair (for-syntax racket/base))

(define-syntax (define-combinations stx)
  (syntax-case stx ()
    [(_ n) (integer? (syntax-e #'n))
     (let ([n (syntax-e #'n)])
       (define options (list (cons "a" #'mcar) (cons "d" #'mcdr)))
       (define (add-options r)
         (apply append
                (map (? (opt)
                       (map (? (l) (cons (string-append (car opt) (car l))
                                         (list (cdr opt) (cdr l))))
                            r))
                     options)))
       (define combinations
         (cdddr
          (let loop ([n n] [r '(("" . x))])
            (if (zero? n) r (append r (loop (sub1 n) (add-options r)))))))
       (define (make-name combo)
         (let ([s (string->symbol (string-append "mc" (car combo) "r"))])
           (datum->syntax stx s stx)))
       (with-syntax ([(body ...) (map cdr combinations)]
                     [(name ...) (map make-name combinations)])
         #'(begin (define (name x) body) ...)))]))

(define-combinations 4)
(mcaddr (mlist 1 2 3 4 5))
Run Code Online (Sandbox Code Playgroud)