参数覆盖在 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)))])))
基本情况要求 l1
和 l2
都为 null?
,但由于 l2
被 ol
同时替换为 l1
从一个元素到零都不会是 null
因为 l2
将是原始列表。
那么默认情况下会尝试在空列表上使用first
。要解决此问题,只需更改基本情况以在 l1
为 null?
:
时终止
(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))
我对 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)))])))
基本情况要求 l1
和 l2
都为 null?
,但由于 l2
被 ol
同时替换为 l1
从一个元素到零都不会是 null
因为 l2
将是原始列表。
那么默认情况下会尝试在空列表上使用first
。要解决此问题,只需更改基本情况以在 l1
为 null?
:
(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))