需要在方案中使用抽象列表函数来练习

时间:2013-12-11 22:10:28

标签: scheme

有没有人知道在方案中解释抽象列表功能的任何好问题或网站?出于某种原因,我很难理解抽象列表函数以及如何使用它们。

当给出一个必须单独使用抽象列表函数解决的问题时,我几乎完全迷失了。

作为一个例子,我如何编写一个只使用抽象列表函数查找列表中最大元素的函数?

这是我到目前为止所做的:

(define (maximum lst)
  (foldr (lambda (e acc) (if (empty? acc) empty
                           (if (< acc e) acc empty))) empty lst))

有人可以向我解释为什么它不起作用以及我做错了什么? 非常感谢

2 个答案:

答案 0 :(得分:2)

(请注意,我假设您使用了Racket,因为您的代码中的参数顺序为foldr;如果我对此错误,我可以将其调整为。) < / p>

我会这样做:

(define (maximum lst)
  (if (null? lst) 
      lst               
      (foldl 
       (lambda (e r) (if (< r e) e r))  ; function to call successively
       (car lst)                        ; initial value for the result r
       (cdr lst))))                     ; list to call function for (element by element)
  • 如果列表为空,则返回空列表(或任何您认为合适的;必要的,因为我们之后使用car,如果列表为空则会抛出错误)
  • 如果没有,请使用foldl(为此,如果您使用foldlfoldr无效,但foldl效率更高)
    • 将结果初始化为第一个元素(car
    • 对于列表的其余部分(cdr),使用1.下一个元素调用该函数2.前一个结果
    • 在函数中
      • 如果e&gt; r,返回e,否则返回r(返回的值在下一次调用时绑定到r,或者是每个项目处理后foldl的结果)

示例:

(maximum '(3 6 7 1))
  1. r初始化为3(car lst
  2. 调用函数,e = 6(下一个元素),r = 3(初始化值),返回6
  3. 调用函数,e = 7(下一个元素),r = 6(上一个结果),返回7
  4. 使用e = 1(下一个元素)和r = 7(上一个结果)调用该函数,返回7,因此7成为foldl的结果
  5. 请注意,Racket有第二种表达方式,可能更容易阅读,因为它更接近传统的for循环:

    (define (maximum lst)
      (if (null? lst) 
          '()
          (for/fold ((r (car lst))) ((e (in-list (cdr lst))))
            (if (< r e) e r))))
    

答案 1 :(得分:0)

当你寻求帮助时,要理解为什么它不起作用。

(define (maximum lst)
  (foldr (lambda (e acc) (if (empty? acc) empty
                           (if (< acc e) acc empty))) empty lst))

这里的问题是你的初始对象是“空的”。这意味着acc开头时fold为空。在英语中,您的代码将按如下方式编写:

lst折叠,从空开始。如果acc为空,则返回空。否则,acc小于e返回e但如果不是,请返回空。返回的值将成为新的acc

这里有两个问题:当你从空开始时:acc总是空的。另一个问题是:

(if (< acc e) acc empty)

在这里,如果它小于e,你将返回acc,否则你将返回空。但如果acc小于e,则意味着e更大。这意味着您应该返回e而不是empty

没有真正的理由来检查你的折叠中的empty?

折叠电话看起来像这样:

(foldr (lambda (e acc) (if (< acc e) e acc)) (car lst) (cdr lst))

其转换为折叠列表其余部分的第一个元素。如果acc小于e则返回e,否则返回acc。返回的值将在下一次迭代中替换acc。

不需要做的就是检查空列表,你可能会看到类似的内容。

(define (maximum lst)
  (if (empty? lst)
    (error "Cannot find max from empty list")
    (foldr
      (lambda (e acc)
        (if (< acc e) e acc))
      (car lst)
      lst)))

还有一件事,foldlfoldr是相同的,除了一个从第一个元素开始,一个从最后一个元素开始。在我的解决方案中,我没有测试,但由于我的最后一个参数是整个列表,所以你使用的折叠版本无关紧要。