[clean-list] Program compiles and runs, with unpredictable result
David C. Norris
David_Norris at brown.edu
Sat Sep 29 18:09:45 MEST 2007
The following experiment with modeling imperative 'for' loops in Clean
produces programs exhibiting unpredictable behavior. My impression is
that it is necessary to set the SumLoop stop index large to obtain the
behavior. With that done, changing the end character of the CatLoop
produces various results -- sometimes correct, sometimes not.
Correct result:
(5000050000,13,"abcdefg",{1,1,2,3,5,8,13},{4,13,22,15})
Examples of incorrect results:
(5000050000,13,"abcdefghijklmnopqrstuvwxyz",{1,1,2,3,5,8,13},{4,13,8.50705942721713e+37,15})
(5000050000,13,"abcdefghijklmnopqrstuvw",{1,1,2,3,5,8,13},{4,13,-1.21290479585191e+229,15})
(5000050000,13,"abc",{1,1,2,3,5,8,13},{4,13,22,9.52682081175185e+139})
Does this represent a bug?
Regards,
David
------------------------------------------------------
module huh
import StdEnv
// Document apparent bug exposed by attempt to model for imperative
'for' loops
:: *FOR i r = { index :: !i
, stop :: !i
, body :: .(i, r) -> r
, value :: !r
}
SumLoop :: (FOR Int Real)
SumLoop = { index = 1, stop = 100000, body = \(i,x) = x + toReal i,
value = 0.0 }
FibLoop :: (FOR Int (Int, Int))
FibLoop = { index = 2, stop = 7, body = \(i,(m,n)) = (n, m+n), value =
(0, 1) }
CatLoop :: (FOR Char String)
CatLoop = { index = 'a', stop = 'c', body = \(c,s) = s +++ toString c,
value = "" }
FibArrayLoop :: (FOR Int {#Int})
FibArrayLoop = { index = 2
, stop = 7
, body = \(i,a) = update2 i (+) (i-2) (i-1) a
, value = createArray 7 1
}
ConvolveLoop :: (FOR Int *{#Real})
ConvolveLoop = { index = 0
, stop = 3
, body = \(i, c) = runloop { index = 0
, stop = 2
, body = \(j, c) = update1
(i+j) ((+) (a.[i] * b.[j])) (i+j) c
, value = c
}
, value = createArray 4 0.0
}
where
a :: *{#Real}
a = {1.0, 2.0, 3.0}
b :: *{#Real}
b = {4.0, 5.0}
update1 :: !Int (e -> e) !Int !*(a e) -> *(a e) | Array a e
update1 i f j a=:{[j]=aj} = {a & [i] = f aj}
update2 :: !Int (e e -> e) !Int !Int !*(a e) -> *(a e) | Array a e
update2 i f j k a=:{[j]=aj, [k]=ak} = {a & [i] = f aj ak}
runloop :: !*(FOR i .r) -> .r | Enum i
runloop loop
| loop.index > loop.stop = loop.value
| otherwise = runloop { loop & index = inc loop.index,
value = loop.body (loop.index,
loop.value)}
Start :: ( Real
, Int
, String
, {#Int}
, {#Real}
)
Start = ( runloop SumLoop
, snd (runloop FibLoop)
, runloop CatLoop
, runloop FibArrayLoop
, runloop ConvolveLoop
)
More information about the clean-list
mailing list