[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