> Yes, I've run into this before.  In fact this is one of those tricky
> problems where you can't quite get tail-recursion where you want it:
> (pseudo-ish code follows)
>
>    peekCString ptr = do
>      x <- peek ptr
>      if x == '\0' then return [] else do
>      xs <- peekCString (ptr + 1)
>      return (x:xs)
>
> Any ideas?  I seem to recall the ML folks have a hack for dealing with
> this.

Off the top of my head:

1) Compute length of C string.
   (As usual, need to use seq on the '+1' argument.)
2) Scan from right to left, constructing the list.

  peekCString ptr = do
    l <- lenCString ptr 0
    peekCString' ptr l []

  lenCString ptr n = seq n $ do
    c <- peek (ptr+n)
    if c=='\0'
      then return n
      else lenCString ptr (n+1)

  peekCString' ptr 0     r = return r
  peekCString' ptr (n+1) r = do
    c <- peek (ptr+n)
    peekCString' ptr n (c:r)

I don't think this will leak.

Or, since making two passes seems ugly, construct the list in reverse and then 
return the reversed list:

  peekCString ptr = peekCString' ptr []
   where
    peekCString' ptr r = do
      c <- peek ptr
      if c == '\0'
        then return (reverse r)
        else peekCString' (ptr+1) (c:r)

I have a nasty feeling that reverse doesn't work in constant stack space 
though so this probably doesn't work.

--
Alastair

_______________________________________________
Glasgow-haskell-bugs mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs

Reply via email to