Función armónica del esquema

Is there a way to write this function using an if statement instead of cond? The following works as intended, but I was curious to see another option.

(define (harmonic-numbers n)
    (cond ((= n 1) 1)
       ((> n 1) (+ (/ 1 n)
       (harmonic-numbers(- n 1))))))

preguntado el 09 de septiembre de 13 a las 22:09

2 Respuestas

Por supuesto, un cond can be implemented as a series of nested ifs. Notice that you have a potential bug in your code, what happens if n es menor que 1?

(define (harmonic-numbers n)
  (if (= n 1)
      1
      (if (> n 1)
          (+ (/ 1 n) (harmonic-numbers (- n 1)))
          (error 'undefined))))

Depending on the Scheme interpreter in use, the if form might require you to always provide an "else" part for all conditions (which is why I signaled an error if n es menor que 1). Other interpreters are not as strict, and will happily allow you to write a one-armed condition:

(define (harmonic-numbers n)
  (if (= n 1)
      1
      (if (> n 1)
          (+ (/ 1 n) (harmonic-numbers (- n 1))))))

EDITAR

Now that we've established what happens if n is less than one, we can write a simpler version using if:

(define (harmonic-numbers n)
  (if (<= n 1)
      1
      (+ (/ 1 n) (harmonic-numbers (- n 1)))))

And here's the equivalent version using cond:

(define (harmonic-numbers n)
  (cond ((<= n 1) 1)
        (else (+ (/ 1 n) (harmonic-numbers (- n 1))))))

Respondido el 09 de Septiembre de 13 a las 22:09

Infinite recursion will result if n is less than 1 so I should change "(=" to "(<=". Thanks - John Friedrich

Not infinite recursion, your code will return #<void>, or false, or undefined if n is less than 1 (it depends on the interpreter). Look carefully at the last part of my answer, the function can be simplified once we realize that the conditions are mutually exclusive - a perfect fit for using if - Óscar López

Thank you, I understand both methods now. - John Friedrich

cond se llama un Derived conditional in the R6RS spec and is not essential syntax, like if is. It is not required as a primitive but can be define as a macro. Here's the definition of cond as defined in the R5RS spec, but it is compatible with current that is defined with syntax-case macros:

(define-syntax cond
  (syntax-rules (else =>)
    ((cond (else result1 result2 ...))
     (begin result1 result2 ...))
    ((cond (test => result))
     (let ((temp test))
       (if temp (result temp))))
    ((cond (test => result) clause1 clause2 ...)
     (let ((temp test))
       (if temp
           (result temp)
           (cond clause1 clause2 ...))))
    ((cond (test)) test)
    ((cond (test) clause1 clause2 ...)
     (let ((temp test))
       (if temp
           temp
           (cond clause1 clause2 ...))))
    ((cond (test result1 result2 ...))
     (if test (begin result1 result2 ...)))
    ((cond (test result1 result2 ...)
           clause1 clause2 ...)
     (if test
         (begin result1 result2 ...)
         (cond clause1 clause2 ...)))))

Respondido el 10 de Septiembre de 13 a las 00:09

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.