<#70835#>;; <#61646#><#7109#>area-of-disk<#7109#> <#7110#>:<#7110#> <#7111#>number<#7111#> <#7112#><#7112#><#7113#>-;SPMgt;<#7113#><#7114#><#7114#> <#7115#>number<#7115#><#61646#><#70835#> <#70836#>;; to compute the area of a disk with radius <#61647#><#7116#>r<#7116#><#61647#><#70836#> <#7117#>(d<#7117#><#7118#>efine<#7118#> <#7119#>(area-of-disk<#7119#> <#7120#>r)<#7120#> <#7121#>(*<#7121#> <#7122#>3.14<#7122#> <#7123#>(*<#7123#> <#7124#>r<#7124#> <#7125#>r)))<#7125#>Clearly, our friends may wish to use this function, especially for some of their geometry homework. Unfortunately, when our friends use this function, they may accidentally apply it to a symbol rather than a number. When that happens, the function stops with a whimsical and uninformative error message:
<#7133#>;SPMgt;<#7133#> <#7134#>(area-of-disk<#7134#> <#7135#>'<#7135#><#7136#>my-disk)<#7136#> <#7137#>*:<#7137#> <#7138#>expects<#7138#> <#7139#>type<#7139#> <#7140#>;SPMlt;number;SPMgt;<#7140#> <#7141#>as<#7141#> <#7142#>1st<#7142#> <#7143#>argument,<#7143#> <#7144#>given:<#7144#> <#7145#>'<#7145#><#7146#>my-disk<#7146#><#7147#>; ... <#7147#>Using predicates, we can do better. To prevent this kind of accident, we should define <#7151#>checked<#7151#> versions of our functions, when we wish to hand them to our friends. In general, a <#61648#><#7152#>CHECKED FUNCTION<#7152#><#61648#> inputs an arbitrary Scheme value: a number, a boolean, a symbol, or a structure. For all those values that are in the class of values for which the original function is defined, the checked version applies the latter; for all others, it signals an error. Concretely, <#61649#><#7153#>checked-area-of-disk<#7153#><#61649#> consumes an arbitrary Scheme value, uses <#61650#><#7154#>area-of-disk<#7154#><#61650#> to compute the area of the a disk if the input is a number, and stops with an error message otherwise. Based on the enumeration of Scheme's values, the template for a checked function is as follows:
<#70837#>;; <#61651#><#7159#>f<#7159#> <#7160#>:<#7160#> <#7161#>Scheme-value<#7161#> <#7162#><#7162#><#7163#>-;SPMgt;<#7163#><#7164#><#7164#> <#7165#>?<#7165#><#7166#>?<#7166#><#7167#>?<#7167#><#61651#><#70837#> <#7168#>(d<#7168#><#7169#>efine<#7169#> <#7170#>(f<#7170#> <#7171#>v)<#7171#> <#7172#>(c<#7172#><#7173#>ond<#7173#> <#7174#>[<#7174#><#7175#>(number?<#7175#> <#7176#>v)<#7176#> <#7177#>...]<#7177#> <#7178#>[<#7178#><#7179#>(boolean?<#7179#> <#7180#>v)<#7180#> <#7181#>...]<#7181#> <#7182#>[<#7182#><#7183#>(symbol?<#7183#> <#7184#>v)<#7184#> <#7185#>...]<#7185#> <#7186#>[<#7186#><#7187#>(struct?<#7187#> <#7188#>v)<#7188#> <#7189#>...]<#7189#><#7190#>))<#7190#>Each line corresponds to one possible class of input. If we need to distinguish among the structures, we expand the last line appropriately. The first clause is the only one where we can use <#61652#><#7194#>area-of-disk<#7194#><#61652#>. For the others, however, we must signal an error. In Scheme we use the operation <#61653#><#7195#>error<#7195#><#61653#> to do so. It consumes a symbol and a string, which is a sequence of keyboard characters enclosed in quotation marks (<#61654#><#7196#>``...''<#7196#><#61654#>). Here is an example:
<#7201#>(error<#7201#> <#7202#>'<#7202#><#7203#>checked-area-of-disk<#7203#> <#7204#>``number<#7204#> <#7205#>expected'')<#7205#>Hence, the full definition of <#61655#><#7209#>checked-area-of-disk<#7209#><#61655#> is:
<#7214#>(d<#7214#><#7215#>efine<#7215#> <#7216#>(checked-area-of-disk<#7216#> <#7217#>v)<#7217#> <#7218#>(c<#7218#><#7219#>ond<#7219#> <#7220#>[<#7220#><#7221#>(number?<#7221#> <#7222#>v)<#7222#> <#7223#>(area-of-disk<#7223#> <#7224#>v)]<#7224#> <#7225#>[<#7225#><#7226#>(boolean?<#7226#> <#7227#>v)<#7227#> <#7228#>(error<#7228#> <#7229#>'<#7229#><#7230#>checked-area-of-disk<#7230#> <#7231#>``number<#7231#> <#7232#>expected'')]<#7232#> <#7233#>[<#7233#><#7234#>(symbol?<#7234#> <#7235#>v)<#7235#> <#7236#>(error<#7236#> <#7237#>'<#7237#><#7238#>checked-area-of-disk<#7238#> <#7239#>``number<#7239#> <#7240#>expected'')]<#7240#> <#7241#>[<#7241#><#7242#>(struct?<#7242#> <#7243#>v)<#7243#> <#7244#>(error<#7244#> <#7245#>'<#7245#><#7246#>checked-area-of-disk<#7246#> <#7247#>``number<#7247#> <#7248#>expected'')]<#7248#><#7249#>))<#7249#>Using <#61656#><#7253#>else<#7253#><#61656#> we can greatly simplify the function:
<#70838#>;; <#61657#><#7258#>checked-area-of-disk<#7258#> <#7259#>:<#7259#> <#7260#>Scheme-value<#7260#> <#7261#><#7261#><#7262#>-;SPMgt;<#7262#><#7263#><#7263#> <#7264#>boolean<#7264#><#61657#><#70838#> <#70839#>;; to compute the area of a disk with radius <#61658#><#7265#>v<#7265#><#61658#>, <#70839#> <#70840#>;; if <#61659#><#7266#>v<#7266#><#61659#> is a number<#70840#> <#7267#>(d<#7267#><#7268#>efine<#7268#> <#7269#>(checked-area-of-disk<#7269#> <#7270#>v)<#7270#> <#7271#>(c<#7271#><#7272#>ond<#7272#> <#7273#>[<#7273#><#7274#>(number?<#7274#> <#7275#>v)<#7275#> <#7276#>(area-of-disk<#7276#> <#7277#>v)]<#7277#> <#7278#>[<#7278#><#7279#>else<#7279#> <#7280#>(error<#7280#> <#7281#>'<#7281#><#7282#>checked-area-of-disk<#7282#> <#7283#>``number<#7283#> <#7284#>expected'')]<#7284#><#7285#>))<#7285#>Of course, such a simplification may not always be possible and may require a re-ordering of the <#61660#><#7289#>cond<#7289#><#61660#>-clauses first.
<#7324#>(define-struct<#7324#> <#7325#>vec<#7325#> <#7326#>(x<#7326#> <#7327#>y))<#7327#>
A <#61670#><#7332#>speed vector<#7332#><#61670#> (<#7333#>vec<#7333#>) is a structure:Develop the function <#61674#><#7340#>checked-make-vec<#7340#><#61674#>, which should be understood as a checked version of the primitive operation <#61675#><#7341#>make-vec<#7341#><#61675#>. It ensures that the arguments to <#61676#><#7342#>make-vec<#7342#><#61676#> are positive numbers, and not just arbitrary numbers. In other words, <#61677#><#7343#>checked-make-vec<#7343#><#61677#> enforces our informal data definition.~ Solution<#61678#><#61678#>
<#70841#> <#61671#><#7334#>(make-vec<#7334#>\ <#7335#>x<#7335#>\ <#7336#>y)<#7336#><#61671#> <#70841#> where both <#61672#><#7337#>x<#7337#><#61672#> and <#61673#><#7338#>y<#7338#><#61673#> are positive numbers.