2011-06-04 55 views
4

我想知道如何在Racket中實現cadr,caddr和類似的可變版本,而無需單獨定義每個版本?即。不是cadr,caddr等的可變版本

(define (mcadr exp) 
    (mcar (mcdr exp))) 

似乎對於可變列表或對,球拍只支持mcar和mcdr,但不支持「擴展」版本。我需要知道並擅長宏才能做到這一點?

回答

2

你可以這樣做:

(define mcaar (compose mcar mcar)) 
(define mcadr (compose mcar mcdr)) 
;; ... 
(define mcddddr (compose mcdr mcdr mcdr mcdr)) 

但沒有真正圍繞重複獲得。即使在球拍來源(查看​​),重複也在那裏,雖然用C宏進行了一些修飾。

+1

是的,這可能是甜蜜點不涉及宏的解決方案。 – 2011-06-05 00:24:37

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)) 
+1

+1爲硬核。 – 2011-06-05 01:11:22