Передать список в качестве параметра функции? - PullRequest
3 голосов
/ 12 марта 2012

Я пытаюсь создать в схеме простую функцию, которая находит наибольшее число в списке.

Вот мой код:

(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 ]

5 голосов
/ 12 марта 2012

Мой awnser здесь основан на Ракетка (которая основана на схеме)

Есть несколько проблем с вашей программой. Во-первых, = сравнивает числа, а не списки. Во-вторых, () - это функция, в которой ничего нет, а не список. Для создания пустого списка используйте либо (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))
2 голосов
/ 12 марта 2012

У меня есть четыре пункта на вашей функции:

  • Ваша ошибка в том, что оператор = предназначен для числового сравнения, а не общего равенства. Для проверки того, что список пуст, вы обычно используете функцию null?.
  • Кроме того, для оператора типа if ... then ... else if ... обычно используется cond, а не if.
  • Вам не нужно let* здесь; unstarred let будет делать. Фактически, я бы полностью отказался от привязок let для этой простой функции.
  • Вы действительно должны использовать обычные отступы на Лиспе и связать скобки.

Итак, ваша функция с этими изменениями:

(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))
1 голос
/ 12 марта 2012

Это более идиоматическая процедура 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

В качестве последнего примечания, комментария к стилю: в Схеме (и других LISP по этому вопросу) вы закрываете все скобки в одной строке, а не в отдельных. Вы знаете, это не фигурные скобки:)

0 голосов
/ 24 апреля 2013
(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' является встроенной процедурой, которую, я думаю, будет иметь большинство реализаций схемы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...