2012-03-12 5 views
3

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

Вот мой код:

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

Я думаю, что есть что-то неправильно с параметрами. Я изучаю схему, и я не знаю, где проблема.

ответ

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)) 
+0

Чрезвычайно много, я ном со схемой: P – kentverger

+0

Почему вы называете это «PLT Scheme», если вы знаете, что веб-сайт предназначен для «Racket» ...? –

+0

Раньше это называлось «PLT Scheme». Я думал, что назвать его «Racket» может немного запутать. Но, по-видимому, это называлось «PLT Scheme», также сбивало с толку, плохо отредактировал мой ответ. –

1

Это более идиоматическая Схема процедуры для нахождения максимального значения в списке:

(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 

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

2

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

  • Ваша ошибка в том, что оператор = для числового сравнения, а не общее равенство. Для проверки того, что список пуст, вы обычно используете функцию null?.
  • Кроме того, для описания типа if ... then ... else if ... обычно используется cond, а не if.
  • Здесь не нужно let*; неармированный 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 -loop в императивных языках:

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)) 
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)))))) 

это предполагает, что «Макс» является процедура сборки, в котором я думаю, что большинство схема implementions будет.

Смежные вопросы