我想向您寻求帮助,以完成下面的代码,条件是测试列表ws
和vs
是否不相等。如果它们不相等,则返回文本false(#f)
,否则返回下面的处理代码。我盯着令人满意的变量len1和len2,它们都在计算两个列表的长度。当我运行它时,出现以下错误:lambda: no expression after a sequence of internal definitions in: lambda
我在做什么错了?
(define (weighted-sum . ws)
(define (sub . vs)
(let ((len1 (length ws)) (len2 (length vs)))
(if (not (equal? (len1 len2) '#f))
(foldl
(lambda (i j res) (+ res (* i j)))
0
ws vs)))
sub)
感谢帮助。
答案 0 :(得分:3)
length
几乎始终是Scheme中的反模式。
length
是 O(n)操作,它被调用两次,然后您调用另一个 O(n)操作foldl
,导致weighted-sum
的 O(3n)过程-远离理想的最小 O(n)。 foldl
是许多线性计算的理想选择,但是由于长度匹配的要求,您已经创建了一个小圆角方孔的情况。
使用命名的let
和match*
,我们将weighted-sum
写为 O(n)计算-
#lang racket
(define ((weighted-sum . ws) . vs) ;; curried form syntactic sugar
(let loop ((acc 0)
(ws ws)
(vs vs))
(match* (ws vs)
;; both lists have at least one value
[((list w ws ...) (list v vs ...))
(loop (+ acc (* w v))
ws
vs)]
;; both lists are empty
[((list) (list))
acc]
;; any other case
[(_ _)
#f])))
当然match*
是一个漂亮的宏,因此,我将向您展示如何使用简单的weighted-sum
表达式重写cond
。准备好逻辑推理的帽子:条件子句的 order 在这里非常重要-
(define ((weighted-sum . ws) . vs)
(let loop ((acc 0)
(ws ws)
(vs vs))
(cond
;; both lists are empty
[(and (null? ws)
(null? vs))
acc]
;; at least one list is empty
[(or (null? ws)
(null? vs))
#f]
;; inductive: both lists have at least one value
[else
(loop (+ acc (* (car ws)
(car vs)))
(cdr ws)
(cdr vs))])))
两个程序都具有相同的输出-
((weighted-sum 1 2 3) 1 2 3)
;; 14
((weighted-sum 1 2 3) 1 2)
;; #f
((weighted-sum 1 2) 1 2 3)
;; #f
((weighted-sum))
;; 0
答案 1 :(得分:1)
在))
之后擦除#f
。在))
之后添加len1 len2)
,它将起作用。 (不太完全,但是close (*))
#f
是自我评估,您无需引用它。缩进(foldl ...)
形式,该形式现已成为if
表达式的一部分。
最后,(if (not A) #f B)
与(if A B #f)
和(and A B)
相同。
检查两个列表的 lengths (携带的(sic)和预期的)是否相等是正确的。我不明白为什么列表自己应该相等。据我所知,它们不应该。
(weighted-sum list-of-weights)
创建了一个过程,该过程期望一个数字列表使用先前提供的权重来计算其加权和。
(*)经过更多修复后,更正后的代码为:
(define (weighted-sum . ws)
(define (sub . vs)
(let ((len1 (length ws)) (len2 (length vs)))
(and (equal? len1 len2)
(foldl
(lambda (i j res) (+ res (* i j)))
0
ws vs))))
sub)
强烈建议安装例如球拍并使用其编辑器查看并更正括号不匹配等情况。