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?
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.
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
> 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
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).
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
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
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))
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.
> --- 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