我想知道如何在Racket中實現cadr,caddr和類似的可變版本,而無需單獨定義每個版本?即。不是cadr,caddr等的可變版本
(define (mcadr exp)
(mcar (mcdr exp)))
似乎對於可變列表或對,球拍只支持mcar和mcdr,但不支持「擴展」版本。我需要知道並擅長宏才能做到這一點?
我想知道如何在Racket中實現cadr,caddr和類似的可變版本,而無需單獨定義每個版本?即。不是cadr,caddr等的可變版本
(define (mcadr exp)
(mcar (mcdr exp)))
似乎對於可變列表或對,球拍只支持mcar和mcdr,但不支持「擴展」版本。我需要知道並擅長宏才能做到這一點?
你可以這樣做:
(define mcaar (compose mcar mcar))
(define mcadr (compose mcar mcdr))
;; ...
(define mcddddr (compose mcdr mcdr mcdr mcdr))
但沒有真正圍繞重複獲得。即使在球拍來源(查看),重複也在那裏,雖然用C宏進行了一些修飾。
這裏有一個宏觀的解決方案:
#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爲硬核。 – 2011-06-05 01:11:22
是的,這可能是甜蜜點不涉及宏的解決方案。 – 2011-06-05 00:24:37