A few days ago, I offered an primarily technical example on why Scheme’s nested procedure are actually pretty great. While it’s true the technical application applies, and probably more so in the more difficult exercises, I wanted to discuss the organizational methodology too.
Let’s say you write code like this. It’s code for tax bracket eerily similar to real life. For our purposes though, it looks like a complete and utter mess.
(define (tax amount) (define total (cond ((<= amount 35000) (* amount .15)) ((and (> amount 35000) (<= amount 100000)) (+ (* 35000 .15) (* (- amount 35000 ) .25 ) ) ) ((> amount 100000) (+ (* 35000 .15) (* 65000 .25 ) (* .35 (- amount 100000) ) ) ) ) ) (if (> amount 50000) (+ total (* .05 (- amount 50000))) total ) )
This example goes like this: define the total as the result of the cond, where the cond will decide which bracket to use. Conceptually, it’s not really important to know how the tax is calculated to discuss organization. Plainly, this code is repetitive and obviously busy.
Using nested procedures though, we can clean it up. Since there are three brackets, let’s make three nested procedures. Granted, this may not look any simpler, but it is. That’s because the logic driving the calculations are abstracted away from the conditionals from which they originate. Indeed, this would definitely be better with some variables, but you can’t have everything.
(define (tax2 amount)
(define (bracket1)
(* amount .15)
)
(define (bracket2)
(+ (* 35000 .15) (* (- amount 35000 ) .25 ) )
)
(define (bracket3)
(+ (* 35000 .15) (* 65000 .25 ) (* .35 (- amount 100000) ) )
)
(define total
(cond
((<= amount 35000) (bracket1) )
((and (> amount 35000) (<= amount 100000)) (bracket2) )
((> amount 100000) (bracket3) )
)
)
(if (> amount 50000) (+ total (* .05 (- amount 50000))) total )
)
Notice that last if-statement though? It still has some messy junk in there that’s still doing calculations. You could easily trim part of that down. But there’s a problem with trimming it down completely. Notice its use of total? It was previously defined as the value returned from the cond above it. If I were to refer to it in a previously defined procedure-within-a-procedure, possibly called state-bracket, I would get an error stating that total doesn’t exist yet, and that’s true, it doesn’t. What could I do? I could pass it in as an argument!
Notice the change in the last if-statement and the addition of a new nested procedure.
(define (tax3 amount)
(define (bracket1)
(* amount .15)
)
(define (bracket2)
(+ (* 35000 .15) (* (- amount 35000 ) .25 ) )
)
(define (bracket3)
(+ (* 35000 .15) (* 65000 .25 ) (* .35 (- amount 100000) ) )
)
(define (state-bracket)
(+ total (* .05 (- amount 50000)))
)
(define total
(cond
((<= amount 35000) (bracket1) )
((and (> amount 35000) (<= amount 100000)) (bracket2) )
((> amount 100000) (bracket3) )
)
)
(if (> amount 50000) (state-bracket total) total )
)
This code is abstracted more than it was originally. That means it’s more flexible and likely easier to read at a glance. I will admit that though that are improvements to be made. For instance, the concurrent repeating of constants could be eliminated. Personally, I feel setting a define up so that it has a conditional value is a hack, but apparently that’s the best way.
And that’s all about logical organization and abstraction with the nested procedures Scheme offers.
Happy abstracting!






