[previous] [up] [next]     [index]
Next: Boolean Expressions Up: Intermezzo 1 Syntax and Semantics Previous: The Meaning of Scheme

Errors

Parenthesized sentences may or may not belong to Scheme, depending on whether or not they are legal according to the grammar in figure [cross-reference]. If DrScheme verifies that a sentence does not belong to the language dubbed Beginning Student, it signals a SYNTAX ERROR. The remaining expressions are syntactically legal, but some of those may still pose problems for our evaluation rules. We say that such legal expressions contain LOGICAL ERRORS or RUN-TIME ERRORS. Consider the simplest example: (/ 1 0). We already know from mathematics that

displaymath71945

does not have a value. Clearly, since Scheme's calculations must be consistent with mathematics, it too must not equate (/ 1 0) with a value.

In general, if an expression is not a value and if the evaluation rules allow no further simplification, we say that an error occurred or that the function raises an error signal. Pragmatically this means that the evaluation stops immediately with an appropriate error message, such as ``/: divide by zero'' for division by zero.

For an example, consider the following evaluation:

  (+ (* 20 2) (/ 1 (- 10 10)))
= (+ 40 (/ 1 0)) 
= /: divide by zero 
The error eliminates the context (+ 40 ...) around (/ 1 0), which represents the remainder of the computation with respect to the division.

To understand how run-time errors are signaled, we must inspect the evaluation rules again. Consider the function

;; my-divide : number -> number
(define (my-divide n) 
  (cond 
    [(= n 0) 'inf] 
    [else (/ 1 n)])) 
Now suppose we apply my-divide to 0. Then the first step is:
  (my-divide 0)

= (cond [(= 0 0) 'inf] [else tex2html_wrap_inline71947 ])

It would obviously be wrong to say that the function signals the error ``/: divide by zero'' now, even though an evaluation of the underlined subexpression would demand it. After all, (= 0 0) is true and therefore the application has a proper result:
  (my-divide 0)

= (cond [(= 0 0) 'inf] [else tex2html_wrap_inline71947 ])

= (cond [true 'inf] [else tex2html_wrap_inline71947 ])

= 'inf

Fortunately, our laws of evaluation take care of these situations automatically. We just need to keep in mind when the laws apply. For example, in

(+ (* 20 2) (/ 20 2))
the addition cannot take place before the multiplication or division. Similarly, the underlined division in
(cond
  [(= 0 0) 'inf] 
  [else  tex2html_wrap_inline71947 ]) 
cannot be evaluated until the corresponding line is the first condition in the cond-expression.

As a rule of thumb, it is best to keep the following in mind:

Guideline on Expression Evaluation

Simplify the outermost (and left-most) subexpression that is ready for evaluation.

While this guideline is a simplification, it always explains Scheme's results.

In some cases, programmers also want to define functions that raise errors. Recall the checked version of area-of-disk from section [cross-reference]:

;; checked-area-of-disk : Scheme-value -> boolean
;; to compute the area of a disk with radius v, if v is a number 
(define (checked-area-of-disk v) 
  (cond 
    [(number? v) (area-of-disk v)] 
    [else (error 'checked-area-of-disk ``number expected'')])) 
If we were to apply checked-area-of-disk to a symbol, we would get the following evaluation:
  (- (checked-area-of-disk 'a)
     (checked-area-of-disk 10))

= (- (cond [(number? 'a) (area-of-disk 'a)] [else (error 'checked-area-of-disk ``number expected'')]) (checked-area-of-disk 10))

= (- (cond [false (area-of-disk 'a)] [else (error 'checked-area-of-disk ``number expected'')]) (checked-area-of-disk 10))

= (- (error 'checked-area-of-disk ``number expected'') (checked-area-of-disk 10))

= checked-area-of-disk : number expected

In other words, when we evaluate an the error expression, we proceed as if we had encountered a division by zero.


[previous] [up] [next]     [index]
Next: Boolean Expressions Up: Intermezzo 1 Syntax and Semantics Previous: The Meaning of Scheme

PLT