本文介绍了Little Schemer:仅支持长度≤2的列表的写函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

小计划者一书中,我们发现此功能仅支持长度小于或等于 1 的列表:

In the book The little schemer, we find this function that only supports lists with length smaller than or equal to 1:

 (((lambda (mk-length)                                  ; A.
      (mk-length mk-length))
  (lambda (mk-length)
      (lambda (l)
          (cond
              ((null? l ) 0)
              (else (add1 ((mk-length  eternity ) (cdr l))))))))
 '(1))

我想一步一步学习,并且想编写类似的函数,仅支持长度小于或等于 2 的列表.

I want to study step by step, and want to write the similar function that supports only lists of length smaller than or equal to 2.

请不要通过提供以下代码来回答这个问题:

Please, don't answer this question by offering code like:

(((lambda (mk-length)                                   ; B.
      (mk-length mk-length))
  (lambda (mk-length)
      (lambda (l)
          (cond
              ((null? l) 0 )
              (else (add1((mk-length mk-length) (cdr l))))))))
 '(a b c d))

因为此功能支持任何长度.

because this function supports any length.

我已经知道如何编写这样的函数:

And I already know how to write function like this:

(((lambda (mk-length)                                   ; C.
      (mk-length
          (mk-length (mk-length eternity))))
  (lambda (length)
      (lambda (l)
          (cond
              ((null? l) 0)
              (else (add1 (length (cdr l))))))))
 '(1 2)) ;;

实现我的目标.但是,这段代码与第一个代码段相距不止一个步骤.

to achieve my goal. But this code is more than one step away from the first snippet.

也许我不应该更改:

(lambda (mk-length)                                     ; D.
      (mk-length mk-length)

推荐答案

TL; DR: (mk-length A)(在cond表单内部)计算 length 函数适用于长度为 0 的列表,并将使用(A A)计算将用于尾部的 length 函数(即(cdr ...)).

TL;DR: (mk-length A) (inside the cond form) calculates the length function that works for lists of length 0 and will use (A A) to calculate the length function that will be used to work on the tail (i.e. the result of (cdr ...)) of the argument list.

您的第一个代码段(;A.)仅适用于长度为 0 1 的列表.要使其也适用于 2 ,请替换

Your first code snippet (;A.) works for lists of length 0 and 1 only. To make it work for 2 also, replacing

                               (mk-length eternity)               ; length≤1

使用

                               (mk-length   ; (2)                 ; length≤2
                                  (lambda (x) (mk-length eternity)))

有效.

(注意:(mk-length eternity)本身会计算length≤0,但整体功能变为length≤1是所有length≤i注释所引用的内容.)

(NB: (mk-length eternity) itself calculates length≤0, but the overall function becomes length≤1; this is what all the further length≤i comments refer to.)

密切关注

     (((lambda (mk-length)
          (mk-length mk-length))            
      (lambda (mk-length)                   ; (1)
          (lambda (l)                       
              (cond
                  ((null? l ) 0)
                  (else (add1 ((mk-length   ; (2)                 ; length≤2
                                  (lambda (x) (mk-length eternity)) )
                               (cdr l))))))))
     '(1 2))

我们可以看到,在;(2)处的(mk-length ...)结果用于处理(cdr l),而在;(2)处的 argument mk-length将替换mk-length在处理(cddr l)时调用.

we can see that the result of (mk-length ...) at ;(2) is used to process (cdr l), while the argument to mk-length at ;(2) will replace mk-length in that call when processing the (cddr l).

如果使用(mk-length eternity)(如您的第一个代码一样),则(cdr l)可以正常处理,但((eternity eternity) (cddr l))自然会失败.

If (mk-length eternity) is used (as in your first code), (cdr l) gets processed OK but ((eternity eternity) (cddr l)) naturally fails.

如果使用(mk-length (lambda (x) (mk-length eternity))),则(cdr l)得到处理,然后((lambda (x) (mk-length eternity)) (lambda (x) (mk-length eternity))) = (mk-length eternity)用于处理(cddr l),这也可以(因此,正确处理了长度 2 ),那么((eternity eternity) (cdddr l))自然会失败(长度为 3 及以上).

If (mk-length (lambda (x) (mk-length eternity))) is used, (cdr l) gets processed OK and then ((lambda (x) (mk-length eternity)) (lambda (x) (mk-length eternity))) = (mk-length eternity) is used to process (cddr l) which is also OK (so, length 2 is handled correctly), and then ((eternity eternity) (cdddr l)) naturally fails (for lengths 3 and up).

因此可以处理最多三个元素的列表,

Thus to process the lists of up to three elements,

                              ((mk-length   ; (2)                 ; length≤3
                                  (lambda (x) (mk-length 
                                                (lambda (x) (mk-length eternity)))) )

可以使用:

    (define (eternity x) (- 1))    ; to get an error instead of looping

    (((lambda (mk-length)
          (mk-length mk-length))
      (lambda (mk-length)
          (lambda (l)
              (cond
                  ((null? l ) 0)
                  (else (add1 ((mk-length   ; (2)                 ; length≤3
                                  (lambda (x) (mk-length
                                               (lambda (x) (mk-length eternity)))) )
                               (cdr l))))))))

      '(1 2 3))        ; => 3

    ; ...........
    ; '(1 2 3 4))      ; => **error**

您正确地猜到了,是使用方式中的过渡步骤

As you correctly surmised, this is the interim step on the way to using

                     (mk-length (lambda (x) (mk-length x)))   ; (2)       ; length≤∞

将列表中的下一个元素处理为

which turns, on the processing of the next element of the list into

                     ((lambda (x) (mk-length x)) (lambda (x) (mk-length x)))
    =
                     (mk-length (lambda (x) (mk-length x)))

,因此适用于每个列表,无论其长度如何.

and thus works for every list, whatever its length is.

通过eta转换,这只是(mk-length mk-length).

And by eta-conversion this is just (mk-length mk-length).

这篇关于Little Schemer:仅支持长度≤2的列表的写函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-28 21:41