Mutable Functional Structures


<#52175#>(d<#52175#><#52176#>efine<#52176#> <#52177#>(fm-make-posn<#52177#> <#52178#>x0<#52178#> <#52179#>y0)<#52179#>
  <#52180#>(l<#52180#><#52181#>ocal<#52181#> <#52182#>(<#52182#><#52183#>(define<#52183#> <#52184#>x<#52184#> <#52185#>y0)<#52185#> 
          <#52186#>(define<#52186#> <#52187#>y<#52187#> <#52188#>y0)<#52188#> 
          <#52189#>(d<#52189#><#52190#>efine<#52190#> <#52191#>(service-manager<#52191#> <#52192#>msg)<#52192#> 
            <#52193#>(c<#52193#><#52194#>ond<#52194#> 
              <#52195#>[<#52195#><#52196#>(symbol=?<#52196#> <#52197#>msg<#52197#> <#52198#>'<#52198#><#52199#>x)<#52199#> <#52200#>x]<#52200#> 
              <#52201#>[<#52201#><#52202#>(symbol=?<#52202#> <#52203#>msg<#52203#> <#52204#>'<#52204#><#52205#>y)<#52205#> <#52206#>y]<#52206#> 
              <#52207#>[<#52207#><#52208#>(symbol=?<#52208#> <#52209#>msg<#52209#> <#52210#>'<#52210#><#52211#>set-x)<#52211#> <#52212#>(lambda<#52212#> <#52213#>(x-new)<#52213#> <#52214#>(set!<#52214#> <#52215#>x<#52215#> <#52216#>x-new))]<#52216#> 
              <#52217#>[<#52217#><#52218#>(symbol=?<#52218#> <#52219#>msg<#52219#> <#52220#>'<#52220#><#52221#>set-y)<#52221#> <#52222#>(lambda<#52222#> <#52223#>(y-new)<#52223#> <#52224#>(set!<#52224#> <#52225#>y<#52225#> <#52226#>y-new))]<#52226#> 
              <#52227#>[<#52227#><#52228#>else<#52228#> <#52229#>(error<#52229#> <#52230#>'<#52230#><#52231#>posn<#52231#> <#52232#>``...'')]<#52232#><#52233#>)))<#52233#> 
    <#52234#>service-manager))<#52234#> 
<#52235#>(d<#52235#><#52236#>efine<#52236#> <#52237#>(fm-posn-x<#52237#> <#52238#>p)<#52238#> 
  <#52239#>(p<#52239#> <#52240#>'<#52240#><#52241#>x))<#52241#> 
<#52242#>(d<#52242#><#52243#>efine<#52243#> <#52244#>(fm-posn-y<#52244#> <#52245#>p)<#52245#> 
  <#52246#>(p<#52246#> <#52247#>'<#52247#><#52248#>y))<#52248#> 
<#52249#>(d<#52249#><#52250#>efine<#52250#> <#52251#>(fm-set-posn-x!<#52251#> <#52252#>p<#52252#> <#52253#>new-value)<#52253#> 
  <#52254#>((p<#52254#> <#52255#>'<#52255#><#52256#>set-x)<#52256#> <#52257#>new-value))<#52257#> 
<#52258#>(d<#52258#><#52259#>efine<#52259#> <#52260#>(fm-set-posn-y!<#52260#> <#52261#>p<#52261#> <#52262#>new-value)<#52262#> 
  <#52263#>((p<#52263#> <#52264#>'<#52264#><#52265#>set-y)<#52265#> <#52266#>new-value))<#52266#> 
<#69275#>Figure: An implementation of <#52270#>posn<#52270#>s with mutators<#69275#>
Together, sections~#secencapsulate#52272> and~#secstructfunc#52273> suggest that structures are mutable. That is, we should be able to change the values of some field in a structure. After all, we introduced the service managers in section~#secencapsulate#52274> to hide state variables, not just ordinary variable definitions. Figure~#figimperativeposn#52275> shows how a small change to the definitions of figure~#figfunctionalposn#52276> turns the <#69276#><#52277#>local<#52277#><#69276#>ly hidden variables into state variables. The modified service manager offers two services per state variable: one for looking up the current value and one for changing it. Consider the following definition and expression:
<#52282#>(define<#52282#> <#52283#>a-posn<#52283#> <#52284#>(fm-make-posn<#52284#> <#52285#>3<#52285#> <#52286#>4))<#52286#>
<#52287#>(b<#52287#><#52288#>egin<#52288#> 
  <#52289#>(fm-set-posn-x!<#52289#> <#52290#>a-posn<#52290#> <#52291#>5)<#52291#> 
  <#52292#>(+<#52292#> <#52293#>(posn-x<#52293#> <#52294#>a-posn)<#52294#> <#52295#>8))<#52295#> 
Evaluating them by hand shows how structures change. Here is the first step:
  <#52303#>...<#52303#> 
<#52304#>=<#52304#> 
  <#52305#>(define<#52305#> <#52306#>x-for-a-posn<#52306#> <#52307#>3)<#52307#> 
  <#52308#>(define<#52308#> <#52309#>y-for-a-posn<#52309#> <#52310#>4)<#52310#> 
  <#52311#>(d<#52311#><#52312#>efine<#52312#> <#52313#>(service-manager-for-a-posn<#52313#> <#52314#>msg)<#52314#> 
    <#52315#>(c<#52315#><#52316#>ond<#52316#> 
      <#52317#>[<#52317#><#52318#>(symbol=?<#52318#> <#52319#>msg<#52319#> <#52320#>'<#52320#><#52321#>x)<#52321#> <#52322#>x-for-a-posn]<#52322#> 
      <#52323#>[<#52323#><#52324#>(symbol=?<#52324#> <#52325#>msg<#52325#> <#52326#>'<#52326#><#52327#>y)<#52327#> <#52328#>y-for-a-posn]<#52328#> 
      <#52329#>[<#52329#><#52330#>(symbol=?<#52330#> <#52331#>msg<#52331#> <#52332#>'<#52332#><#52333#>set-x)<#52333#> 
       <#52334#>(lambda<#52334#> <#52335#>(x-new)<#52335#> <#52336#>(set!<#52336#> <#52337#>x-for-a-posn<#52337#> <#52338#>x-new))]<#52338#> 
      <#52339#>[<#52339#><#52340#>(symbol=?<#52340#> <#52341#>msg<#52341#> <#52342#>'<#52342#><#52343#>set-y)<#52343#> 
       <#52344#>(lambda<#52344#> <#52345#>(y-new)<#52345#> <#52346#>(set!<#52346#> <#52347#>y-for-a-posn<#52347#> <#52348#>y-new))]<#52348#> 
      <#52349#>[<#52349#><#52350#>else<#52350#> <#52351#>(error<#52351#> <#52352#>'<#52352#><#52353#>posn<#52353#> <#52354#>``...'')]<#52354#><#52355#>))<#52355#> 
  <#52356#>(define<#52356#> <#52357#>a-posn<#52357#> <#52358#>service-manager-for-a-posn)<#52358#> 
  <#52359#>(b<#52359#><#52360#>egin<#52360#> 
    <#52361#>(fm-set-posn-x!<#52361#> <#52362#>a-posn<#52362#> <#52363#>5)<#52363#> 
    <#52364#>(+<#52364#> <#52365#>(posn-x<#52365#> <#52366#>a-posn)<#52366#> <#52367#>8))<#52367#> 
It renames and lifts the local definitions from inside of <#69277#><#52371#>fm-make-posn<#52371#><#69277#>. Because the function definition doesn't change for the rest of the evaluation, we focus on just the variable definitions:
  <#52376#>(define<#52376#> <#52377#>x-for-a-posn<#52377#> <#52378#>3)<#52378#>
  <#52379#>(define<#52379#> <#52380#>y-for-a-posn<#52380#> <#52381#>4)<#52381#> 
  <#52382#>(b<#52382#><#52383#>egin<#52383#> 
    <#52384#>(fm-set-posn-x!<#52384#> <#52385#>a-posn<#52385#> <#52386#>5)<#52386#> 
    <#52387#>(+<#52387#> <#52388#>(posn-x<#52388#> <#52389#>a-posn)<#52389#> <#52390#>8))<#52390#> 
<#52391#>=<#52391#> <#52392#>(define<#52392#> <#52393#>x-for-a-posn<#52393#> <#52394#>3)<#52394#> 
  <#52395#>(define<#52395#> <#52396#>y-for-a-posn<#52396#> <#52397#>4)<#52397#> 
  <#52398#>(b<#52398#><#52399#>egin<#52399#> 
    <#52400#>(fm-set-posn-x!<#52400#> <#52401#>service-manager-for-a-posn<#52401#> <#52402#>5)<#52402#> 
    <#52403#>(+<#52403#> <#52404#>(posn-x<#52404#> <#52405#>a-posn)<#52405#> <#52406#>8))<#52406#> 
<#52407#>=<#52407#> <#52408#>(define<#52408#> <#52409#>x-for-a-posn<#52409#> <#52410#>3)<#52410#> 
  <#52411#>(define<#52411#> <#52412#>y-for-a-posn<#52412#> <#52413#>4)<#52413#> 
  <#52414#>(b<#52414#><#52415#>egin<#52415#> 
    <#52416#>((service-manager-for-a-posn<#52416#> <#52417#>'<#52417#><#52418#>set-x)<#52418#> <#52419#>5)<#52419#> 
    <#52420#>(+<#52420#> <#52421#>(posn-x<#52421#> <#52422#>a-posn)<#52422#> <#52423#>8))<#52423#> 
<#52424#>=<#52424#> <#52425#>(define<#52425#> <#52426#>x-for-a-posn<#52426#> <#52427#>3)<#52427#> 
  <#52428#>(define<#52428#> <#52429#>y-for-a-posn<#52429#> <#52430#>4)<#52430#> 
  <#52431#>(b<#52431#><#52432#>egin<#52432#> 
    <#52433#>(set!<#52433#> <#52434#>x-for-a-posn<#52434#> <#52435#>5)<#52435#> 
    <#52436#>(+<#52436#> <#52437#>(posn-x<#52437#> <#52438#>a-posn)<#52438#> <#52439#>8))<#52439#> 
<#52440#>=<#52440#> <#52441#>(define<#52441#> <#52442#>x-for-a-posn<#52442#> <#52443#>5)<#52443#> 
  <#52444#>(define<#52444#> <#52445#>y-for-a-posn<#52445#> <#52446#>4)<#52446#> 
  <#52447#>(+<#52447#> <#52448#>(posn-x<#52448#> <#52449#>a-posn)<#52449#> <#52450#>8)<#52450#> 
At this point, the definition of <#69278#><#52454#>x-for-a-posn<#52454#><#69278#> has been modified in the expected manner. From now on every reference to this state variable, which represents the (simulated) <#69279#><#52455#>x<#52455#><#69279#> field <#69280#><#52456#>a-posn<#52456#><#69280#>, stands for <#69281#><#52457#>5<#52457#><#69281#>. Every further reference to <#69282#><#52458#>x-for-a-posn<#52458#><#69282#> produces <#69283#><#52459#>5<#52459#><#69283#>.
<#52462#>Exercise 40.2.1<#52462#> Develop a functional representation for the following structure definition:
<#52468#>(define-struct<#52468#> <#52469#>boyfriend<#52469#> <#52470#>(name<#52470#> <#52471#>hair<#52471#> <#52472#>eyes<#52472#> <#52473#>phone))<#52473#>
such that the fields of the simulated structure can be changed.~ external Solution<#69284#><#69284#> <#52482#>Exercise 40.2.2<#52482#> Here is a modification of the function-based implementation of <#69285#><#52484#>posn<#52484#><#69285#> structures in exercise~#exfuncstruct1#52485>:
<#52490#>(d<#52490#><#52491#>efine<#52491#> <#52492#>(ffm-make-posn<#52492#> <#52493#>x0<#52493#> <#52494#>y0)<#52494#>
  <#52495#>(local<#52495#> <#52496#>(<#52496#><#52497#>(define<#52497#> <#52498#>x<#52498#> <#52499#>x0)<#52499#> 
          <#52500#>(define<#52500#> <#52501#>(set-x<#52501#> <#52502#>new-x)<#52502#> <#52503#>(set!<#52503#> <#52504#>x<#52504#> <#52505#>new-x))<#52505#> 
          <#52506#>(define<#52506#> <#52507#>y<#52507#> <#52508#>y0)<#52508#> 
          <#52509#>(define<#52509#> <#52510#>(set-y<#52510#> <#52511#>new-y)<#52511#> <#52512#>(set!<#52512#> <#52513#>y<#52513#> <#52514#>new-y)))<#52514#> 
  <#52515#>(l<#52515#><#52516#>ambda<#52516#> <#52517#>(select)<#52517#> 
    <#52518#>(select<#52518#> <#52519#>x<#52519#> <#52520#>y<#52520#> <#52521#>set-x<#52521#> <#52522#>set-y))))<#52522#> 
<#52523#>(d<#52523#><#52524#>efine<#52524#> <#52525#>(ffm-posn-x<#52525#> <#52526#>a-ffm-posn)<#52526#> 
  <#52527#>(a-ffm-posn<#52527#> <#52528#>(lambda<#52528#> <#52529#>(x<#52529#> <#52530#>y<#52530#> <#52531#>sx<#52531#> <#52532#>sy)<#52532#> <#52533#>x)))<#52533#> 
<#52534#>(d<#52534#><#52535#>efine<#52535#> <#52536#>(ffm-posn-y<#52536#> <#52537#>a-ffm-posn)<#52537#> 
  <#52538#>(a-ffm-posn<#52538#> <#52539#>(lambda<#52539#> <#52540#>(x<#52540#> <#52541#>y<#52541#> <#52542#>sx<#52542#> <#52543#>sy)<#52543#> <#52544#>y)))<#52544#> 
<#52545#>(d<#52545#><#52546#>efine<#52546#> <#52547#>(ffm-set-posn-x!<#52547#> <#52548#>a-ffm-posn<#52548#> <#52549#>new-value)<#52549#> 
  <#52550#>(a-ffm-posn<#52550#> <#52551#>(lambda<#52551#> <#52552#>(x<#52552#> <#52553#>y<#52553#> <#52554#>sx<#52554#> <#52555#>sy)<#52555#> <#52556#>(sx<#52556#> <#52557#>new-value))))<#52557#> 
<#52558#>(d<#52558#><#52559#>efine<#52559#> <#52560#>(ffm-set-posn-y!<#52560#> <#52561#>a-ffm-posn<#52561#> <#52562#>new-value)<#52562#> 
  <#52563#>(a-ffm-posn<#52563#> <#52564#>(lambda<#52564#> <#52565#>(x<#52565#> <#52566#>y<#52566#> <#52567#>sx<#52567#> <#52568#>sy)<#52568#> <#52569#>(sy<#52569#> <#52570#>new-value))))<#52570#> 
Demonstrate how to modify a structure like <#69286#><#52574#>(ffm-make-posn<#52574#>\ <#52575#>3<#52575#>\ <#52576#>4)<#52576#><#69286#> so that its <#69287#><#52577#>y<#52577#><#69287#> field contains <#69288#><#52578#>5<#52578#><#69288#>.~ external Solution<#69289#><#69289#>