【问题标题】:Custom Scheme indexing function returns list-external value自定义方案索引函数返回列表外部值
【发布时间】:2017-08-29 07:33:32
【问题描述】:

我是方案编程的新手,正在编写小代码时遇到以下问题,无法令人满意地推理。

(define (at_i lst i)
  (if (eq? i 0)
    (car lst)
    (at_i (cdr lst)
          (- i  1) )))

(at_i '(1 2 3 4) 0) 的评估返回 1。 现在让我们用 lambda 语法定义相同的过程。

(define (at_i lst i)
  (lambda (vec x)
    (if (eq? x 0)
      (car vec)
      (at_i (cdr vec)
            (- x  1) )))
  lst i)

但现在(at_i '(1 2 3 4) 0) 的求值返回0,它不在列表中,通常它返回索引为 1 的元素。

我不明白为什么会这样。

注意:我刚刚意识到它不是返回索引处的元素 - 1 而是索引本身。 @Renzo 在下面很好地解释了其原因。谢谢!

【问题讨论】:

  • Scheme 中的标准命名约定是at-i
  • 以防万一:Scheme 的链表是一种根本不同的数据结构,例如,C++ 的基于动态数组的vector。

标签: indexing lambda linked-list scheme guile


【解决方案1】:

eq? 是内存对象相等。只有一些 Scheme 实现将(eq? 5 5) 解释为#t= 用于数字,eqv? 用于值,equal? 用于集合。

(define (index i xs)       ; `index` is a partial function,
   (if (= i 0)             ; `i` may go out of range
      (car xs)
      (index (- i 1)       ; Tail recursion
             (cdr xs) )))

您的第二个函数返回索引,因为您错过了 lambda 应用程序周围的括号。应该是

(define (index i xs)
   ((lambda (i' xs')
       (if (= i' 0)
          (car xs')
          (index (- i' 1)      ; Not tail-recursive
                 (cdr xs') )))
    i xs))

但这很冗长,并且在语义上与第一个表述不同。

【讨论】:

    【解决方案2】:

    您说您正在定义“使用 lambda 语法的相同过程”,但您不是。那将是(define at_i (lambda lst i) ...)。相反,您实际上是在说(define (at_i lst i) 1 2 3),当然是3

    在您的特定情况下,您将过程at_i 定义为返回(lambda (vec x) ...)lsti。现在,如果您调用(at_i '(1 2 3 4) 0),该过程将返回0,因为此时这是i 的值。

    【讨论】:

    • 那么 0 是从哪里来的呢?也许你应该多解释一下,因为我不熟悉这种编程范式。
    【解决方案3】:

    首先,如果您打算学习该语言,则应该正确缩进代码,因为代码缩进对于理解 Scheme 和 Lisp 类语言的程序非常重要。

    例如,正确缩进的函数是:

    (define (at_i lst i)
      (lambda (vec x)
        (if (eq? x 0)
            (car vec)
            (at_i (cdr vec) (- x  1))))
      lst
      i)
    

    从这里你可以看到你定义的函数at_i与之前完全一样的函数有两个参数(lsti),它的主体由三个表达式组成:第一个@ 987654325@,这是一个(匿名)函数(lambda),它没有被调用或应用,第二个是第一个参数lst,最后是第三个,是第二个参数i。所以,当使用两个参数调用函数at_i时,结果是依次对三个表达式求值,前两个值被丢弃(函数和lst的值),结果是值第二个参数i。这就是(at_i '(1 2 3 4) 0) 的结果是0 的原因,因为它是i 的值。

    例如,以 lambda 形式对函数进行适当的重新定义如下:

    (define at_i
      (lambda (vec x)
        (if (eq? x 0)
            (car vec)
            (at_i (cdr vec) (- x  1)))))
    
    (at_i '(1 2 3 4) 0)  ;; => 1
    

    您可以在其中看到名称at_i,通过define,与正确计算结果的双参数函数相关联。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-27
      • 2023-03-25
      • 2014-02-27
      • 2021-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多