2

スキームとラケットを学ぶにつれて、このパターンを何度も繰り返していることに気づきます。関数のパラメーターの一部は変更されますが、一部のパラメーターは変更されない再帰関数があります。すべてのパラメーターを受け取る外側の関数を作成し、その中で変化するパラメーターのみを受け取り、それを繰り返す内側の関数を定義します。

具体的な例として、"The Little Schemer" の関数演習に多少基づいたケースを示します。

;inserts an item to the right of an element in a list   
(define   (insert-to-right new old lat)    
  (define (insert-to-right lat)  
    (cond  
      [(null? lat) lat]  
      [(eq? old (car lat) ) (cons old (cons new (cdr lat)))]  
      [else (cons (car lat) (insert-to-right    (cdr lat)))]))  
    (insert-to-right lat)) 

次のようにマクロ define* と演算子 (垂直バーなど) を作成することは可能ですか?

(define*   (insert-to-right new old | lat)      
    (cond  
      [(null? lat) lat]  
      [(eq? old (car lat) ) (cons old (cons new (cdr lat)))]  
      [else (cons (car lat) (insert-to-right    (cdr lat)))]))  

これは最初の形式に展開され、すべてのパラメーターが外側の関数に渡されますが、垂直バーの後のパラメーターのみが内側のループに渡されます。

4

3 に答える 3

8

そのようなマクロを書くこともできますが、名前付き let を使うこともできます:

(define (insert-to-right new old lat)
  (let loop ([lat lat])
    (cond
      [(null? lat)         lat]  
      [(eq? old (car lat)) (cons old (cons new (cdr lat)))]  
      [else                (cons (car lat) (loop (cdr lat)))])))
于 2012-04-08T20:39:36.540 に答える
3

遊んだ後、私は自分がやりたいことをするマクロを作りました。

(define-syntax-rule 
  (define* (function-name (outer-var ...)  (inner-var ...)) expr ...)
  (define (function-name outer-var ... inner-var ...) 
    (define (function-name inner-var ...)expr ...)
    (function-name inner-var ...)))   


(define*   (insert-to-right [new old] [lat])        
    (cond  
      [(null? lat) lat]  
      [(eq? old (car lat) ) (cons old (cons new (cdr lat)))]  
      [else (cons (car lat) (insert-to-right    (cdr lat)))])) 

> (insert-to-right 11 3 '(1 2 3 4 5 6))
'(1 2 3 11 4 5 6)

define *ステートメントでは、(最初​​に試みたように)内部パラメーターと外部パラメーターの間にセパレーターを使用しませんが、define *ステートメントの内部パラメーターと外部パラメーターを別々のリストに入れます。これは、より慣用的なスキーム/ラケットだと思います。 。

于 2012-04-09T02:52:12.993 に答える
0

これを行うためにマクロを使用しないでください。これは高階関数の典型例です。特に、あなたの例はpair-fold-rightSRFI-1 から書くことができると思います。テストされていないコード (これが正しいことを願っています):

(define (insert-to-right new old lat)
  (pair-fold-right (lambda (pair rest)
                     (if (eq? (car pair) old)
                         (cons (car pair)
                               (cons new rest))
                         pair))
                   '()
                   lat))

;;; Example implementation of pair-fold-right, just for one list—your Scheme system
;;; probably has this as a library function somewhere
(define (pair-fold-right fn init list)
  (if (null? list)
      init
      (fn list (pair-fold-right fn init (cdr list)))))
于 2012-04-10T21:17:43.040 に答える