[clean-list] finding and curing a Space Leak

Martin Wierich martinw@cs.kun.nl
Mon, 20 Nov 2000 12:25:09 +0100


Hi Erik,

Erik Zuurbier wrote:
> However, I find the result very ugly: having to introduce an extra variable
> (v1) just to force evaluation. Is there a nicer way?

Writing 
  
  :: *Counts      :== *{!(!Real,!Int)}
  
is the same as writing

  :: *Counts      :== *{!(Real,Int)}

If you do not want your program to build closures for all the "(y-x)*0.9+x"
expressions then you could also use an array whose elements contain two strict
values (if you think that's nicer), e.g.:

  :: MyRecord = { real :: !Real, int :: !Int }    // names don't matter here 

  upd _ sta=:{counts,list=list=:[(i,x):rest]} io
          #! y   = counts.[i].real
          #  sta = {sta & counts = {counts & [i].real = (y-x)*0.9+x}}
          #  sta = {sta & list = rest}
          =  (sta,io)


> Other question: I wanted to make the Counts type more unique, like this:
> :: *Counts      :== *{!*(!Real,!Int)}
> I could not find a way to get the program past the type checker though.
> Does anybody know how?

Yes, e.g.

  upd _ sta=:{counts,list=list=:[(i,x):rest]} io
    #! ((y,j), counts) = replace counts i (0.0,0)
    #  sta = {sta & counts = {counts & [i] = ((y-x)*0.9+x,j)}}
    #  sta = {sta & list = rest}
    =  (sta,io)

Don't use conventional selection ("." or "!") with arrays that contain unique
elements, because this would cause the elements to get shared. If you don't like
that "(0.0,0)" expression then you can use a function from the StdLib library:

  updateArrElt :: !(.e -> .e) !Int !*{!.e} -> *{!.e}

And then:

  upd _ sta=:{counts,list=list=:[(i,x):rest]} io
    #  sta = {sta & counts = updateArrElt (\(y,j) -> ((y-x)*0.9+x,j)) i counts}
    #  sta = {sta & list = rest}
    =  (sta,io)

bye
  Martin Wierich