Quick print type debugging

Anybody think something like this would be useful?

module Kernel
  def d(message="",&block)
    ret = block.call
    $stderr.puts("DEBUG: #{block.inspect} #{message} =>
#{ret}") if $DEBUG
    ret
  end
end

irb(main):020:0> $DEBUG=true
=> true
irb(main):019:0> d{1+2*3}
DEBUG: #<Proc:0xb7df9adc@(irb):19> => 7
=> 7
irb(main):020:0> $DEBUG=false
=> false
irb(main):021:0> d{1+2*3}
=> 7

If you have an expression to want to see the result of, you
just surround it with d{...}. The block.inspect gives you the
filename and line number and you get the evaluated value. No
need to have a separate "p" or "puts" statement (and possibly
assignment to a variable) because this returns the value.

What would be nice is if you could somehow convert the block
back to text (and put it in the debug message). Anybody know
how to do that? I know I could make the block be a string of
the code instead to solve the problem (d{"..."}), but that
would be uglier and less efficient when we have debugging off
(because we have to eval).

···

__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around
http://mail.yahoo.com

Yes. I'd even support an RCR for this. This would also sort of mandate
a block-to-string RCR (or at least block-to-nodes-to-string) which
I've wanted for a while, but haven't had enough knowledge to express
clearly.

-austin

···

On 9/9/05, Eric Mahurin <eric_mahurin@yahoo.com> wrote:

Anybody think something like this would be useful?

--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca

Eric Mahurin wrote:

What would be nice is if you could somehow convert the block
back to text (and put it in the debug message). Anybody know
how to do that? I know I could make the block be a string of
the code instead to solve the problem (d{"..."}), but that
would be uglier and less efficient when we have debugging off
(because we have to eval).

See attachment. It's not very general, though.

I think I'd go with the string solution, use Binding.of_caller to put it into the right context and alias it to a method that does nothing when $DEBUG isn't set.

binding_of_caller.rb (2.74 KB)

proc_source.rb (6.86 KB)

Anybody think something like this would be useful?

module Kernel
def d(message="",&block)
   ret = block.call
   $stderr.puts("DEBUG: #{block.inspect} #{message} =>
#{ret}") if $DEBUG
   ret
end
end

yeah - but maybe ENV['DEBUG'] vs $DEBUG so one could just

   DEBUG=1 ruby a.rb

$DEBUG makes many packages VERY noisy when loaded...

irb(main):020:0> $DEBUG=true
=> true
irb(main):019:0> d{1+2*3}
DEBUG: #<Proc:0xb7df9adc@(irb):19> => 7
=> 7
irb(main):020:0> $DEBUG=false
=> false
irb(main):021:0> d{1+2*3}
=> 7

If you have an expression to want to see the result of, you
just surround it with d{...}. The block.inspect gives you the
filename and line number and you get the evaluated value. No
need to have a separate "p" or "puts" statement (and possibly
assignment to a variable) because this returns the value.

What would be nice is if you could somehow convert the block
back to text (and put it in the debug message). Anybody know
how to do that? I know I could make the block be a string of
the code instead to solve the problem (d{"..."}), but that
would be uglier and less efficient when we have debugging off
(because we have to eval).

__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around
http://mail.yahoo.com

-a

···

On Sat, 10 Sep 2005, Eric Mahurin wrote:
--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
Your life dwells amoung the causes of death
Like a lamp standing in a strong breeze. --Nagarjuna

===============================================================================

require 'dev-utils/debug' # http://dev-utils.rubyforge.org

x = 5; y = 6

trace 'x + y' # -> outputs "x + y = 11"

Doesn't tell you file and line numbers, but do you need that if it
prints the expression?

Cheers,
Gavin

Eric Mahurin wrote:

> What would be nice is if you could somehow convert the
block
> back to text (and put it in the debug message). Anybody
know
> how to do that? I know I could make the block be a string
of
> the code instead to solve the problem (d{"..."}), but that
> would be uglier and less efficient when we have debugging
off
> (because we have to eval).

See attachment. It's not very general, though.

Perfect. This was from a ruby quiz, right? Now here is the
new method (didn't need binding_of_caller.rb):

require 'proc_source.rb'

$DEBUG_LEVEL = ENV['DEBUG']||0

module Kernel
  def d(level=1,&block)
    if $DEBUG_LEVEL>=level
      ret = yield
      filename,lineno = block.source_descriptor
      $stderr.printf("DEBUG: %s:%d {%s} => %s\n",
        filename,lineno,block.source,ret)
      ret
    else
      yield
    end
  end
end

$DEBUG_LEVEL = 1
x = d{1+2} + 3*4 - d{5/6}

DEBUG: (irb):24 {} => 3
DEBUG: (irb):24 {} => 0
=> 15

Didn't work. Any idea why, Florian? I tried aProc.source
after using lambda to create it and it worked (also in irb).
But, with a block it doesn't seem to.

I think I'd go with the string solution, use
Binding.of_caller to put it
into the right context and alias it to a method that does
nothing when
$DEBUG isn't set.

I need to evaluate the block even without debugging because the
result will be used as part of an expression independent of
debugging mode (see above).

···

--- Florian Groß <florgro@gmail.com> wrote:

__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around

I just took a peek at your code. This could be quite slow
because it uses Binding#of_caller (searches stack, uses
continuations) and eval. I don't particularly like the idea of
putting code in a string (editors treat it like a string rather
than code). Oh, and having this debug/trace method return the
expression value would be very useful. So, when you have this:

z = x + y

you can just do this to have minimal code change to debug/trace
something:

z = trace('x+y') # or d{x+y} # or d2{'x+y'}

Here would be an implementation of d (expression in a block -
doesn't print expression) and d2 (expression in a string in a
block - prints the expression):

$DEBUG_LEVEL = ENV['DEBUG']||0
module Kernel
  # block contains expression to be evaluated and traced
  def d(level=1,&block)
    result = block.call
    if $DEBUG_LEVEL>=level
      file,line = /\A#<Proc:0x[0-9A-Fa-f]+@(\S+?):(\d+)>\Z/.
          match(block.inspect).captures
      $stderr.printf("DEBUG: %s:%d #=> %s\n",
        file,line,result.to_s)
    end
    result
  end
  # block contains string of expression to be evaluated and
traced
  def d2(level=1,&block)
    expr = block.call
    result = eval(expr,block.binding)
    if $DEBUG_LEVEL>=level
      file,line = /\A#<Proc:0x[0-9A-Fa-f]+@(\S+?):(\d+)>\Z/.
          match(block.inspect).captures
      $stderr.printf("DEBUG: %s:%d - %s #=> %s\n",
        file,line,expr,result.to_s)
    end
    result
  end
end

I don't have ruby on the OS I'm on now, so the above is
untested.

You get it all with d2, but you have the inefficiency of eval
and the ugliness of the expression in a string. But, at least
no Binding#of_caller. I'd probably rather use d and hope that
later down the road we get the ability to convert a Proc back
to the code string. Even if it is inefficient - you only need
it while debugging. Something like Florian's implementation
could be used, be you need one more piece of information - a
column or token number (along with file and line we already
have); otherwise you can't distinguish multiple blocks/lambdas
on the same line.

I just thought of something else. Maybe you could get around
the eval inefficiency in d2, by storing the eval'ed code back
into block (untested):

result = begin
  block.call_string
rescue
  expr = block.call
  proc = eval("lambda {#{expr}}",block.binding)
  block_meta_class = (class << block;self;end)
  block_meta_class.send(:define_method,:call_string,&proc)
  retry
end

Again, this is untested. The idea with above is to only need
to eval once. Something like this should work as long as block
is the same Proc object every time d2 is called in a certain
part of the code (block is compiled and converted to a Proc
once).

···

--- "gsinclair@gmail.com" <gsinclair@gmail.com> wrote:

require 'dev-utils/debug' # http://dev-utils.rubyforge.org

x = 5; y = 6

trace 'x + y' # -> outputs "x + y = 11"

Doesn't tell you file and line numbers, but do you need that
if it
prints the expression?

__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around

Eric Mahurin wrote:

What would be nice is if you could somehow convert the

block

back to text (and put it in the debug message). Anybody

know

how to do that? I know I could make the block be a string

of

the code instead to solve the problem (d{"..."}), but that
would be uglier and less efficient when we have debugging

off

(because we have to eval).

See attachment. It's not very general, though.

Perfect. This was from a ruby quiz, right? Now here is the
new method (didn't need binding_of_caller.rb):

require 'proc_source.rb'

$DEBUG_LEVEL = ENV['DEBUG']||0

module Kernel
def d(level=1,&block)
   if $DEBUG_LEVEL>=level
     ret = yield
     filename,lineno = block.source_descriptor
     $stderr.printf("DEBUG: %s:%d {%s} => %s\n",
       filename,lineno,block.source,ret)
     ret
   else
     yield
   end
end
end

$DEBUG_LEVEL = 1
x = d{1+2} + 3*4 - d{5/6}

DEBUG: (irb):24 {} => 3
DEBUG: (irb):24 {} => 0
=> 15

Didn't work. Any idea why, Florian? I tried aProc.source
after using lambda to create it and it worked (also in irb).
But, with a block it doesn't seem to.

maybe block.call instead of yield?

I think I'd go with the string solution, use
Binding.of_caller to put it
into the right context and alias it to a method that does
nothing when
$DEBUG isn't set.

I need to evaluate the block even without debugging because the
result will be used as part of an expression independent of
debugging mode (see above).

__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around
http://mail.yahoo.com

-a

···

On Sat, 10 Sep 2005, Eric Mahurin wrote:

--- Florian Groß <florgro@gmail.com> wrote:

--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
Your life dwells amoung the causes of death
Like a lamp standing in a strong breeze. --Nagarjuna

===============================================================================

Eric Mahurin wrote:

See attachment. It's not very general, though.

Perfect. This was from a ruby quiz, right? Now here is the
new method (didn't need binding_of_caller.rb):

I also submitted it to a Ruby Quiz, but it is older than that.

Didn't work. Any idea why, Florian? I tried aProc.source
after using lambda to create it and it worked (also in irb). But, with a block it doesn't seem to.

As said: It's not very general.

You can try replacing

        elsif token.is_a?(RubyToken::TkIDENTIFIER) and
              %w{proc lambda}.include?(token.instance_variable_get(:@name))

with

        elsif token.is_a?(RubyToken::TkIDENTIFIER) and
              %w{proc lambda d}.include?(token.instance_variable_get(:@name))

Perhaps it will work.

Eric Mahurin wrote:

I just took a peek at your code. This could be quite slow
because it uses Binding#of_caller (searches stack, uses
continuations) and eval. I don't particularly like the idea of
putting code in a string (editors treat it like a string rather
than code). Oh, and having this debug/trace method return the
expression value would be very useful.

Why do you think that this is too slow? It's something that only happens when debugging. Putting the string into a block doesn't help at all because strings are generated at parse-time so you avoid no overhead at all.

True, getting the caller's binding isn't exactly fast, but it only happens when debugging. I think you are overrating this as you can make trace() a noop when $DEBUG is false. (Just like I do with assert { } in ruby-breakpoint.)

I'm pretty sure that Proc#source is way slower than the Binding.of_caller solution, by the way.

Didn't help. lambda works, but a block doesn't:

irb(main):052:0> lambda { 1+2 }.source
=> "1+2"
irb(main):053:0> def test(&block)
irb(main):054:1> return block.source_descriptor,block.source
irb(main):055:1> end
=> nil
irb(main):056:0> test { 1+2 }
=> [["(irb)", 56], nil]

···

--- "Ara.T.Howard" <Ara.T.Howard@noaa.gov> wrote:

On Sat, 10 Sep 2005, Eric Mahurin wrote:

> --- Florian Groß <florgro@gmail.com> wrote:
>
>> Eric Mahurin wrote:
>>
>>> What would be nice is if you could somehow convert the
>> block
>>> back to text (and put it in the debug message). Anybody
>> know
>>> how to do that? I know I could make the block be a
string
>> of
>>> the code instead to solve the problem (d{"..."}), but
that
>>> would be uglier and less efficient when we have debugging
>> off
>>> (because we have to eval).
>>
>> See attachment. It's not very general, though.
>
> Perfect. This was from a ruby quiz, right? Now here is
the
> new method (didn't need binding_of_caller.rb):
>
> require 'proc_source.rb'
>
> $DEBUG_LEVEL = ENV['DEBUG']||0
>
> module Kernel
> def d(level=1,&block)
> if $DEBUG_LEVEL>=level
> ret = yield
> filename,lineno = block.source_descriptor
> $stderr.printf("DEBUG: %s:%d {%s} => %s\n",
> filename,lineno,block.source,ret)
> ret
> else
> yield
> end
> end
> end
>
>
> $DEBUG_LEVEL = 1
> x = d{1+2} + 3*4 - d{5/6}
>
> DEBUG: (irb):24 {} => 3
> DEBUG: (irb):24 {} => 0
> => 15
>
> Didn't work. Any idea why, Florian? I tried aProc.source
> after using lambda to create it and it worked (also in
irb).
> But, with a block it doesn't seem to.

maybe block.call instead of yield?

__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around

My proposal was that this expression passed to this trace/debug
method always be evaluated (and returned) so that you could
transparently trace any sub-expression in a larger expression.
I think this would make it an extremely quick way to add traces
anywhere in a piece of code (except LHS of assigns - but you
could trace the whole assign). I was thinking you might leave
some of this in your code indefinitely and control by a debug
level, but some you may put in temporarily.

I wouldn't mind if getting the file, line, and source of the
expression was slow because that would only be done during
debugging - but not the expression evaluation.

Maybe a way to get around the slowness of Binding#of_caller
would be to modify the string expression after the first call
and give it a "call" method (similar to what I proposed for the
expression in a string in a block). That way you'd only need
Binding#of_caller and eval once per string expression.

···

--- Florian Groß <florgro@gmail.com> wrote:

Eric Mahurin wrote:

> I just took a peek at your code. This could be quite slow
> because it uses Binding#of_caller (searches stack, uses
> continuations) and eval. I don't particularly like the
idea of
> putting code in a string (editors treat it like a string
rather
> than code). Oh, and having this debug/trace method return
the
> expression value would be very useful.

Why do you think that this is too slow? It's something that
only happens
when debugging. Putting the string into a block doesn't help
at all
because strings are generated at parse-time so you avoid no
overhead at all.

True, getting the caller's binding isn't exactly fast, but it
only
happens when debugging. I think you are overrating this as
you can make
trace() a noop when $DEBUG is false. (Just like I do with
assert { } in
ruby-breakpoint.)

I'm pretty sure that Proc#source is way slower than the
Binding.of_caller solution, by the way.

__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around