- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Re: Design of a new Eclipse Scala debugger
Mon, 2010-11-29, 23:55
Regarding expression-level stepping, I just suggested a way to
implement it in the debugger on this thread
(see the comment on this answer)
http://stackoverflow.com/questions/4272797/debugging-functional-code-in-...
The idea is to have an option in the debugger to temporarily expand
expressions written on a single line into code that expands the
expression into intermediate function calls, on multiple lines. This
way the debugger could step into the code and inspect intermediate
function return values. Once the debugger finished the session, the
code would revert to the original version.
For example, this line
val r =(ls filter (_>1) sort (_<_) zipWithIndex) filter
{v=>(v._2)%2==0} map {_._1}
would temporarily expand into
val r_1 = ls.filter(_>1)
val r_2 = r_1.sort(_<_)
val r_3 = r_2.zipWithIndex
val r_4 = r_3.filter(v => (v._2) % 2 == 0)
val r = r_4.map(_._1)
I believe this is cleaner than run-to-cursor approaches. If this is
doable, it would be great.
Adrian
Tue, 2010-11-30, 10:17
#2
Re: Re: Design of a new Eclipse Scala debugger
On Mon, Nov 29, 2010 at 11:55 PM, Adrian Fritsch <adrianfr@gmail.com> wrote:
Regarding expression-level stepping, I just suggested a way to
implement it in the debugger on this thread
(see the comment on this answer)
http://stackoverflow.com/questions/4272797/debugging-functional-code-in-scala/4273043#4273043
The idea is to have an option in the debugger to temporarily expand
expressions written on a single line into code that expands the
expression into intermediate function calls, on multiple lines. This
way the debugger could step into the code and inspect intermediate
function return values. Once the debugger finished the session, the
code would revert to the original version.
For example, this line
val r =(ls filter (_>1) sort (_<_) zipWithIndex) filter
{v=>(v._2)%2==0} map {_._1}
would temporarily expand into
val r_1 = ls.filter(_>1)
val r_2 = r_1.sort(_<_)
val r_3 = r_2.zipWithIndex
val r_4 = r_3.filter(v => (v._2) % 2 == 0)
val r = r_4.map(_._1)
I believe this is cleaner than run-to-cursor approaches. If this is
doable, it would be great.
This is not exactly easy. Line number information is bundled in the classfile, so to have this expansion you'd need to rebuild your project. That's still ok (it could be another possible detail level for debugging information), but you'd need your libraries to do the same. It's probably better to find a way to show it in the UI (for instance, by highlighting a caret on the current line to show what is the next instruction).
We need to decide on the granularity of a 'step'. One step could be one selection or method application. If you think of the program as a tree, then one step will be to execute one leaf node.
The advantage of this approach is that we can keep code and debugging information separate. One could even ship binary code and debugging information separately, to keep code size in check (code size might be a problem, so it's better to keep our options open).
iulian
Adrian
--
« Je déteste la montagne, ça cache le paysage »
Alphonse Allais
Tue, 2010-11-30, 10:27
#3
Re: Re: Design of a new Eclipse Scala debugger
This additional information could also be used by the code coverage tool
I guess, so it would be really great to have it.
hubert
On 11/30/2010 10:10 AM, iulian dragos wrote:
> This is not exactly easy. Line number information is bundled in the
> classfile, so to have this expansion you'd need to rebuild your
> project. That's still ok (it could be another possible detail level
> for debugging information), but you'd need your libraries to do the
> same. It's probably better to find a way to show it in the UI (for
> instance, by highlighting a caret on the current line to show what is
> the next instruction).
>
> We need to decide on the granularity of a 'step'. One step could be
> one selection or method application. If you think of the program as a
> tree, then one step will be to execute one leaf node.
>
> The advantage of this approach is that we can keep code and debugging
> information separate. One could even ship binary code and debugging
> information separately, to keep code size in check (code size might be
> a problem, so it's better to keep our options open).
>
> iulian
>
Tue, 2010-11-30, 12:47
#4
Re: Re: Design of a new Eclipse Scala debugger
On Nov 29, 2010, at 11:55 PM, Adrian Fritsch wrote:
> Regarding expression-level stepping, I just suggested a way to
> implement it in the debugger on this thread
> (see the comment on this answer)
> http://stackoverflow.com/questions/4272797/debugging-functional-code-in-...
>
> The idea is to have an option in the debugger to temporarily expand
> expressions written on a single line into code that expands the
> expression into intermediate function calls, on multiple lines. This
> way the debugger could step into the code and inspect intermediate
> function return values. Once the debugger finished the session, the
> code would revert to the original version.
>
> For example, this line
>
> val r =(ls filter (_>1) sort (_<_) zipWithIndex) filter
> {v=>(v._2)%2==0} map {_._1}
>
> would temporarily expand into
>
> val r_1 = ls.filter(_>1)
> val r_2 = r_1.sort(_<_)
> val r_3 = r_2.zipWithIndex
> val r_4 = r_3.filter(v => (v._2) % 2 == 0)
> val r = r_4.map(_._1)
>
> I believe this is cleaner than run-to-cursor approaches. If this is
> doable, it would be great.
I think this is a great point. You're absolutely right that it is the *intermediate values* that one is usually interested in, so I really want to find a way to support this. Iulian is right though, implementation might be tricky. We will investigate and report back when we have more information.
Donna
Hi Adrian
On Monday 29 November 2010 23:55:48 Adrian Fritsch wrote:
> val r =(ls filter (_>1) sort (_<_) zipWithIndex) filter
> {v=>(v._2)%2==0} map {_._1}
>
> would temporarily expand into
>
> val r_1 = ls.filter(_>1)
> val r_2 = r_1.sort(_<_)
> val r_3 = r_2.zipWithIndex
> val r_4 = r_3.filter(v => (v._2) % 2 == 0)
> val r = r_4.map(_._1)
>
> I believe this is cleaner than run-to-cursor approaches. If this is
> doable, it would be great.
In the mean time, you could use the Scala IDE's refactorings, "Extract Local"
does exactly this :-) (not in one step though, you need to invoke it several
times; but I could implement a "break chained function calls" refactoring that
does it in a single step).
Cheers,
Mirko