fun x y =
let f1 = ... (f2 x) ...   -- f1 calls f2
    f2 x = x * 2
in case x of
    1 -> f2 0
    _ -> f2 (f1 y)

g x = let z = (some complex computation) in z `div` x

main = print (g (fun 1 2))

This is a classical example of why laziness gets in the way of
debugging. Now, when (f2 0) gets finally evaluated and throws a
divByZero error, x and y are nowhere to be found.
Since we do not have a real dynamic stack, it is difficult to say
where their values should be stored. The only place I can think of is
at the breakpoint itself, but then as Simon said this poses a serious
efficiency problem.

Isn't that a case of premature optimization? I will happily compain
about performance issues later, after the debugger turns out to be
merely too slow!-) Currently, the issue is one of it not working as well as it could, which seems rather more important to me (think of it as infinitely too slow for my needs:-). Once it comes to performance issues (btw, is there a debugger home page on the wiki, where issues/FAQs like "why can't I have scope contexts" are documented?), an obvious compromise would be to state explicitly where to preserve scope information - something like:

   :break fun{x,y}/{f1,f2}/f2{x}

would set a breakpoint on f2, associating with it information about the static scope context including only the named names (items between // define the path towards the name we want to break, level by level; additional names can be added in {} at each level), without affecting other parts of the program.

Claus

_______________________________________________
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users

Reply via email to