<#71628#>;; <#67553#><#40902#>sum<#40902#> <#40903#>:<#40903#> <#40904#>(listof<#40904#> <#40905#>number)<#40905#> <#40906#><#40906#><#40907#>-;SPMgt;<#40907#><#40908#><#40908#> <#40909#>number<#40909#><#67553#><#71628#> <#71629#>;; to compute the sum of the numbers on <#67554#><#40910#>alon<#40910#><#67554#><#71629#> <#40911#>;; structural recursion <#40911#> <#40912#>(d<#40912#><#40913#>efine<#40913#> <#40914#>(sum<#40914#> <#40915#>alon)<#40915#> <#40916#>(c<#40916#><#40917#>ond<#40917#> <#40918#>[<#40918#><#40919#>(empty?<#40919#> <#40920#>alon)<#40920#> <#40921#>0]<#40921#> <#40922#>[<#40922#><#40923#>else<#40923#> <#40924#>(+<#40924#> <#40925#>(first<#40925#> <#40926#>alon)<#40926#> <#40927#>(sum<#40927#> <#40928#>(rest<#40928#> <#40929#>alon)))]<#40929#><#40930#>))<#40930#>Here is the first step toward an accumulator version:
<#71630#>;; <#67555#><#40938#>sum<#40938#> <#40939#>:<#40939#> <#40940#>(listof<#40940#> <#40941#>number)<#40941#> <#40942#><#40942#><#40943#>-;SPMgt;<#40943#><#40944#><#40944#> <#40945#>number<#40945#><#67555#><#71630#> <#71631#>;; to compute the sum of the numbers on <#67556#><#40946#>alon0<#40946#><#67556#><#71631#> <#40947#>(d<#40947#><#40948#>efine<#40948#> <#40949#>(sum<#40949#> <#40950#>alon0)<#40950#> <#40951#>(l<#40951#><#40952#>ocal<#40952#> <#40953#>(<#40953#><#71632#>;; <#67557#><#40954#>accumulator<#40954#><#67557#> ...<#71632#> <#40955#>(d<#40955#><#40956#>efine<#40956#> <#40957#>(sum-a<#40957#> <#40958#>alon<#40958#> <#40959#>accumulator)<#40959#> <#40960#>(c<#40960#><#40961#>ond<#40961#> <#40962#>[<#40962#><#40963#>(empty?<#40963#> <#40964#>alon)<#40964#> <#40965#>...]<#40965#> <#40966#>[<#40966#><#40967#>e<#40967#><#40968#>lse<#40968#> <#40969#>...<#40969#> <#40970#>(sum-a<#40970#> <#40971#>(rest<#40971#> <#40972#>alon)<#40972#>As suggested by our first step, we have put the template for <#67559#><#40986#>sum-a<#40986#><#67559#> into a <#67560#><#40987#>local<#40987#><#67560#> definition, added an accumulator parameter, and renamed <#67561#><#40988#>sum<#40988#><#67561#>'s parameter. Our goal is to develop an accumulator invariant for <#67562#><#40989#>sum<#40989#><#67562#>. To do so, we must consider how <#67563#><#40990#>sum<#40990#><#67563#> proceeds and what the goal of the process is. Like <#67564#><#40991#>rev<#40991#><#67564#>, <#67565#><#40992#>sum-a<#40992#><#67565#> processes the numbers on the list one by one. The goal is to add up these numbers. This suggests that <#67566#><#40993#>accumulator<#40993#><#67566#> represent the sum of the numbers <#40994#>seen so far<#40994#>:#tex2html_wrap74008#<#40976#>)<#40976#> <#40977#>...<#40977#> <#40978#>]<#40978#><#40979#>)))<#40979#> <#40980#>(sum-a<#40980#> <#40981#>alon0<#40981#> <#40982#>...)))<#40982#>
<#40999#>..<#40999#><#41000#>.<#41000#> <#41001#>(l<#41001#><#41002#>ocal<#41002#> <#41003#>(<#41003#><#71633#>;; <#67567#><#41004#>accumulator<#41004#><#67567#> is the sum of the numbers that preceded<#71633#> <#71634#>;; those in <#67568#><#41005#>alon<#41005#><#67568#> on <#67569#><#41006#>alon0<#41006#><#67569#><#71634#> <#41007#>(d<#41007#><#41008#>efine<#41008#> <#41009#>(sum-a<#41009#> <#41010#>alon<#41010#> <#41011#>accumulator)<#41011#> <#41012#>(c<#41012#><#41013#>ond<#41013#> <#41014#>[<#41014#><#41015#>(empty?<#41015#> <#41016#>alon)<#41016#> <#41017#>...]<#41017#> <#41018#>[<#41018#><#41019#>e<#41019#><#41020#>lse<#41020#> <#41021#>...<#41021#> <#41022#>(sum-a<#41022#> <#41023#>(rest<#41023#> <#41024#>alon)<#41024#> <#41025#>(+<#41025#> <#41026#>(first<#41026#> <#41027#>alon)<#41027#> <#41028#>accumulator))<#41028#> <#41029#>...<#41029#> <#41030#>]<#41030#><#41031#>)))<#41031#> <#41032#>(sum-a<#41032#> <#41033#>alon0<#41033#> <#41034#>0)))<#41034#>When we apply <#67570#><#41038#>sum-a<#41038#><#67570#> we must use <#67571#><#41039#>0<#41039#><#67571#> as the value of <#67572#><#41040#>accumulator<#41040#><#67572#>, because it hasn't processed any of the numbers on <#67573#><#41041#>alon<#41041#><#67573#> yet. For the second clause, we must add <#67574#><#41042#>(first<#41042#>\ <#41043#>alon)<#41043#><#67574#> to <#67575#><#41044#>accumulator<#41044#><#67575#> so that the invariant holds again for the function application. Given a precise invariant, the rest is straightforward again. If <#67576#><#41045#>alon<#41045#><#67576#> is <#67577#><#41046#>empty<#41046#><#67577#>, <#67578#><#41047#>sum-a<#41047#><#67578#> returns <#67579#><#41048#>accumulator<#41048#><#67579#> because it represents the sum of all numbers on <#67580#><#41049#>alon<#41049#><#67580#> now. Figure~#figaccumulatorstyle#41050>
<#71635#>;; <#67582#><#41056#>sum<#41056#> <#41057#>:<#41057#> <#41058#>(listof<#41058#> <#41059#>number)<#41059#> <#41060#><#41060#><#41061#>-;SPMgt;<#41061#><#41062#><#41062#> <#41063#>number<#41063#><#67582#><#71635#> <#71636#>;; to compute the sum of the numbers on <#67583#><#41064#>alon0<#41064#><#67583#><#71636#> <#41065#>(d<#41065#><#41066#>efine<#41066#> <#41067#>(sum<#41067#> <#41068#>alon0)<#41068#> <#41069#>(l<#41069#><#41070#>ocal<#41070#> <#41071#>(<#41071#><#71637#>;; <#67584#><#41072#>accumulator<#41072#><#67584#> is the sum of the numbers that preceded<#71637#> <#71638#>;; those in <#67585#><#41073#>alon<#41073#><#67585#> on <#67586#><#41074#>alon0<#41074#><#67586#><#71638#> <#41075#>(d<#41075#><#41076#>efine<#41076#> <#41077#>(sum-a<#41077#> <#41078#>alon<#41078#> <#41079#>accumulator)<#41079#> <#41080#>(c<#41080#><#41081#>ond<#41081#> <#41082#>[<#41082#><#41083#>(empty?<#41083#> <#41084#>alon)<#41084#> <#41085#>accumulator]<#41085#> <#41086#>[<#41086#><#41087#>else<#41087#> <#41088#>(sum-a<#41088#> <#41089#>(rest<#41089#> <#41090#>alon)<#41090#> <#41091#>(+<#41091#> <#41092#>(first<#41092#> <#41093#>alon)<#41093#> <#41094#>accumulator))]<#41094#><#41095#>)))<#41095#> <#41096#>(sum-a<#41096#> <#41097#>alon0<#41097#> <#41098#>0)))<#41098#>
<#71639#>;; <#67587#><#41106#>!<#41106#> <#41107#>:<#41107#> <#41108#>N<#41108#> <#41109#><#41109#><#41110#>-;SPMgt;<#41110#><#41111#><#41111#> <#41112#>N<#41112#><#67587#><#71639#> <#41113#>;; to compute<#41150#>Figure: Some simple accumulator-style functions<#41150#>#tex2html_wrap_inline73972#<#41113#> <#41114#>(d<#41114#><#41115#>efine<#41115#> <#41116#>(!<#41116#> <#41117#>n0)<#41117#> <#41118#>(l<#41118#><#41119#>ocal<#41119#> <#41120#>(<#41120#><#71640#>;; <#67588#><#41121#>accumulator<#41121#><#67588#> is the product of all natural numbers in [<#67589#><#41122#>n0<#41122#><#67589#>, <#67590#><#41123#>n<#41123#><#67590#>)<#71640#> <#41124#>(d<#41124#><#41125#>efine<#41125#> <#41126#>(!-a<#41126#> <#41127#>n<#41127#> <#41128#>accumulator)<#41128#> <#41129#>(c<#41129#><#41130#>ond<#41130#> <#41131#>[<#41131#><#41132#>(zero?<#41132#> <#41133#>n)<#41133#> <#41134#>accumulator]<#41134#> <#41135#>[<#41135#><#41136#>else<#41136#> <#41137#>(!-a<#41137#> <#41138#>(sub1<#41138#> <#41139#>n)<#41139#> <#41140#>(*<#41140#> <#41141#>n<#41141#> <#41142#>accumulator))]<#41142#><#41143#>)))<#41143#> <#41144#>(!-a<#41144#> <#41145#>n0<#41145#> <#41146#>1)))<#41146#>
<#41157#>(sum<#41157#> <#41158#>(list<#41158#> <#41159#>10.23<#41159#> <#41160#>4.50<#41160#> <#41161#>5.27))<#41161#> <#41162#>=<#41162#> <#41163#>(+<#41163#> <#41164#>10.23<#41164#> <#41165#>(sum<#41165#> <#41166#>(list<#41166#> <#41167#>4.50<#41167#> <#41168#>5.27)))<#41168#> <#41169#>=<#41169#> <#41170#>(+<#41170#> <#41171#>10.23<#41171#> <#41172#>(+<#41172#> <#41173#>4.50<#41173#> <#41174#>(sum<#41174#> <#41175#>(list<#41175#> <#41176#>5.27))))<#41176#> <#41177#>=<#41177#> <#41178#>(+<#41178#> <#41179#>10.23<#41179#> <#41180#>(+<#41180#> <#41181#>4.50<#41181#> <#41182#>(+<#41182#> <#41183#>5.27<#41183#> <#41184#>(sum<#41184#> <#41185#>empty))))<#41185#> <#41186#>=<#41186#> <#41187#>(+<#41187#> <#41188#>10.23<#41188#> <#41189#>(+<#41189#> <#41190#>4.50<#41190#> <#41191#>(+<#41191#> <#41192#>5.27<#41192#> <#41193#>0)))<#41193#> <#41194#>=<#41194#> <#41195#>(+<#41195#> <#41196#>10.23<#41196#> <#41197#>(+<#41197#> <#41198#>4.50<#41198#> <#41199#>5.27))<#41199#> <#41200#>=<#41200#> <#41201#>(+<#41201#> <#41202#>10.23<#41202#> <#41203#>9.77)<#41203#> <#41204#>=<#41204#> <#41205#>20.0<#41205#>
<#41211#>(sum<#41211#> <#41212#>(list<#41212#> <#41213#>10.23<#41213#> <#41214#>4.50<#41214#> <#41215#>5.27))<#41215#> <#41216#>=<#41216#> <#41217#>(sum-a<#41217#> <#41218#>(list<#41218#> <#41219#>10.23<#41219#> <#41220#>4.50<#41220#> <#41221#>5.27)<#41221#> <#41222#>0)<#41222#> <#41223#>=<#41223#> <#41224#>(sum-a<#41224#> <#41225#>(list<#41225#> <#41226#>4.50<#41226#> <#41227#>5.27)<#41227#> <#41228#>10.23)<#41228#> <#41229#>=<#41229#> <#41230#>(sum-a<#41230#> <#41231#>(list<#41231#> <#41232#>5.27)<#41232#> <#41233#>14.73)<#41233#> <#41234#>=<#41234#> <#41235#>(sum-a<#41235#> <#41236#>empty<#41236#> <#41237#>20.0)<#41237#> <#41238#>=<#41238#> <#41239#>20.0<#41239#>On the left side, we see how the plain recursive function descends the list of numbers all the way to the end and sets up addition operations on the way. On the right side, we see how the accumulator-style version adds up the numbers as it goes. Furthermore, we see that for each application of <#67592#><#41243#>sum-a<#41243#><#67592#> the invariant holds with respect to the application of <#67593#><#41244#>sum<#41244#><#67593#>. When <#67594#><#41245#>sum-a<#41245#><#67594#> is finally applied to <#67595#><#41246#>empty<#41246#><#67595#>, the accumulator is the final result, and <#67596#><#41247#>sum-a<#41247#><#67596#> returns it.
<#41257#>(d<#41257#><#41258#>efine<#41258#> <#41259#>(g-series<#41259#> <#41260#>n)<#41260#> <#41261#>(c<#41261#><#41262#>ond<#41262#> <#41263#>[<#41263#><#41264#>(zero?<#41264#> <#41265#>n)<#41265#> <#41266#>empty]<#41266#> <#41267#>[<#41267#><#41268#>else<#41268#> <#41269#>(cons<#41269#> <#41270#>(expt<#41270#> <#41271#>-0.99<#41271#> <#41272#>n)<#41272#> <#41273#>(g-series<#41273#> <#41274#>(sub1<#41274#> <#41275#>n)))]<#41275#><#41276#>))<#41276#>Applying <#67598#><#41280#>g-series<#41280#><#67598#> to a natural number produces the beginning of a decreasing geometric series (see section~#secseqsfunc#41281>
<#41286#>(sum<#41286#> <#41287#>(g-series<#41287#> <#41288#>1000))<#41288#>with both the original version of <#67599#><#41292#>sum<#41292#><#67599#> as well as its accumulator-style version. Then evaluate
<#41297#>(*<#41297#> <#41298#>10e15<#41298#> <#41299#>(sum<#41299#> <#41300#>(g-series<#41300#> <#41301#>1000)))<#41301#>which proves that, depending on the context, the difference can be arbitrarily large.~ Solution<#67600#><#67600#>
<#71641#>;; <#67601#><#41317#>!<#41317#> <#41318#>:<#41318#> <#41319#>N<#41319#> <#41320#><#41320#><#41321#>-;SPMgt;<#41321#><#41322#><#41322#> <#41323#>N<#41323#><#67601#><#71641#> <#41324#>;; to computeWhile <#67602#><#41347#>relative-2-absolute<#41347#><#67602#> and <#67603#><#41348#>reverse<#41348#><#67603#> processed lists, the factorial function works on natural numbers. Its template is that for <#67604#><#41349#>N<#41349#><#67604#>-processing functions. We proceed as before by creating a <#67605#><#41350#>local<#41350#><#67605#> definition of <#67606#><#41351#>!<#41351#><#67606#>:#tex2html_wrap_inline73974#<#41324#> <#41325#>;; structural recursion <#41325#> <#41326#>(d<#41326#><#41327#>efine<#41327#> <#41328#>(!<#41328#> <#41329#>n)<#41329#> <#41330#>(c<#41330#><#41331#>ond<#41331#> <#41332#>[<#41332#><#41333#>(zero?<#41333#> <#41334#>n)<#41334#> <#41335#>1]<#41335#> <#41336#>[<#41336#><#41337#>else<#41337#> <#41338#>(*<#41338#> <#41339#>n<#41339#> <#41340#>(!<#41340#> <#41341#>(sub1<#41341#> <#41342#>n)))]<#41342#><#41343#>))<#41343#>
<#71642#>;; <#67607#><#41356#>!<#41356#> <#41357#>:<#41357#> <#41358#>N<#41358#> <#41359#><#41359#><#41360#>-;SPMgt;<#41360#><#41361#><#41361#> <#41362#>N<#41362#><#67607#><#71642#> <#41363#>;; to computeThis sketch suggests that if <#67610#><#41400#>!<#41400#><#67610#> is applied to the natural number n, <#67611#><#41401#>!-a<#41401#><#67611#> processes n, then n-1, n-2, and so on until it reaches <#67612#><#41402#>0<#41402#><#67612#>. Since the goal is to multiply these numbers, the accumulator should be the product of all those numbers that <#67613#><#41403#>!-a<#41403#><#67613#> has encountered:#tex2html_wrap_inline73976#<#41363#> <#41364#>(d<#41364#><#41365#>efine<#41365#> <#41366#>(!<#41366#> <#41367#>n0)<#41367#> <#41368#>(l<#41368#><#41369#>ocal<#41369#> <#41370#>(<#41370#><#71643#>;; <#67608#><#41371#>accumulator<#41371#><#67608#> ...<#71643#> <#41372#>(d<#41372#><#41373#>efine<#41373#> <#41374#>(!-a<#41374#> <#41375#>n<#41375#> <#41376#>accumulator)<#41376#> <#41377#>(c<#41377#><#41378#>ond<#41378#> <#41379#>[<#41379#><#41380#>(zero?<#41380#> <#41381#>n)<#41381#> <#41382#>...]<#41382#> <#41383#>[<#41383#><#41384#>e<#41384#><#41385#>lse<#41385#> <#41386#>...<#41386#> <#41387#>(!-a<#41387#> <#41388#>(sub1<#41388#> <#41389#>n)<#41389#> #tex2html_wrap74010#<#41391#>)<#41391#> <#41392#>...]<#41392#><#41393#>)))<#41393#> <#41394#>(!-a<#41394#> <#41395#>n0<#41395#> <#41396#>...)))<#41396#>
<#41408#>..<#41408#><#41409#>.<#41409#> <#41410#>(l<#41410#><#41411#>ocal<#41411#> <#41412#>(<#41412#><#71644#>;; <#67614#><#41413#>accumulator<#41413#><#67614#> is the product of all natural numbers between<#71644#> <#71645#>;; <#67615#><#41414#>n0<#41414#><#67615#> (inclusive) and <#67616#><#41415#>n<#41415#><#67616#> (exclusive)<#71645#> <#41416#>(d<#41416#><#41417#>efine<#41417#> <#41418#>(!-a<#41418#> <#41419#>n<#41419#> <#41420#>accumulator)<#41420#> <#41421#>(c<#41421#><#41422#>ond<#41422#> <#41423#>[<#41423#><#41424#>(zero?<#41424#> <#41425#>n)<#41425#> <#41426#>...]<#41426#> <#41427#>[<#41427#><#41428#>e<#41428#><#41429#>lse<#41429#> <#41430#>...<#41430#> <#41431#>(!-a<#41431#> <#41432#>(sub1<#41432#> <#41433#>n)<#41433#> <#41434#>(*<#41434#> <#41435#>n<#41435#> <#41436#>accumulator))<#41436#> <#41437#>...]<#41437#><#41438#>)))<#41438#> <#41439#>(!-a<#41439#> <#41440#>n0<#41440#> <#41441#>1)))<#41441#>To make the invariant true at the beginning, we must use <#67617#><#41445#>1<#41445#><#67617#> for the accumulator. When <#67618#><#41446#>!-a<#41446#><#67618#> recurs, we must multiply the current value of the accumulator with <#67619#><#41447#>n<#41447#><#67619#> to re-establish the invariant. From the purpose statement for the accumulator of <#67620#><#41448#>!-a<#41448#><#67620#>, we can see that if <#67621#><#41449#>n<#41449#><#67621#> is <#67622#><#41450#>0<#41450#><#67622#>, the accumulator is the product of <#67623#><#41451#>n<#41451#><#67623#>, ..., <#67624#><#41452#>1<#41452#><#67624#>. That is, it is the desired result. So, like <#67625#><#41453#>sum<#41453#><#67625#>, <#67626#><#41454#>!-a<#41454#><#67626#> returns <#67627#><#41455#>accumulator<#41455#><#67627#> in the first case and simply recurs in the second one. Figure~#figaccumulatorstyle#41456>
<#41462#>(!<#41462#> <#41463#>3)<#41463#> <#41464#>=<#41464#> <#41465#>(*<#41465#> <#41466#>3<#41466#> <#41467#>(!<#41467#> <#41468#>2))<#41468#> <#41469#>=<#41469#> <#41470#>(*<#41470#> <#41471#>3<#41471#> <#41472#>(*<#41472#> <#41473#>2<#41473#> <#41474#>(!<#41474#> <#41475#>1)))<#41475#> <#41476#>=<#41476#> <#41477#>(*<#41477#> <#41478#>3<#41478#> <#41479#>(*<#41479#> <#41480#>2<#41480#> <#41481#>(*<#41481#> <#41482#>1<#41482#> <#41483#>(!<#41483#> <#41484#>0))))<#41484#> <#41485#>=<#41485#> <#41486#>(*<#41486#> <#41487#>3<#41487#> <#41488#>(*<#41488#> <#41489#>2<#41489#> <#41490#>(*<#41490#> <#41491#>1<#41491#> <#41492#>1)))<#41492#> <#41493#>=<#41493#> <#41494#>(*<#41494#> <#41495#>3<#41495#> <#41496#>(*<#41496#> <#41497#>2<#41497#> <#41498#>1))<#41498#> <#41499#>=<#41499#> <#41500#>(*<#41500#> <#41501#>3<#41501#> <#41502#>2)<#41502#> <#41503#>=<#41503#> <#41504#>6<#41504#>
<#41510#>(!<#41510#> <#41511#>3)<#41511#> <#41512#>=<#41512#> <#41513#>(!-a<#41513#> <#41514#>3<#41514#> <#41515#>1)<#41515#> <#41516#>=<#41516#> <#41517#>(!-a<#41517#> <#41518#>2<#41518#> <#41519#>3)<#41519#> <#41520#>=<#41520#> <#41521#>(!-a<#41521#> <#41522#>1<#41522#> <#41523#>6)<#41523#> <#41524#>=<#41524#> <#41525#>(!-a<#41525#> <#41526#>0<#41526#> <#41527#>6)<#41527#> <#41528#>=<#41528#> <#41529#>6<#41529#>The left column shows how the original version works, the right one how the accumulator-style function proceeds. Both traverse the natural number until they reach <#67629#><#41533#>0<#41533#><#67629#>, but while the original version only schedules multiplications, the new one multiplies the numbers as they are processed. In addition, the right column illustrates how the new factorial function maintains the accumulator invariant. For each application, the accumulator is the product of <#67630#><#41534#>3<#41534#><#67630#> to <#67631#><#41535#>n<#41535#><#67631#> where <#67632#><#41536#>n<#41536#><#67632#> is the first argument to <#67633#><#41537#>!-a<#41537#><#67633#>.
<#71646#>;; <#67638#><#41552#>many<#41552#> <#41553#>:<#41553#> <#41554#>N<#41554#> <#41555#>(<#41555#><#41556#>N<#41556#> <#41557#><#41557#><#41558#>-;SPMgt;<#41558#><#41559#><#41559#> <#41560#>N<#41560#><#41561#>)<#41561#> <#41562#><#41562#><#41563#>-;SPMgt;<#41563#><#41564#><#41564#> <#41565#>true<#41565#><#67638#><#71646#> <#71647#>;; to evaluate <#67639#><#41566#>(f<#41566#> <#41567#>20)<#41567#><#67639#> <#67640#><#41568#>n<#41568#><#67640#> times <#71647#> <#41569#>(define<#41569#> <#41570#>(many<#41570#> <#41571#>n<#41571#> <#41572#>f)<#41572#> <#41573#>...)<#41573#>(2) Evaluating <#67641#><#41577#>(time<#41577#>\ <#41578#>an-expression)<#41578#><#67641#> determines how much time the evaluation of <#67642#><#41579#>an-expression<#41579#><#67642#> takes. Solution<#67643#><#67643#>
<#41591#>(define-struct<#41591#> <#41592#>node<#41592#> <#41593#>(left<#41593#> <#41594#>right))<#41594#>and its corresponding data definition:
A <#67644#><#41599#>binary tree<#41599#><#67644#> (short: tree) is eitherThese trees contain no information, and all of them end in <#67650#><#41610#>empty<#41610#><#67650#>. Still, there are many different trees as figure~#figsimbtex#41611>
- <#67645#><#41601#>empty<#41601#><#67645#>
- <#67646#><#41602#>(make-node<#41602#>\ <#41603#>tl<#41603#>\ <#41604#>tr)<#41604#><#67646#> where <#67647#><#41605#>tl<#41605#><#67647#>, <#67648#><#41606#>tr<#41606#><#67648#> are <#67649#><#41607#>trees<#41607#><#67649#>.
<#41657#>Figure: Some stripped-down binary trees<#41657#>
the second one is
That is, the exponent represents the number of digits that
follow.~ Solution<#67711#><#67711#>
<#42096#>Exercise 31.3.8<#42096#>
<#42152#>Pitfalls<#42152#>:\
~<#42154#>PLAN: need to dig out the bad exam solution and work it in
It represents the results for
exercise~#extimefactorial#42162>
Using the graphical representation of binary trees we can easily determine
properties of trees. For example, we can count how many nodes it contains,
how many <#67661#><#41659#>empty<#41659#><#67661#>s there are, or how high it is. Let's look at the
function <#67662#><#41660#>height<#41660#><#67662#>, which consumes a tree and determines how high it
is:
<#71649#>;; <#67663#><#41665#>height<#41665#> <#41666#>:<#41666#> <#41667#>tree<#41667#> <#41668#><#41668#><#41669#>-;SPMgt;<#41669#><#41670#><#41670#> <#41671#>number<#41671#><#67663#><#71649#>
<#71650#>;; to measure the height of <#67664#><#41672#>abt0<#41672#><#67664#><#71650#>
<#41673#>;; structural recursion <#41673#>
<#41674#>(d<#41674#><#41675#>efine<#41675#> <#41676#>(height<#41676#> <#41677#>abt)<#41677#>
<#41678#>(c<#41678#><#41679#>ond<#41679#>
<#41680#>[<#41680#><#41681#>(empty?<#41681#> <#41682#>abt)<#41682#> <#41683#>0]<#41683#>
<#41684#>[<#41684#><#41685#>else<#41685#> <#41686#>(+<#41686#> <#41687#>(max<#41687#> <#41688#>(height<#41688#> <#41689#>(node-left<#41689#> <#41690#>abt))<#41690#>
<#41691#>(height<#41691#> <#41692#>(node-right<#41692#> <#41693#>abt)))<#41693#> <#41694#>1)]<#41694#><#41695#>))<#41695#>
Like the data definition, this function definition has two
self-references.
To transform this function into an accumulator-style function, we follow the
standard path. We begin with putting an appropriate template into a
<#67665#><#41699#>local<#41699#><#67665#> definition:
<#71651#>;; <#67666#><#41704#>height<#41704#> <#41705#>:<#41705#> <#41706#>tree<#41706#> <#41707#><#41707#><#41708#>-;SPMgt;<#41708#><#41709#><#41709#> <#41710#>number<#41710#><#67666#><#71651#>
<#71652#>;; to measure the height of <#67667#><#41711#>abt0<#41711#><#67667#><#71652#>
<#41712#>(d<#41712#><#41713#>efine<#41713#> <#41714#>(height<#41714#> <#41715#>abt0)<#41715#>
<#41716#>(l<#41716#><#41717#>ocal<#41717#> <#41718#>(<#41718#><#71653#>;; <#67668#><#41719#>accumulator<#41719#><#67668#> ...<#71653#>
<#41720#>(d<#41720#><#41721#>efine<#41721#> <#41722#>(height-a<#41722#> <#41723#>abt<#41723#> <#41724#>accumulator)<#41724#>
<#41725#>(c<#41725#><#41726#>ond<#41726#>
<#41727#>[<#41727#><#41728#>(empty?<#41728#> <#41729#>abt)<#41729#> <#41730#>...]<#41730#>
<#41731#>[<#41731#><#41732#>e<#41732#><#41733#>lse<#41733#>
<#41734#>...<#41734#> <#41735#>(height-a<#41735#> <#41736#>(node-left<#41736#> <#41737#>abt)<#41737#>
The problem, as always, is to determine what knowledge the accumulator
should represent.
An obvious choice is that <#67671#><#41760#>accumulator<#41760#><#67671#> should be a number. More
specifically, <#67672#><#41761#>accumulator<#41761#><#67672#> should represent the number of
<#67673#><#41762#>node<#41762#><#67673#>s that <#67674#><#41763#>height-a<#41763#><#67674#> has processed so far. Initially, it
has seen <#67675#><#41764#>0<#41764#><#67675#> nodes; as it descends the tree, it must increase the
accumulator as it processes a <#67676#><#41765#>node<#41765#><#67676#>:
<#41770#>..<#41770#><#41771#>.<#41771#>
<#41772#>(l<#41772#><#41773#>ocal<#41773#> <#41774#>(<#41774#><#71654#>;; <#67677#><#41775#>accumulator<#41775#><#67677#> represents how many nodes <#67678#><#41776#>height-a<#41776#><#67678#> <#71654#>
<#71655#>;; has encountered on its way to <#67679#><#41777#>abt<#41777#><#67679#> from <#67680#><#41778#>abt0<#41778#><#67680#><#71655#>
<#41779#>(d<#41779#><#41780#>efine<#41780#> <#41781#>(height-a<#41781#> <#41782#>abt<#41782#> <#41783#>accumulator)<#41783#>
<#41784#>(c<#41784#><#41785#>ond<#41785#>
<#41786#>[<#41786#><#41787#>(empty?<#41787#> <#41788#>abt)<#41788#> <#41789#>...]<#41789#>
<#41790#>[<#41790#><#41791#>e<#41791#><#41792#>lse<#41792#>
<#41793#>...<#41793#> <#41794#>(height-a<#41794#> <#41795#>(node-left<#41795#> <#41796#>abt)<#41796#> <#41797#>(+<#41797#> <#41798#>accumulator<#41798#> <#41799#>1))<#41799#> <#41800#>...<#41800#>
<#41801#>...<#41801#> <#41802#>(height-a<#41802#> <#41803#>(node-right<#41803#> <#41804#>abt)<#41804#> <#41805#>(+<#41805#> <#41806#>accumulator<#41806#> <#41807#>1))<#41807#> <#41808#>...]<#41808#><#41809#>)))<#41809#>
<#41810#>(height<#41810#> <#41811#>abt0<#41811#> <#41812#>0))<#41812#>
That is, the accumulator invariant is that <#67681#><#41816#>accumulator<#41816#><#67681#> counts how
many steps <#67682#><#41817#>height-a<#41817#><#67682#> has taken on a particular path into the tree
<#67683#><#41818#>abt<#41818#><#67683#>.
The result in the base case is <#67684#><#41819#>accumulator<#41819#><#67684#> again; after all it
represents the height or length of the particular path. But, in contrast to
the first two examples, it is not the final result. In the second
<#67685#><#41820#>cond<#41820#><#67685#>-clause, the new function has two heights to deal with. Given
that we are interested in the larger one, we use Scheme's <#67686#><#41821#>max<#41821#><#67686#>
operation to select it.
<#71656#>;; <#67687#><#41826#>height<#41826#> <#41827#>:<#41827#> <#41828#>tree<#41828#> <#41829#><#41829#><#41830#>-;SPMgt;<#41830#><#41831#><#41831#> <#41832#>number<#41832#><#67687#><#71656#>
<#71657#>;; to measure the height of <#67688#><#41833#>abt0<#41833#><#67688#><#71657#>
<#41834#>(d<#41834#><#41835#>efine<#41835#> <#41836#>(height<#41836#> <#41837#>abt0)<#41837#>
<#41838#>(l<#41838#><#41839#>ocal<#41839#> <#41840#>(<#41840#><#71658#>;; <#67689#><#41841#>accumulator<#41841#><#67689#> represents how many nodes <#67690#><#41842#>height-a<#41842#><#67690#> <#71658#>
<#71659#>;; has encountered on its way to <#67691#><#41843#>abt<#41843#><#67691#> from <#67692#><#41844#>abt0<#41844#><#67692#><#71659#>
<#41845#>(d<#41845#><#41846#>efine<#41846#> <#41847#>(height-a<#41847#> <#41848#>abt<#41848#> <#41849#>accumulator)<#41849#>
<#41850#>(c<#41850#><#41851#>ond<#41851#>
<#41852#>[<#41852#><#41853#>(empty?<#41853#> <#41854#>abt)<#41854#> <#41855#>accumulator]<#41855#>
<#41856#>[<#41856#><#41857#>else<#41857#> <#41858#>(max<#41858#> <#41859#>(height-a<#41859#> <#41860#>(node-left<#41860#> <#41861#>abt)<#41861#> <#41862#>(+<#41862#> <#41863#>accumulator<#41863#> <#41864#>1))<#41864#>
<#41865#>(height-a<#41865#> <#41866#>(node-right<#41866#> <#41867#>abt)<#41867#> <#41868#>(+<#41868#> <#41869#>accumulator<#41869#> <#41870#>1)))]<#41870#><#41871#>)))<#41871#>
<#41872#>(height-a<#41872#> <#41873#>abt0<#41873#> <#41874#>0)))<#41874#>
<#67693#>Figure: The accumulator-style version of <#41878#>height<#41878#><#67693#>
Figure~#figheightaccu#41880> <#41886#>(height<#41886#> <#41887#>(m<#41887#><#41888#>ake-node<#41888#>
<#41889#>(make-node<#41889#> <#41890#>empty<#41890#>
<#41891#>(make-node<#41891#> <#41892#>empty<#41892#> <#41893#>empty))<#41893#>
<#41894#>empty))<#41894#>
<#41902#>=<#41902#> <#41903#>(height-a<#41903#> <#41904#>(m<#41904#><#41905#>ake-node<#41905#>
<#41906#>(make-node<#41906#> <#41907#>empty<#41907#>
<#41908#>(make-node<#41908#> <#41909#>empty<#41909#> <#41910#>empty))<#41910#>
<#41911#>empty)<#41911#>
<#41912#>0)<#41912#>
<#41920#>=<#41920#> <#41921#>(max<#41921#> <#41922#>(h<#41922#><#41923#>eight-a<#41923#>
<#41924#>(make-node<#41924#> <#41925#>empty<#41925#>
<#41926#>(make-node<#41926#> <#41927#>empty<#41927#> <#41928#>empty))<#41928#>
<#41929#>1)<#41929#>
<#41930#>(height-a<#41930#> <#41931#>empty<#41931#> <#41932#>1))<#41932#>
<#41940#>=<#41940#> <#41941#>(max<#41941#> <#41942#>(m<#41942#><#41943#>ax<#41943#>
<#41944#>(height-a<#41944#> <#41945#>empty<#41945#> <#41946#>2)<#41946#>
<#41947#>(height-a<#41947#> <#41948#>(make-node<#41948#> <#41949#>empty<#41949#> <#41950#>empty)<#41950#> <#41951#>2))<#41951#>
<#41952#>(height-a<#41952#> <#41953#>empty<#41953#> <#41954#>1))<#41954#>
<#41962#>=<#41962#> <#41963#>(max<#41963#> <#41964#>(m<#41964#><#41965#>ax<#41965#>
<#41966#>(height-a<#41966#> <#41967#>empty<#41967#> <#41968#>2)<#41968#>
<#41969#>(max<#41969#> <#41970#>(height-a<#41970#> <#41971#>empty<#41971#> <#41972#>3)<#41972#> <#41973#>(height-a<#41973#> <#41974#>empty<#41974#> <#41975#>3)))<#41975#>
<#41976#>(height-a<#41976#> <#41977#>empty<#41977#> <#41978#>1))<#41978#>
<#41986#>=<#41986#> <#41987#>(max<#41987#> <#41988#>(m<#41988#><#41989#>ax<#41989#>
<#41990#>2<#41990#>
<#41991#>(max<#41991#> <#41992#>3<#41992#> <#41993#>3))<#41993#>
<#41994#>1)<#41994#>
<#41995#>=<#41995#> <#41996#>3<#41996#>
It shows how <#67695#><#42000#>height-a<#42000#><#67695#> increments the accumulator at each step and
that the accumulator at the top of a path represents the number of lines
traversed. The hand-evaluation also shows that the results of the various
branches are combined at each branching point.
<#42003#>Exercise 31.3.3<#42003#>
<#42048#>(to10<#42048#> <#42049#>(list<#42049#> <#42050#>1<#42050#> <#42051#>0<#42051#> <#42052#>2))<#42052#>
<#42053#>=<#42053#> <#42054#>102<#42054#>
<#42055#>(to10<#42055#> <#42056#>(list<#42056#> <#42057#>2<#42057#> <#42058#>1))<#42058#>
<#42059#>=<#42059#> <#42060#>21<#42060#>
Now generalize the function so that it consumes a base b and a list of
b-digits. The conversion produces the decimal (10-based) value of the
list. The base is between <#67709#><#42064#>2<#42064#><#67709#> and <#67710#><#42065#>10<#42065#><#67710#>. A b-digit is a
number between <#42066#>0<#42066#> and b-1.
Examples:
<#42071#>(to10-general<#42071#> <#42072#>10<#42072#> <#42073#>(list<#42073#> <#42074#>1<#42074#> <#42075#>0<#42075#> <#42076#>2))<#42076#>
<#42077#>=<#42077#> <#42078#>102<#42078#>
<#42079#>(to10-general<#42079#> <#42080#>08<#42080#> <#42081#>(list<#42081#> <#42082#>1<#42082#> <#42083#>0<#42083#> <#42084#>2))<#42084#>
<#42085#>=<#42085#> <#42086#>66<#42086#>
<#42090#>Hint:<#42090#> \ In the first example, the result is determine by
<#71660#>;; <#67716#><#42109#>is-prime?<#42109#> <#42110#>:<#42110#> <#42111#>N<#42111#><#42112#>[<#42112#><#42113#>;SPMgt;=1]<#42113#> <#42114#><#42114#><#42115#>-;SPMgt;<#42115#><#42116#><#42116#> <#42117#>boolean<#42117#><#67716#><#71660#>
<#71661#>;; to determine whether <#67717#><#42118#>n<#42118#><#67717#> is a prime number<#71661#>
<#42119#>(d<#42119#><#42120#>efine<#42120#> <#42121#>(is-prime?<#42121#> <#42122#>n)<#42122#>
<#42123#>(c<#42123#><#42124#>ond<#42124#>
<#42125#>[<#42125#><#42126#>(=<#42126#> <#42127#>n<#42127#> <#42128#>1)<#42128#> <#42129#>...]<#42129#>
<#42130#>[<#42130#><#42131#>else<#42131#> <#42132#>...<#42132#> <#42133#>(is-prime?<#42133#> <#42134#>(sub1<#42134#> <#42135#>n))<#42135#> <#42136#>...]<#42136#><#42137#>))<#42137#>
From this outline, we can immediately conclude that the function
forgets <#67718#><#42141#>n<#42141#><#67718#>, its initial argument as it recurs. Since <#67719#><#42142#>n<#42142#><#67719#>
is clearly needed to determine whether <#67720#><#42143#>n<#42143#><#67720#> is divisible by 2 ... n-1,
this suggests that we design an accumulator-style local function that
remembers <#67721#><#42144#>n<#42144#><#67721#> as it recurs.~ Solution<#67722#><#67722#>
quick-sort or merge-sort misunderstood -- and we get a bad version of insertion sort back<#42154#>
People who encounter accumulator-style programming for the first time often
get the impression that they are always faster or easier to understand
(design) than their recursive counterparts. Both parts are plain
wrong. While it is impossible to deal with the full scope of the mistake,
let us take a look at a small counterexample.
Consider the following table: