Pass a list as a parameter function?

I am trying to make a simple function in a schema that finds the largest number in a list.

Here is my code:

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

      

I am calling the function like this:

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

      

And the program will return this:

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

      

I think there is something wrong with the parameters. I am researching the circuit and I don't know where the problem is.

+3


source to share


4 answers


My tent here is Racket based (which is schematic based)

There are several problems with your program. One, =

compares numbers, not lists. Second, it ()

is a function that has nothing, not a list. To create an empty list, use either (list)

or '()

. Finally, it ((maximo (cdr lista) primero))

has an additional set of parentheses that cause the result to be executed (maximo (cdr lista) primero)

. However, the result (maximo (cdr lista) primero)

is a number.

I think you need something like this which will return 9

when you call(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)))))

      

You can also write it with fold , which is a little shorter:

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

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

      

+5


source


I have four points in your function:

  • Your error is because the operator =

    is for numerical comparison, not general equality. To check that a list is empty, you usually use a function null?

    .
  • Also, type expression is if ... then ... else if ...

    usually used cond

    instead of if

    .
  • You don't need to here let*

    ; unstable let

    . In fact, I will do without bindings let

    for this simple function.
  • You really need to use regular Lisp indentation and copy the parentheses.

So your function with these changes:

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

      

A more advanced way of writing this function is to use the fold-left

generic iterative list operator, which we can define as follows:



(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

matches this common for

-loop type in imperative languages:

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

      

Using the fold-left

second helper function as well máximo-de-dos-valores

, we now have:

(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


source


This is a more idiomatic Scheme procedure for finding the maximum value in a list:

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

      

Note that I have introduced a new procedure mi-maximo

to call a helper procedure maximo

that does all the work. For those cases where you have more than two conditions, it is better to use cond

a series of nested ones instead if

. Finally, it prefers to use empty?

or null?

for testing if the list is empty. Use the above procedures:

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

      

As a final note, a style comment: in Scheme (and other LISPs, for that matter), you close all the parentheses on one line, not on separate lines. They are not curly braces, you know :)

+1


source


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

      

this assumes that "max" is the build routine that I think most schema implementations will have.

0


source







All Articles