From: Eric Mahurin Date: 2005-09-11T00:08:46+09:00 Subject: Re: quick print type debugging --- "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? 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#\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#\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). __________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com