列表中项目的重量组合

时间:2014-10-10 00:21:10

标签: recursion functional-programming racket

我在Dr. Racket工作,这是我第一次使用功能语言,所以我很困惑。

我只需要添加每种不同动物的重量"在列表中。 所有不同的动物都有一个体重"属性,但球拍不会让我访问"体重"任何给定列表元素的项目,因为它声称它未定义"

到目前为止我所拥有的:

(define (zoo-weight animals)
 (cond [(empty? animals) 0]
       [else (+ (first weight)(zoo-weight (rest animals)))])) ;This is where I get the error for weight, saying it is undefined.

如果有人可以让我知道如何引用体重而不管列表项目(蛇重,牛重等),这整个功能性的东西都会让人感到困惑。

谢谢!

3 个答案:

答案 0 :(得分:1)

你几乎得到了它!尝试这样的事情:

(define (zoo-weight animals)
  (cond [(empty? animals) 0]
        [else (+ (weight (first animals))
                 (zoo-weight (rest animals)))]))

问题是你不能说(first weight)。什么是weight?它可能是适用于动物或变量的功能。所以,你写道:“取weight的第一个元素”。显然,没有意义,我们想从列表中取出第一只动物,然后然后找出动物的体重,然后进入列表中的下一个动物。

如上所示,在你的程序中使用以下表达式,假设给我们动物体重的函数被称为weight(如果没有,使用适当的函数 - animal-wight,{ {1}},我不知道你怎么称呼它:

weight-animal

<强>更新

现在你提到每只动物都有不同的体重功能,我有几点评论。这是一个糟糕设计的症状,同样的功能应该适用于各种动物,以避免到处都是那些长条件(如果我们添加一种新的动物,这将是一个麻烦!)。我不知道这些动物目前是如何实施的,所以我无法提出进一步的建议。但如果无法修复当前表示,至少将条件封装在一个地方,如下所示:

(weight (first animals))

现在我的(define (weight animal) ; find the correct weight function ((cond ((snake? animal) snake-weight) ((dillo? animal) dillo-weight) ((ant? animal) ant-weight) (else (error "Unknown animal:" animal))) ; apply the function to the animal animal)) 实现无需任何修改即可使用,无需在需要权重的地方复制条件。如果写一个以上的函数是一个问题(我无法想象为什么你的老师会提出这个限制,函数式编程鼓励构建大量可重用的函数!),我们总是可以插入代码:

zoo-weight

另外,借用@ Jack的解决方案,我们可以使用(define (zoo-weight animals) (cond [(empty? animals) 0] [else (+ (let ([animal (first animals)]) ((cond ((snake? animal) snake-weight) ((dillo? animal) dillo-weight) ((ant? animal) ant-weight) (else (error "Unknown animal:" animal))) animal)) (zoo-weight (rest animals)))])) (匿名函数)和高阶lambda过程。这仍然算作一个单一的功能:

map

答案 1 :(得分:1)

假设你有一个动物列表和一个动物weight,它需要一只动物并给你它的重量,你最好不要在这里使用applymap代替自己做递归:

(define (zoo-weight animals)
  (apply + (map weight animals)))

map获取一个函数和一个列表,并为列表中的每个事物调用一次函数,例如(map sqrt '(9 16 25))评估到列表'(3 4 5)apply函数接受一个函数和一个列表,并以列表项作为参数调用该函数,例如(apply + '(1 2 3))(+ 1 2 3)相同。通过组合这两者,您可以获得所需的功能。从这些模式的角度来学习思考可能很困难,但是一旦你做到了,这样做的好处是巨大的。但是你应该首先深入理解Oscar Lopez的回答中的递归模式,这对于理解函数式编程模式是绝对必要的。

更新

关于没有一般weight函数只允许创建一个的那一点就是限制。通常在函数式语言中,许多通用函数和辅助函数都是 good 。您可以使用Oscar答案中概述的匿名函数方法,但我想补充一点,使用zoo-weight将此函数绑定到let函数体中的名称可能会更好:

(define (zoo-weight animals)
  (let ([weight (lambda (animal)
                  ((cond [(snake? animal) snake-weight]
                         [(dillo? animal) dillo-weight]
                         [(ant?   animal) ant-weight]
                         [else (error "Unknown animal:" animal)])
                   animal))])
    (apply + (map weight animals)))

您也可以使用内部define实现相同的目标:

(define (zoo-weight animals)
  (define (weight animal)
    ((cond [(snake? animal) snake-weight]
           [(dillo? animal) dillo-weight]
           [(ant?   animal) ant-weight]
           [else (error "Unknown animal:" animal)])
     animal))
  (apply + (map weight animals)))

这与定义单独的辅助函数基本相同,但weight函数隐藏在zoo-weight函数内 - zoo-weight函数外的任何代码都不能使用帮助器


正如约书亚所说,你可以使用其他更高阶的函数,例如foldl的变体。 foldl获取函数,初始值和列表,并使用步骤中的函数将列表缩减为一个值。 (foldl + 0 '(1 2 3))(foldl + 1 '(2 3))相同,(foldl + 3 '(3))foldl相同,为6.在Racket中,使用(apply + (map weight animals))代替(foldl + 0 (map weight animals)) (foldl (lambda (animal acc) (+ acc (weight animal))) 0 animals) 看起来像这些中的任何一个:

(for/fold ([sum 0]) ([animal animals])
  (+ sum (weight animal)))

Racket还提供了for/fold宏,它可以使逻辑更清晰:

reduce

这个基于Common Lisp (define (reduce f xs #:key [key-func #f]) (let ([xs (if key-func (map key-func xs) xs)]) (foldl f (first xs) (rest xs)))) (reduce + animals #:key weight) 的折叠功能也适用:

{{1}}

答案 2 :(得分:0)

谢谢大家的回复,我放弃了你的时间投票。你的所有答案都很好,除了我只允许一个功能,所以我不能做出一个重量&#34;获得任何动物体重的功能。我最终不得不用一个大的&#34; cond&#34;声明如下。我知道这是不太好的代码,但它可以完成工作而无需构建任何其他功能(这是我唯一的选择):

(define (zoo-weight animals)
  (cond [(empty? animals) 0]
        [(snake? (first animals)) (+(snake-weight (first animals))(zoo-weight (rest animals)))]
        [(dillo? (first animals)) (+(dillo-weight (first animals))(zoo-weight (rest animals)))]
        [(ant? (first animals))   (+(ant-weight (first animals))(zoo-weight (rest animals)))]
        ))

再次感谢,您的所有答案都帮助我来到这里!