Conditionals and Conditional Functions

#drnseccondprog2#2503> Some banks pay different levels of interest for saving accounts. The more a customer deposits, the more the bank pays. In such arrangements, the interest rate depends on the <#2504#>interval<#2504#> into which the savings amount falls. To assist their bank clerks, banks deploy interest-rate functions. An interest function consumes the amount that a customer wishes to deposit and responds with the interest that the customer receives for this amount of money. Our interest rate function must determine which of several conditions holds for the input. We say that the function is a <#60704#><#2505#>CONDITIONAL FUNCTION<#2505#><#60704#>, and we formulate the definition of such functions using <#60705#><#2506#>CONDITIONAL EXPRESSIONS<#2506#><#60705#>. The general shape of a conditional expression is
<#2511#>(c<#2511#><#2512#>ond<#2512#>
  <#2513#>[<#2513#><#2514#>question<#2514#> <#2515#>answer]<#2515#> 
  <#2516#>...<#2516#> 
  <#2517#>[<#2517#><#2518#>question<#2518#> <#2519#>answer]<#2519#><#2520#>)<#2520#> 
<#2523#>or<#2523#>
<#2527#>(c<#2527#><#2528#>ond<#2528#>
  <#2529#>[<#2529#><#2530#>question<#2530#> <#2531#>answer]<#2531#> 
  <#2532#>...<#2532#> 
  <#2533#>[<#2533#><#2534#>else<#2534#> <#2535#>answer]<#2535#><#2536#>)<#2536#> 
The dots indicate that a <#60706#><#2540#>cond<#2540#>-expression<#60706#> may contain an arbitrary number of <#60707#><#2541#>cond<#2541#><#60707#>-lines. Each <#60708#><#2542#>cond<#2542#><#60708#>-line, also called a <#60709#><#2543#>cond<#2543#><#60709#>-clause, contains two expressions, called <#60710#><#2544#>CONDITION<#2544#><#60710#> and <#60711#><#2545#>ANSWER<#2545#><#60711#>. A <#2546#>condition<#2546#> is a conditional expression that involves the parameters; the answer is a Scheme expression that computes the result from the parameters and other data if the conditional expression holds. Conditional expressions are the most complicated form of expressions we have encountered and will encounter. It is therefore easy to make mistakes when we write them down. Compare the following two parenthesized expressions:
<#2553#>(c<#2553#><#2554#>ond<#2554#>
  <#2555#>[<#2555#><#2556#>(;SPMlt;<#2556#> <#2557#>n<#2557#> <#2558#>10)<#2558#> <#2559#>5.0]<#2559#> 
  <#2560#>[<#2560#><#2561#>(;SPMlt;<#2561#> <#2562#>n<#2562#> <#2563#>20)<#2563#> <#2564#>5]<#2564#> 
  <#2565#>[<#2565#><#2566#>(;SPMlt;<#2566#> <#2567#>n<#2567#> <#2568#>30)<#2568#> <#2569#>true<#2569#><#2570#>]<#2570#><#2571#>)<#2571#> 
<#2577#>(c<#2577#><#2578#>ond<#2578#>
  <#2579#>[<#2579#><#2580#>(;SPMlt;<#2580#> <#2581#>n<#2581#> <#2582#>10)<#2582#> <#2583#>30<#2583#> <#2584#>12]<#2584#> 
  <#2585#>[<#2585#><#2586#>(;SPMgt;<#2586#> <#2587#>n<#2587#> <#2588#>25)<#2588#> <#2589#>false<#2589#><#2590#>]<#2590#> 
  <#2591#>[<#2591#><#2592#>(;SPMgt;<#2592#> <#2593#>n<#2593#> <#2594#>20)<#2594#> <#2595#>0]<#2595#><#2596#>)<#2596#> 
The left one is a valid <#60714#><#2600#>cond<#2600#>-expression<#60714#> because each <#60715#><#2601#>cond<#2601#><#60715#>-line contains two expressions. In contrast, the right one is <#2602#>not<#2602#> a valid <#60716#><#2603#>cond<#2603#>-expression<#60716#>. Its first line contains three expressions instead of two. When Scheme evaluates a <#60717#><#2604#>cond<#2604#>-expression<#60717#>, it determines the value of each condition, one by one. A condition must evaluate to <#60718#><#2605#>true<#2605#><#60718#> or <#60719#><#2606#>false<#2606#><#60719#>. For the first condition that evaluates to <#60720#><#2607#>true<#2607#><#60720#>, Scheme evaluates the corresponding answer, and the value of the answer is the value of the entire <#60721#><#2608#>cond<#2608#>-expression<#60721#>. If the last condition is <#60722#><#2609#>else<#2609#><#60722#> and all other conditions fail, the answer for the <#60723#><#2610#>cond<#2610#><#60723#> is the value of the last answer expression. Here are two simple examples:
<#2619#>(c<#2619#><#2620#>ond<#2620#>
  <#2621#>[<#2621#><#2622#>(;SPMlt;=<#2622#> <#2623#>n<#2623#> <#2624#>1000)<#2624#> <#2625#>.040]<#2625#> 
  <#2626#>[<#2626#><#2627#>(;SPMlt;=<#2627#> <#2628#>n<#2628#> <#2629#>5000)<#2629#> <#2630#>.045]<#2630#> 
  <#2631#>[<#2631#><#2632#>(;SPMlt;=<#2632#> <#2633#>n<#2633#> <#2634#>10000)<#2634#> <#2635#>.055]<#2635#> 
  <#2636#>[<#2636#><#2637#>(;SPMgt;<#2637#> <#2638#>n<#2638#> <#2639#>10000)<#2639#> <#2640#>.060]<#2640#><#2641#>)<#2641#> 
<#2647#>(c<#2647#><#2648#>ond<#2648#>
  <#2649#>[<#2649#><#2650#>(;SPMlt;=<#2650#> <#2651#>n<#2651#> <#2652#>1000)<#2652#> <#2653#>.040]<#2653#> 
  <#2654#>[<#2654#><#2655#>(;SPMlt;=<#2655#> <#2656#>n<#2656#> <#2657#>5000)<#2657#> <#2658#>.045]<#2658#> 
  <#2659#>[<#2659#><#2660#>(;SPMlt;=<#2660#> <#2661#>n<#2661#> <#2662#>10000)<#2662#> <#2663#>.055]<#2663#> 
  <#2664#>[<#2664#><#2665#>else<#2665#> <#2666#>.060]<#2666#><#2667#>)<#2667#> 
If we replace <#60727#><#2671#>n<#2671#><#60727#> with <#60728#><#2672#>20000<#2672#><#60728#>, the first three conditions evaluate to <#60729#><#2673#>false<#2673#><#60729#> in both expressions. For the expression on the left the fourth condition, <#60730#><#2674#>(;SPMgt;<#2674#>\ <#2675#>20000<#2675#>\ <#2676#>10000)<#2676#><#60730#>, evaluates to <#60731#><#2677#>true<#2677#><#60731#> and therefore the answer is <#60732#><#2678#>0.60<#2678#><#60732#>. For the expression on the right, the <#60733#><#2679#>else<#2679#><#60733#> clause specifies what the result of the entire expression is. In contrast, if <#60734#><#2680#>n<#2680#><#60734#> is <#60735#><#2681#>10000<#2681#><#60735#>, the value of is <#60736#><#2682#>.055<#2682#><#60736#> because for both expressions, <#60737#><#2683#>(;SPMlt;=<#2683#>\ <#2684#>10000<#2684#>\ <#2685#>1000)<#2685#><#60737#> and <#60738#><#2686#>(;SPMlt;=<#2686#>\ <#2687#>10000<#2687#>\ <#2688#>5000)<#2688#><#60738#> evaluate to <#60739#><#2689#>false<#2689#><#60739#> and <#60740#><#2690#>(;SPMlt;=<#2690#>\ <#2691#>10000<#2691#>\ <#2692#>10000)<#2692#><#60740#> evaluates to <#60741#><#2693#>true<#2693#><#60741#>.
<#2696#>Exercise 4.3.1<#2696#> Decide which of the following two <#60742#><#2698#>cond<#2698#>-expression<#60742#>s is legal:
<#2703#>(c<#2703#><#2704#>ond<#2704#>
  <#2705#>[<#2705#><#2706#>(;SPMlt;<#2706#> <#2707#>n<#2707#> <#2708#>10)<#2708#> <#2709#>20]<#2709#> 
  <#2710#>[<#2710#><#2711#>(;SPMgt;<#2711#> <#2712#>n<#2712#> <#2713#>20)<#2713#> <#2714#>0]<#2714#> 
  <#2715#>[<#2715#><#2716#>else<#2716#> <#2717#>1]<#2717#><#2718#>)<#2718#> 
<#2724#>(c<#2724#><#2725#>ond<#2725#>
  <#2726#>[<#2726#><#2727#>(;SPMlt;<#2727#> <#2728#>n<#2728#> <#2729#>10)<#2729#> <#2730#>20]<#2730#> 
  <#2731#>[<#2731#><#2732#>(and<#2732#> <#2733#>(;SPMgt;<#2733#> <#2734#>n<#2734#> <#2735#>20)<#2735#> <#2736#>(;SPMlt;=<#2736#> <#2737#>n<#2737#> <#2738#>30))]<#2738#> 
  <#2739#>[<#2739#><#2740#>else<#2740#> <#2741#>1]<#2741#><#2742#>)<#2742#> 
Explain why the other one is not. Why is
<#2750#>(c<#2750#><#2751#>ond<#2751#> 
  <#2752#>[<#2752#><#2753#>(;SPMlt;<#2753#> <#2754#>n<#2754#> <#2755#>10)<#2755#> <#2756#>20]<#2756#> 
  <#2757#>[<#2757#><#2758#>*<#2758#> <#2759#>10<#2759#> <#2760#>n]<#2760#> 
  <#2761#>[<#2761#><#2762#>else<#2762#> <#2763#>555]<#2763#><#2764#>)<#2764#> 
not a valid <#60743#><#2768#>cond<#2768#>-expression<#60743#>?~ external Solution<#60744#><#60744#> <#2774#>Exercise 4.3.2<#2774#> What is the value of the above <#60745#><#2776#>cond<#2776#>-expression<#60745#>s for
(a) <#60746#><#2777#>n<#2777#>\ <#2778#>=<#2778#>\ <#2779#>500<#2779#><#60746#>, (b) <#60747#><#2780#>n<#2780#>\ <#2781#>=<#2781#>\ <#2782#>2800<#2782#><#60747#>, and (c) <#60748#><#2783#>n<#2783#>\ <#2784#>=<#2784#>\ <#2785#>15000<#2785#><#60748#>? external Solution<#60749#><#60749#> <#2791#>Exercise 4.3.3<#2791#> What is the value of
<#2797#>(c<#2797#><#2798#>ond<#2798#>
  <#2799#>[<#2799#><#2800#>(;SPMlt;=<#2800#> <#2801#>n<#2801#> <#2802#>1000)<#2802#> <#2803#>(*<#2803#> <#2804#>.040<#2804#> <#2805#>1000)]<#2805#> 
  <#2806#>[<#2806#><#2807#>(;SPMlt;=<#2807#> <#2808#>n<#2808#> <#2809#>5000)<#2809#> <#2810#>(+<#2810#> <#2811#>(*<#2811#> <#2812#>1000<#2812#> <#2813#>.040)<#2813#> 
                        <#2814#>(*<#2814#> <#2815#>(-<#2815#> <#2816#>n<#2816#> <#2817#>1000)<#2817#> <#2818#>.045))]<#2818#> 
  <#2819#>[<#2819#><#2820#>else<#2820#> <#2821#>(+<#2821#> <#2822#>(*<#2822#> <#2823#>1000<#2823#> <#2824#>.040)<#2824#> 
           <#2825#>(*<#2825#> <#2826#>4000<#2826#> <#2827#>.045)<#2827#> 
           <#2828#>(*<#2828#> <#2829#>(-<#2829#> <#2830#>n<#2830#> <#2831#>10000)<#2831#> <#2832#>.055))]<#2832#><#2833#>)<#2833#> 
for (a) <#60750#><#2837#>n<#2837#>\ <#2838#>=<#2838#>\ <#2839#>500<#2839#><#60750#>, (b) <#60751#><#2840#>n<#2840#>\ <#2841#>=<#2841#>\ <#2842#>2800<#2842#><#60751#>, and (c) <#60752#><#2843#>n<#2843#>\ <#2844#>=<#2844#>\ <#2845#>15000<#2845#><#60752#>? external Solution<#60753#><#60753#>
With the help of <#60754#><#2853#>cond<#2853#>-expression<#60754#>s, we can now define the interest rate function that we mentioned at the beginning of this section. Suppose the bank pays 4 for deposits of up to $1,000 (inclusive), 4.5 for deposits of up to $5,000 (inclusive), and 5 for deposits of more than $5,000. Clearly, the function consumes one number and produces one:
<#70719#>;; <#60755#><#2858#>interest-rate<#2858#> <#2859#>:<#2859#> <#2860#>number<#2860#> <#2861#><#2861#><#2862#>-;SPMgt;<#2862#><#2863#><#2863#> <#2864#>number<#2864#><#60755#><#70719#>
<#70720#>;; to determine the interest rate for the given <#60756#><#2865#>amount<#2865#><#60756#><#70720#> 
<#2866#>(define<#2866#> <#2867#>(interest-rate<#2867#> <#2868#>amount)<#2868#> <#2869#>...)<#2869#> 
Furthermore, the problem statement provides three examples:
  1. <#60757#><#2874#>(interest-rate<#2874#>\ <#2875#>1000)<#2875#>\ <#2876#>=<#2876#>\ <#2877#>.040<#2877#><#60757#>
  2. <#60758#><#2878#>(interest-rate<#2878#>\ <#2879#>5000)<#2879#>\ <#2880#>=<#2880#>\ <#2881#>.045<#2881#><#60758#>
  3. <#60759#><#2882#>(interest-rate<#2882#>\ <#2883#>8000)<#2883#>\ <#2884#>=<#2884#>\ <#2885#>.050<#2885#><#60759#>
The body of the function must be a <#60760#><#2887#>cond<#2887#>-expression<#60760#> that distinguishes the three cases mentioned in the problem statement. Here is a sketch:
  <#2892#>(c<#2892#><#2893#>ond<#2893#>
    <#2894#>[<#2894#><#2895#>(;SPMlt;=<#2895#> <#2896#>amount<#2896#> <#2897#>1000)<#2897#> <#2898#>...]<#2898#> 
    <#2899#>[<#2899#><#2900#>(;SPMlt;=<#2900#> <#2901#>amount<#2901#> <#2902#>5000)<#2902#> <#2903#>...]<#2903#> 
    <#2904#>[<#2904#><#2905#>(;SPMgt;<#2905#> <#2906#>amount<#2906#> <#2907#>5000)<#2907#> <#2908#>...]<#2908#><#2909#>)<#2909#> 
Using the examples and the outline of the <#60761#><#2913#>cond<#2913#>-expression<#60761#>, the answers are easy:
<#2919#>(d<#2919#><#2920#>efine<#2920#> <#2921#>(interest-rate<#2921#> <#2922#>amount)<#2922#>
  <#2923#>(c<#2923#><#2924#>ond<#2924#> 
    <#2925#>[<#2925#><#2926#>(;SPMlt;=<#2926#> <#2927#>amount<#2927#> <#2928#>1000)<#2928#> <#2929#>0.040]<#2929#> 
    <#2930#>[<#2930#><#2931#>(;SPMlt;=<#2931#> <#2932#>amount<#2932#> <#2933#>5000)<#2933#> <#2934#>0.045]<#2934#> 
    <#2935#>[<#2935#><#2936#>(;SPMgt;<#2936#> <#2937#>amount<#2937#> <#2938#>5000)<#2938#> <#2939#>0.050]<#2939#><#2940#>))<#2940#> 
Since we know that the function only requires three cases, we can also replace the last condition with <#60762#><#2944#>else<#2944#><#60762#>:
<#2949#>(d<#2949#><#2950#>efine<#2950#> <#2951#>(interest-rate<#2951#> <#2952#>amount)<#2952#>
  <#2953#>(c<#2953#><#2954#>ond<#2954#> 
    <#2955#>[<#2955#><#2956#>(;SPMlt;=<#2956#> <#2957#>amount<#2957#> <#2958#>1000)<#2958#> <#2959#>0.040]<#2959#> 
    <#2960#>[<#2960#><#2961#>(;SPMlt;=<#2961#> <#2962#>amount<#2962#> <#2963#>5000)<#2963#> <#2964#>0.045]<#2964#> 
    <#2965#>[<#2965#><#2966#>else<#2966#> <#2967#>0.050]<#2967#><#2968#>))<#2968#> 
external ~<#60763#>Neither form is preferable. For beginners, it might be better to spell all out all conditions. If they make a mistake, Scheme will signal a run-time error. If they use <#2973#>else<#2973#>, the function will produce the value of the <#2974#>else<#2974#>-clause, even though the conditions may be set up wrong.<#60763#> When we apply <#60764#><#2975#>interest-rate<#2975#><#60764#> to an amount, say <#60765#><#2976#>4000<#2976#><#60765#>, the calculation proceeds as usual. Scheme first copies the body of the function and replaces <#60766#><#2977#>amount<#2977#><#60766#> by <#60767#><#2978#>4000<#2978#><#60767#>:
  <#2983#>(interest-rate<#2983#> <#2984#>4000)<#2984#>
<#2985#>=<#2985#> <#2986#>(c<#2986#><#2987#>ond<#2987#> 
    <#2988#>[<#2988#><#2989#>(;SPMlt;=<#2989#> <#2990#>4000<#2990#> <#2991#>1000)<#2991#> <#2992#>0.040]<#2992#> 
    <#2993#>[<#2993#><#2994#>(;SPMlt;=<#2994#> <#2995#>4000<#2995#> <#2996#>5000)<#2996#> <#2997#>0.045]<#2997#> 
    <#2998#>[<#2998#><#2999#>else<#2999#> <#3000#>0.050]<#3000#><#3001#>)<#3001#> 
<#3002#>=<#3002#> <#3003#>0.045<#3003#> 
The first condition is <#60768#><#3007#>false<#3007#><#60768#> but the second one is <#60769#><#3008#>true<#3008#><#60769#>, so the result is <#60770#><#3009#>0.045<#3009#><#60770#> or 4.5. The evaluation would proceed in the same manner if we had used the variant of the function with <#60771#><#3010#>(;SPMgt;<#3010#>\ <#3011#>amount<#3011#><#3012#> <#3012#><#3013#>5000)<#3013#><#60771#> instead of <#60772#><#3014#>else<#3014#><#60772#>.