Dominik Bathon
7/10/2005 10:08:00 PM
On Sun, 10 Jul 2005 21:25:36 +0200, Robin Stocker
<robin-lists-ruby-talk@nibor.org> wrote:
> def to_proc
> # Raises exception if block isn't valid, e.g. SyntaxError.
> eval "Proc.new{ #{@block} }"
> end
>
> def method_missing( *args )
> to_proc.send( *args )
> end
Nice idea, to avoid storing the Proc object in an instance variable and so
being able to just use the default serializing. But I guess this is quite
slow ;-)
So, here is my solution. It should be almost as fast as normal procs, but
I had to implement custom serializing methods. I also implemented a custom
==, because that doesn't really work with method_missing/delegate.
require "delegate"
require "yaml"
class SProc < DelegateClass(Proc)
attr_reader :proc_src
def initialize(proc_src)
super(eval("Proc.new { #{proc_src} }"))
@proc_src = proc_src
end
def ==(other)
@proc_src == other.proc_src rescue false
end
def inspect
"#<SProc: #{@proc_src.inspect}>"
end
alias :to_s :inspect
def marshal_dump
@proc_src
end
def marshal_load(proc_src)
initialize(proc_src)
end
def to_yaml(opts = {})
YAML::quick_emit(self.object_id, opts) { |out|
out.map("!rubyquiz.com,2005/SProc" ) { |map|
map.add("proc_src", @proc_src)
}
}
end
end
YAML.add_domain_type("rubyquiz.com,2005", "SProc") { |type, val|
SProc.new(val["proc_src"])
}
if $0 == __FILE__
require "pstore"
code = SProc.new %q{ |*args|
puts "Hello world"
print "Args: "
p args
}
orig = code
code.call(1)
File.open("proc.marshalled", "w") { |file| Marshal.dump(code, file) }
code = File.open("proc.marshalled") { |file| Marshal.load(file) }
code.call(2)
store = PStore.new("proc.pstore")
store.transaction do
store["proc"] = code
end
store.transaction do
code = store["proc"]
end
code.call(3)
File.open("proc.yaml", "w") { |file| YAML.dump(code, file) }
code = File.open("proc.yaml") { |file| YAML.load(file) }
code.call(4)
p orig == code
end