Scheme 是否将列表作为参数函数传递?

Scheme 是否将列表作为参数函数传递?,scheme,Scheme,我试图在scheme中创建一个简单的函数,用于查找列表中的最大数字 这是我的密码: (define (maximo lista maximo_actual) (if (= lista ()) maximo_actual (let* ((primero maximo_actual) (segundo (car lista))) (if (> primero segundo)

我试图在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"

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

我的awnser是基于(基于scheme)

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

我想您需要这样的东西,当使用
(maximo(列表6 3 2 8 9)5)调用时,它将返回
9

您也可以使用略短的

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

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

这是一个更惯用的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
,用于调用helper过程
maximo
,它完成了所有工作。对于有两个以上条件的情况,最好使用
cond
,而不是一系列嵌套的
if
。最后,最好使用
empty?
null?
来测试列表是否为空。按照以下步骤进行操作:

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

最后请注意,在Scheme(以及其他Lisp)中,您可以关闭同一行中的所有括号,而不是在单独的行中。它们不是花括号,你知道:)

我对你的函数有四点看法:

  • 您的错误是因为
    =
    运算符用于数值比较,而不是一般相等。为了测试列表是否为空,通常使用
    null?
    函数
  • 另外,对于
    如果。。。然后。。。否则,如果…
    某种语句,通常使用
    cond
    ,而不是
    if
  • 你不需要
    让*
    在这里;取消拖动
    就行了。事实上,对于这个简单的函数,我完全不需要
    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))))
但是,编写此函数的更高级方法是使用
左折
,这是一种通用的列表迭代运算符,我们可以通过以下方式定义:

(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
使用
左折
和第二个辅助功能
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))

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

非常感谢,我是方案的noob:PWhy你称它为“PLT scheme”,如果你知道这个网站是为“Racket”…?它过去被称为“PLT scheme”。我想称它为“Racket”可能有点混乱。但显然,称之为“PLT方案”也令人困惑,我将编辑我的答案。
(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))
(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))))))