参数覆盖在 scheme/racket 中不起作用

Argument overwrite doesn't work in scheme/racket

我对 Racket/Scheme 还很陌生。我知道基本语法。
我写了一个程序来做 list1 和 list2 的笛卡尔积。我使用 Dr Racket 调试程序。似乎当 l2 变为 null 时,程序不会将 l2 替换为原始列表,即 ol2(这是我正在尝试做的)。
我无法弄清楚为什么会这样。

 (define product   (lambda (ol2 l1 l2)  
     (cond  
       [(and (null? l1) (null? l2)) '()]  
       [(null? l2) (product ol2 (rest l1) ol2)]  
       [else (cons (list (first l1) (first l2)) (product ol2 l1 (rest l2)))])))  

在您的原始代码中:

(define product   (lambda (ol2 l1 l2)  
     (cond  
       [(and (null? l1) (null? l2)) '()]  
       [(null? l2) (product ol2 (rest l1) ol2)]  ; here l1 gets empty and l2 becomes the same as ol2
       [else (cons (list (first l1) (first l2)) (product ol2 l1 (rest l2)))])))  

基本情况要求 l1l2 都为 null?,但由于 l2ol 同时替换为 l1 从一个元素到零都不会是 null 因为 l2 将是原始列表。

那么默认情况下会尝试在空列表上使用first。要解决此问题,只需更改基本情况以在 l1null?:

时终止
(define product   (lambda (ol2 l1 l2)  
     (cond  
       [(null? l1) '()] ; terminate when l1 is null? 
       [(null? l2) (product ol2 (rest l1) ol2)] 
       [else (cons (list (first l1) (first l2)) (product ol2 l1 (rest l2)))])))  

使用一个本应相同的额外变量对我或其他评论者来说并不明显。使用命名的 let 或本地帮助程序隐藏了用户不必关心的实现细节:

;; with named let
(define (product l1 l2)
  (let product ((l1 l1) (tl2 l2)) 
    (cond  
      [(null? l1) '()] ; terminate when l1 is null? 
      [(null? tl2) (product (rest l1) l2)] 
      [else (cons (list (first l1) (first tl2)) (product l1 (rest tl2)))])))  

;; with local helper procedure
(define (product l1 l2)
  (define (product l1 tl2) 
    (cond  
      [(null? l1) '()] ; terminate when l1 is null? 
      [(null? tl2) (product (rest l1) l2)] 
      [else (cons (list (first l1) (first tl2)) (product l1 (rest tl2)))]))
  ;; call the helper
  (product l1 l2))