Errors

Parenthesized sentences may or may not belong to Scheme, depending on whether or not they are legal according to the grammar in figure~#figsynbeginner#8119>. If DrScheme verifies that a sentence does not belong to the language dubbed <#8120#>Beginning Student<#8120#>, it signals a <#8121#>syntax error<#8121#>. 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 <#8122#>semantic<#8122#> or <#61825#><#8123#>RUN-TIME<#8123#><#61825#> errors. Consider the simplest example: <#61826#><#8124#>(/<#8124#>\ <#8125#>1<#8125#>\ <#8126#>0)<#8126#><#61826#>. We already know from mathematics that

#displaymath72874#

does not have a value. Clearly, since Scheme's calculations must be consistent with mathematics, it too must not equate <#61827#><#8129#>(/<#8129#>\ <#8130#>1<#8130#>\ <#8131#>0)<#8131#><#61827#> 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 <#61828#><#8132#>``/<#8132#><#8133#>:<#8133#>\ <#8134#>divide<#8134#>\ <#8135#>by<#8135#>\ <#8136#>zero''<#8136#><#61828#> for division by zero. For example, the evaluation of

  <#8141#>(+<#8141#> <#8142#>(*<#8142#> <#8143#>20<#8143#> <#8144#>2)<#8144#> <#8145#>(/<#8145#> <#8146#>1<#8146#> <#8147#>(-<#8147#> <#8148#>10<#8148#> <#8149#>10)))<#8149#>
proceeds as follows:
  <#8157#>(+<#8157#> <#8158#>(*<#8158#> <#8159#>20<#8159#> <#8160#>2)<#8160#> <#8161#>(/<#8161#> <#8162#>1<#8162#> <#8163#>(-<#8163#> <#8164#>10<#8164#> <#8165#>10)))<#8165#>
<#8166#>=<#8166#> <#8167#>(+<#8167#> <#8168#>40<#8168#> <#8169#>(/<#8169#> <#8170#>1<#8170#> <#8171#>0))<#8171#> 
<#8172#>=<#8172#> <#8173#>/:<#8173#> <#8174#>divide<#8174#> <#8175#>by<#8175#> <#8176#>zero<#8176#> 
In particular, the error eliminates the context <#61829#><#8180#>(+<#8180#>\ <#8181#>40<#8181#>\ <#8182#>...)<#8182#><#61829#> around <#61830#><#8183#>(/<#8183#>\ <#8184#>1<#8184#>\ <#8185#>0)<#8185#><#61830#>, 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
<#70885#>;; <#61831#><#8190#>my-divide<#8190#> <#8191#>:<#8191#> <#8192#>number<#8192#> <#8193#><#8193#><#8194#>-;SPMgt;<#8194#><#8195#><#8195#> <#8196#>number<#8196#><#61831#><#70885#>
<#8197#>(d<#8197#><#8198#>efine<#8198#> <#8199#>(my-divide<#8199#> <#8200#>n)<#8200#> 
  <#8201#>(c<#8201#><#8202#>ond<#8202#> 
    <#8203#>[<#8203#><#8204#>(=<#8204#> <#8205#>n<#8205#> <#8206#>0)<#8206#> <#8207#>'<#8207#><#8208#>inf]<#8208#> 
    <#8209#>[<#8209#><#8210#>else<#8210#> <#8211#>(/<#8211#> <#8212#>1<#8212#> <#8213#>n)]<#8213#><#8214#>))<#8214#> 
Now suppose we apply <#61832#><#8218#>my-divide<#8218#><#61832#> to <#61833#><#8219#>0<#8219#><#61833#>. Then the first step is:
  <#8224#>(my-divide<#8224#> <#8225#>0)<#8225#>
<#8226#>=<#8226#> <#8227#>(c<#8227#><#8228#>ond<#8228#> 
    <#8229#>[<#8229#><#8230#>(=<#8230#> <#8231#>0<#8231#> <#8232#>0)<#8232#> <#8233#>'<#8233#><#8234#>inf]<#8234#> 
    <#8235#>[<#8235#><#8236#>else<#8236#> <#72327#>#tex2html_wrap_inline72876#<#72327#><#8240#>]<#8240#><#8241#>)<#8241#> 
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, <#61835#><#8245#>(=<#8245#>\ <#8246#>0<#8246#>\ <#8247#>0)<#8247#><#61835#> is <#61836#><#8248#>true<#8248#><#61836#> and therefore the application has a proper result:
  <#8253#>(my-divide<#8253#> <#8254#>0)<#8254#>
<#8255#>=<#8255#> <#8256#>(c<#8256#><#8257#>ond<#8257#> 
    <#8258#>[<#8258#><#8259#>(=<#8259#> <#8260#>0<#8260#> <#8261#>0)<#8261#> <#8262#>'<#8262#><#8263#>inf]<#8263#> 
    <#8264#>[<#8264#><#8265#>else<#8265#> <#72328#>#tex2html_wrap_inline72878#<#72328#><#8269#>]<#8269#><#8270#>)<#8270#> 
<#8271#>=<#8271#> <#8272#>(c<#8272#><#8273#>ond<#8273#> 
    <#8274#>[<#8274#><#8275#>true<#8275#> <#8276#>'<#8276#><#8277#>inf]<#8277#> 
    <#8278#>[<#8278#><#8279#>else<#8279#> <#72329#>#tex2html_wrap_inline72880#<#72329#><#8283#>]<#8283#><#8284#>)<#8284#> 
<#8285#>=<#8285#> <#8286#>'<#8286#><#8287#>inf<#8287#> 
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
<#8295#>(+<#8295#> <#8296#>(*<#8296#> <#8297#>20<#8297#> <#8298#>2)<#8298#> <#8299#>(/<#8299#> <#8300#>20<#8300#> <#8301#>2))<#8301#>
the addition cannot take place before the multiplication or division. Similarly, the underlined division in the <#61839#><#8305#>cond<#8305#>-expression<#61839#>
<#8310#>(c<#8310#><#8311#>ond<#8311#>
  <#8312#>[<#8312#><#8313#>(=<#8313#> <#8314#>0<#8314#> <#8315#>0)<#8315#> <#8316#>'<#8316#><#8317#>inf]<#8317#> 
  <#8318#>[<#8318#><#8319#>else<#8319#> <#72330#>#tex2html_wrap_inline72882#<#72330#><#8323#>]<#8323#><#8324#>)<#8324#> 
cannot be evaluated until the corresponding line is the first condition in the <#61841#><#8328#>cond<#8328#>-expression<#61841#>. As a rule of thumb, it is best to keep the following in mind: rawhtml16 Guideline on Expression Evaluation rawhtml17 Evaluate the outermost and leftmost subexpressions first. rawhtml18 While this guideline is an oversimplification, it always explains Scheme's results. In some cases, programmers also want to define functions that raise errors. Recall the checked version of <#61842#><#8329#>area-of-disk<#8329#><#61842#> from section~#secrecords#8330>:
<#70890#>;; <#61843#><#8335#>checked-area-of-disk<#8335#> <#8336#>:<#8336#> <#8337#>Scheme-value<#8337#> <#8338#><#8338#><#8339#>-;SPMgt;<#8339#><#8340#><#8340#> <#8341#>boolean<#8341#><#61843#><#70890#>
<#70891#>;; to compute the area of a disk with radius <#61844#><#8342#>v<#8342#><#61844#>, if <#61845#><#8343#>v<#8343#><#61845#> is a number<#70891#> 
<#8344#>(d<#8344#><#8345#>efine<#8345#> <#8346#>(checked-area-of-disk<#8346#> <#8347#>v)<#8347#> 
  <#8348#>(c<#8348#><#8349#>ond<#8349#> 
    <#8350#>[<#8350#><#8351#>(number?<#8351#> <#8352#>v)<#8352#> <#8353#>(area-of-disk<#8353#> <#8354#>v)]<#8354#> 
    <#8355#>[<#8355#><#8356#>else<#8356#> <#8357#>(error<#8357#> <#8358#>'<#8358#><#8359#>checked-area-of-disk<#8359#> <#8360#>``number<#8360#> <#8361#>expected'')]<#8361#><#8362#>))<#8362#> 
If we were to apply <#61846#><#8366#>checked-area-of-disk<#8366#><#61846#> to a symbol, we would get the following evaluation:
  <#8371#>(-<#8371#> <#8372#>(checked-area-of-disk<#8372#> <#8373#>'<#8373#><#8374#>a)<#8374#>
     <#8375#>(checked-area-of-disk<#8375#> <#8376#>10))<#8376#> 
<#8377#>=<#8377#> <#8378#>(-<#8378#> <#8379#>(c<#8379#><#8380#>ond<#8380#> 
       <#8381#>[<#8381#><#8382#>(number?<#8382#> <#8383#>'<#8383#><#8384#>a)<#8384#> <#8385#>(area-of-disk<#8385#> <#8386#>'<#8386#><#8387#>a)]<#8387#> 
       <#8388#>[<#8388#><#8389#>else<#8389#> <#8390#>(error<#8390#> <#8391#>'<#8391#><#8392#>checked-area-of-disk<#8392#> <#8393#>``number<#8393#> <#8394#>expected'')]<#8394#><#8395#>)<#8395#> 
     <#8396#>(checked-area-of-disk<#8396#> <#8397#>10))<#8397#> 
<#8398#>=<#8398#> <#8399#>(-<#8399#> <#8400#>(c<#8400#><#8401#>ond<#8401#> 
       <#8402#>[<#8402#><#8403#>false<#8403#> <#8404#>(area-of-disk<#8404#> <#8405#>'<#8405#><#8406#>a)]<#8406#>   
       <#8407#>[<#8407#><#8408#>else<#8408#> <#8409#>(error<#8409#> <#8410#>'<#8410#><#8411#>checked-area-of-disk<#8411#> <#8412#>``number<#8412#> <#8413#>expected'')]<#8413#><#8414#>)<#8414#> 
     <#8415#>(checked-area-of-disk<#8415#> <#8416#>10))<#8416#> 
<#8417#>=<#8417#> <#8418#>(-<#8418#> <#8419#>(error<#8419#> <#8420#>'<#8420#><#8421#>checked-area-of-disk<#8421#> <#8422#>``number<#8422#> <#8423#>expected'')<#8423#> 
     <#8424#>(checked-area-of-disk<#8424#> <#8425#>10))<#8425#> 
<#8426#>=<#8426#> <#8427#>checked-area-of-disk<#8427#> <#8428#>:<#8428#> <#8429#>number<#8429#> <#8430#>expected<#8430#> 
In other words, when we evaluate an the <#61847#><#8434#>error<#8434#><#61847#> expression, we proceed as if we had encountered a division by zero.