[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