Domanda

Using DrRacket, on both linux and Mac OS, the following code gives this error

*: expects type <number> as 1st argument, given #<undefined>

but if I uncomment the (newline) at the beginning of the procedure definition, it works fine, yielding the expected value, 9.

#lang r5rs

(define (quadr x y)
        ;(newline)
        (define xx (* x x))
        (define yy (* y y))
        (define xxyy (* xx yy))
        (+ xx yy xxyy))

(display (quadr 1 2))
(newline)

Is this a bug in Racket's scheme interpreter, or is the language specified so that the nested invocations of (define ...) may happen out of order? If the latter is the case, where can I find the relevant bit of the language specification?

As an aside, I am very aware of the "let" construct and know that this is not the recommended way to define such a procedure. Still, I didn't expect this error.

È stato utile?

Soluzione

Here's the relevant link to the R5RS specification explaining the behavior of internal definitions. Notice that in section §5.2.2 is stated that:

... it must be possible to evaluate each <expression> of every internal definition in a <body> without assigning or referring to the value of any <variable> being defined.

In other words, you can't count on a correct behavior if you define values that depend on previously defined values within the same internal definition. Use let* for this:

(define (quadr x y)
  (let* ((xx   (* x x))
         (yy   (* y y))
         (xxyy (* xx yy)))
    (+ xx yy xxyy)))

Or a bit more verbose, using a couple of nested lets:

(define (quadr x y)
  (let ((xx (* x x))
        (yy (* y y)))
    (let ((xxyy (* xx yy)))
      (+ xx yy xxyy))))

It's very peculiar that inserting a (newline) causes the variable definition to work for this example, but when you're dealing with undefined behavior, anything can happen. As a side note, if I use #lang racket instead of #lang r5rs, the original code works for me without the extra (newline).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top