将列表作为参数函数传递?

时间:2012-03-12 06:53:59

标签: scheme

我试图在方案中创建一个简单的函数,找到列表中的最大数字。

这是我的代码:

(define (maximo lista maximo_actual)
    (if (= lista ())
        maximo_actual
        (let* ((primero maximo_actual)
               (segundo (car lista)))
          (if (> primero segundo)
              ((maximo (cdr lista) primero))
              ((maximo (cdr lista) segundo))))))

我用这个函数调用函数:

(maximo (list 6 3 2 8 9) 5)

程序返回:

;ERROR: "programas.scm": =: Wrong type in arg1 (6 3 2 8 9)
; in expression: (#@= #@lista ())
; in scope:
;   (lista maximo_actual)  procedure maximo
; defined by load: "programas.scm"

我认为参数有问题。我正在学习计划,我不知道问题出在哪里。

4 个答案:

答案 0 :(得分:5)

我的awnser基于Racket(基于方案)

您的计划存在一些问题。一,=比较数字,而不是列表。其次()是一个没有任何内容的函数,而不是列表。要创建空列表,请使用(list)'()。最后,((maximo (cdr lista) primero))有一组额外的括号,导致(maximo (cdr lista) primero)的结果被执行。但是,(maximo (cdr lista) primero)的结果是一个数字。

我认为你想要这样的东西,当用9

调用时会返回(maximo (list 6 3 2 8 9) 5)
(define (maximo lista maximo_actual)
    (if (empty? lista)
        maximo_actual
        (let* ((primero maximo_actual)
                (segundo (car lista)))
            (if ( > primero segundo)
                (maximo (cdr lista) primero)
                (maximo (cdr lista) segundo)))))

您也可以使用fold来编写它,它稍微短一些:

(define (maxio2 current result)
  (if (> current result)
      current
      result))

(foldl maxio2 5 (list 6 3 2 8 9))

答案 1 :(得分:2)

我的功能有四点:

  • 您的错误是因为=运算符用于数字比较,而不是一般相等。要测试列表是否为空,通常使用null?函数。
  • 此外,对于if ... then ... else if ...种语句,通常使用cond,而非if
  • 这里不需要let*; unstarred let会做的。事实上,对于这个简单的函数,我完全不需要let绑定。
  • 你真的应该使用传统的Lisp缩进,并将括号括起来。

所以,你的功能,有这些变化:

(define (máximo lista máximo-actual)
  (cond ((null? lista)
         máximo-actual)
        ((> (car lista) máximo-actual)
         (máximo (cdr lista) (car lista)))
        (else
         (máximo (cdr lista) máximo-actual))))

然而,编写此函数的更高级方法是使用fold-left,这是我们可以这样定义的通用列表迭代运算符:

(define (fold-left función valor-corriente lista)
  (if (null? lista)
      valor-corriente
      (fold-left función
                 (función (car lista) valor-corriente)
                 (cdr lista))))

fold-left对应于命令式语言中这种常见类型的for循环:

resultado = valor_inicial
for valor in valores:
    resultado = función(valor, resultado)
return resultado

使用fold-left和第二个辅助功能máximo-de-dos-valores,现在我们有:

(define (máximo lista máximo-inicial)
  (fold-left máximo-de-dos-valores máximo-inicial lista))

(define (máximo-de-dos-valores a b)
  (if (> a b)
      a
      b))

答案 2 :(得分:1)

这是一个更惯用的Scheme程序,用于查找列表中的最大值:

(define (mi-maximo lista)
  (if (empty? lista)
      null
      (maximo (rest lista) (first lista))))

(define (maximo lista maximo-actual)
  (cond ((empty? lista) maximo-actual)
        ((> (first lista) maximo-actual)
         (maximo (rest lista) (first lista)))
        (else (maximo (rest lista) maximo-actual))))

请注意,我引入了一个新过程mi-maximo来调用帮助程序maximo,该过程完成所有工作。对于有两个以上条件的情况,最好使用cond而不是一系列嵌套if。最后,如果列表为空,则首选使用empty?null?进行测试。使用上述步骤:

(mi-maximo '(1 2 3 4 5))
> 5

作为最后一点,对样式的评论:在Scheme(以及其他LISP)中,关闭同一行的所有括号,而不是单独的行。他们不是大括号,你知道:)。

答案 3 :(得分:0)

(define (max-num lat)
(cond ((null? lat) (error "invalid list of numbers"))
      ((null? (cdr lat)) (car lat))
      (else (max (car lat) (max-num (cdr lat))))))

这假设'max'是一个内置程序,我认为大多数方案实现都会有。