Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between `traceIO` and `hPutStrLn stderr`?

Looking at the description for traceIO, I feel that it does exactly what hPutStrLn stderr does. However when I looked into its source code:

traceIO :: String -> IO ()
traceIO msg = do
    withCString "%s\n" $ \cfmt -> do
     -- NB: debugBelch can't deal with null bytes, so filter them
     -- out so we don't accidentally truncate the message.  See Trac #9395
     let (nulls, msg') = partition (=='\0') msg
     withCString msg' $ \cmsg ->
      debugBelch cfmt cmsg
     when (not (null nulls)) $
       withCString "WARNING: previous trace message had null bytes" $ \cmsg ->
         debugBelch cfmt cmsg

It seems it uses a foreign routine called debugBelch, which I failed to find any documentation about. So what does traceIO do that can't be done by hPutStrLn stderr?

like image 272
xzhu Avatar asked Oct 10 '15 22:10

xzhu


1 Answers

One thing I can think of is that it might ensure that the string is printed as a unit, without any other trace messages inside. Indeed an experiment seems to confirm this:

Prelude Debug.Trace System.IO> traceIO $ "1" ++ trace "2" "3"
2
13
Prelude Debug.Trace System.IO> hPutStrLn stderr $ "1" ++ trace "2" "3"
12
3

Another difference is that it seems to remove characters that cannot safely be printed to stderr:

Prelude Debug.Trace System.IO> hPutStrLn stderr "\9731"
*** Exception: <stderr>: hPutChar: invalid argument (invalid character)
Prelude Debug.Trace System.IO> traceIO "\9731"

Prelude Debug.Trace System.IO> 

As @dfeuer reminds me of, none of these features would be impossible to write in Haskell. So the deciding factor is probably this: debugBelch is already a predefined C function, used all over the place in GHC's runtime system, which is written in C and C--, not Haskell.

like image 122
Ørjan Johansen Avatar answered Sep 25 '22 12:09

Ørjan Johansen