J
jeff.sykes.rb
module Tracer
if $DEBUG
def trace(str)
STDERR.puts(str)
end
else
def trace(str)
end
end
end
class Application
include Tracer
def initialize
trace "initializing..."
# ...
end
def run
trace "running..."
# ...
end
end
I have unit tests to confirm things are working well, etc, however in
complex multi-threaded code there's no substitute for the trace output
when problems arise. However even an empty method call is significant,
require 'benchmark'
include Tracer
Benchmark.bm(16) { |b|
n = 10_000_000
b.report("with trace") { n.times { trace } }
b.report("without trace") { n.times { } }
}
user system total real
with trace 3.090000 0.000000 3.090000 ( 3.094240)
without trace 1.010000 0.000000 1.010000 ( 1.015994)
So ... why not ...
# Manipulate the AST
SyntaxTree.each_node { |node|
if node.ast_type == :method_call and node.method_name == "trace"
node.ast_type = :noop # or remove it, or whatever
end
}
# No more trace statements!
Application.new.run
Now I could gsub out those trace statements manually (or for a cleaner
approach maybe ParseTree on RubyForge could be used). But that extra
step is cumbersome compared to the magic I desire. If SyntaxTree were
implemented, I think we would be close to having that bit of power
which lisp provides but ruby does not. Removing trace statements
would only be a trivial use of this Ultimate Power!
In my example SyntaxTree is using the code running in memory, but in
principle I could say
code = SyntaxTree.entry_point { Application.new.run }
code.each_node { |node|
# ... manipulate the code ...
}
# Execute some alternate-universe version of Application.new.run
code.call
Now THAT would be getting lispy.
if $DEBUG
def trace(str)
STDERR.puts(str)
end
else
def trace(str)
end
end
end
class Application
include Tracer
def initialize
trace "initializing..."
# ...
end
def run
trace "running..."
# ...
end
end
I have unit tests to confirm things are working well, etc, however in
complex multi-threaded code there's no substitute for the trace output
when problems arise. However even an empty method call is significant,
require 'benchmark'
include Tracer
Benchmark.bm(16) { |b|
n = 10_000_000
b.report("with trace") { n.times { trace } }
b.report("without trace") { n.times { } }
}
user system total real
with trace 3.090000 0.000000 3.090000 ( 3.094240)
without trace 1.010000 0.000000 1.010000 ( 1.015994)
So ... why not ...
# Manipulate the AST
SyntaxTree.each_node { |node|
if node.ast_type == :method_call and node.method_name == "trace"
node.ast_type = :noop # or remove it, or whatever
end
}
# No more trace statements!
Application.new.run
Now I could gsub out those trace statements manually (or for a cleaner
approach maybe ParseTree on RubyForge could be used). But that extra
step is cumbersome compared to the magic I desire. If SyntaxTree were
implemented, I think we would be close to having that bit of power
which lisp provides but ruby does not. Removing trace statements
would only be a trivial use of this Ultimate Power!
In my example SyntaxTree is using the code running in memory, but in
principle I could say
code = SyntaxTree.entry_point { Application.new.run }
code.each_node { |node|
# ... manipulate the code ...
}
# Execute some alternate-universe version of Application.new.run
code.call
Now THAT would be getting lispy.