我有一个名为clean-up
的函数,它基本上可以完成已经可用的flatten
函数的工作。然后,我有了一个名为multiplier
的函数,该函数接收一个列表并将其中的所有数字相乘。一个问题是,有时multiplier
中使用的列表可能会有一种奇怪的语法,并且它不会将每个数字相乘。例如:
示例输入
(multiplier '((1 (2 3)) 4 5 (6)))
正确的输出
720
我的输出
*: contract violation
expected: number?
given: '(6 . 1)
argument position: 2nd
other arguments...
我们现在不喜欢错误吗?此multiplier
函数可用于外观正常的列表,例如(multiplier '(1 2 3 4 5 6))
。因此,我编写了clean-up
函数,将一些令人困惑的列表变成了正常外观的列表。但是,在尝试解析并进行乘法运算之前,我不知道如何调用它来清理列表。我可以验证clean-up
函数是否能很好地完成其工作。有人可以帮忙吗?这是我两个人的代码:
(define (clean-up s)
(cond [(null? s) '()]
[(not (pair? s)) (list s)]
[else (append (clean-up (car s)) (clean-up (cdr s)))]
))
(define multiplier
(lambda (s)
(cond [(null? s) 1]
[(number? (car s)) (* (car s) (multiplier(cdr s)))]
[list? (car s) (append (car s) (multiplier(cdr s)))]
[else (multiplier (cdr s))]
)))
答案 0 :(得分:1)
不需要clean-up
函数来解决multiplier
中遇到的问题。但是,您可以首先使用以下命令在输入上调用clean-up
:
scratch.rkt> (multiplier (clean-up '((1 (2 3)) 4 5 (6))))
720
或者,您可以创建一个辅助函数来为您执行此操作:
(define (multiplier-workaround s)
(multiplier (clean-up s)))
scratch.rkt> (multiplier-workaround '((1 (2 3)) 4 5 (6)))
720
类似的解决方法可能会在一定程度上帮助您,但不能解决代码中的实际问题。
使用更好的代码格式可能更容易发现此处的某些问题。在Lisps中留下吊括号是 bad 样式,就像这些是C样式语言一样。但这可能不会给您造成问题。但是,使用缩进来显示表达式的结构是好样式。通过适当的缩进,很明显list?
谓词行中缺少括号:
(define multiplier
(lambda (s)
(cond [(null? s) 1]
[(number? (car s))
(* (car s) (multiplier(cdr s)))]
[list? (car s)
(append (car s) (multiplier (cdr s)))]
[else
(multiplier (cdr s))])))
对该行的进一步调查显示,代码正在尝试将(car s)
附加到(multiplier (cdr s))
的结果中;然而,现在已知(car s)
是一个列表,而multiplier
应该返回一个数字!这里的意图肯定是要与列表multiply
上的调用(car s)
的结果与(multiplier (cdr s))
的结果相乘:
(define multiplier
(lambda (s)
(cond [(null? s) 1]
[(number? (car s))
(* (car s)
(multiplier (cdr s)))]
[(list? (car s))
(* (multiplier (car s))
(multiplier (cdr s)))]
[else
(multiplier (cdr s))])))
不清楚为什么需要else
分支,除非OP希望能够处理诸如(a (1 (2 b) (3 (c (4 5) 6) d) e)))
之类的列表。对于期望嵌套数字列表的代码,可以这样做:
(define multiplier-2
(lambda (s)
(cond [(null? s) 1]
[(number? (car s))
(* (car s) (multiplier (cdr s)))]
[else
(* (multiplier (car s))
(multiplier (cdr s)))])))
这两个函数现在都可以用于OP示例表达式,并且更正后的OP代码也可以用于带有虚假值的输入:
scratch.rkt> (multiplier '((1 (2 3)) 4 5 (6)))
720
scratch.rkt> (multiplier-2 '((1 (2 3)) 4 5 (6)))
720
scratch.rkt> (multiplier '(a (1 (2 3)) 4 5 b (6) c))
720
答案 1 :(得分:0)
我认为内置flatten
的错误处理更多。
(define (multiplier lst)
(apply * (filter number? (flatten lst))))
;;; TEST
(define test-lst1 (list + (vector 1) '(1 (2 3) c) "w" 4 5 '(6) + - * sqr))
(define test-lst2 '(1(a 2(3 b (c 4(d 5 e(6) (f)))))))
(multiplier test-lst1) ; 720
(multiplier test-lst2) ; 720