From: Bernard Lambeau Date: 2011-06-21T03:02:29+09:00 Subject: Re: What about Object#to_ruby ? --bcaec50162fbc6d2be04a628877f Content-Type: text/plain; charset=ISO-8859-1 Thanks a lot for your responses. I suspect that my question was not that clear, though. I'm not really looking or Marshal or YAML or JSON dump format, but for a method to print a ruby *literal* (I should have called it to_ruby_literal) from a ruby value, where it makes sense. The goal is to ease human-readable ruby code generation, I must add. Nowadays, using inspect works for all but a few basic values: blambeau@kali:~$ irb -r time to_ruby_literal.rb ruby-1.8.7-p334 :001 > eval(true.inspect) => true ruby-1.8.7-p334 :002 > eval(1.inspect) => 1 ruby-1.8.7-p334 :003 > eval(1.0.inspect) => 1.0 ruby-1.8.7-p334 :004 > eval(nil.inspect) => nil ruby-1.8.7-p334 :005 > eval("O'Neil".inspect) => "O'Neil" ruby-1.8.7-p334 :006 > eval('O " Dude'.inspect) => "O \" Dude" ruby-1.8.7-p334 :007 > eval([1, 2, 3].inspect) => [1, 2, 3] ruby-1.8.7-p334 :008 > eval({:hello => "world"}.inspect) => {:hello=>"world"} ruby-1.8.7-p334 :009 > eval(/[a-z]*/.inspect) => /[a-z]*/ ruby-1.8.7-p334 :010 > eval((1.0/0).inspect) NameError: (eval):1:in `irb_binding': uninitialized constant Infinity from to_ruby_literal.rb:10 from to_ruby_literal.rb:10 ruby-1.8.7-p334 :011 > eval(Time.now.inspect) SyntaxError: (eval):1:in `irb_binding': compile error (eval):1: syntax error, unexpected tINTEGER, expecting $end Mon Jun 20 20:01:19 +0200 2011 ^ from to_ruby_literal.rb:11 from to_ruby_literal.rb:11 Bernard On Mon, Jun 20, 2011 at 7:37 PM, Josh Cheek wrote: > On Mon, Jun 20, 2011 at 7:40 AM, Bernard Lambeau > wrote: > > > Hi! > > > > It's not the first time that I need a to_ruby method which would > guarantee > > the following invariant: > > > > Kernel.eval(foo.to_ruby) == foo > > > > It actually works when using inspect with most basic objects (Integer, > > String, > > True & FalseClass, etc.), without actually being the specification of > > inspect. > > > > I admit that such a feature probably only makes sense for classes that > > actually > > capture datatypes, whose instances are then true values. > > > > Does anyone know a gem that provides such a feature? To your knowledge, > > would to_ruby be a conflicting name with existing gems in the ecosystem > > or future plans for ruby itself? > > > > Just in case you ask yourself whether this feature is needed, have a look > > at rubygems itself: > > > > > https://github.com/rubygems/rubygems/blob/master/lib/rubygems/specification.rb#L1899-1915 > > > > Thanks for any suggestion, > > Bernard > > > > -- > > PhD Student, Computer Science Department, EPL/INGI, UCLouvain, Belgium > > Mail: blambeau@gmail.com > > Mobile: +32 477 24 58 61 > > Blog: http://revision-zero.org/ > > Code: http://github.com/blambeau/ > > Follow: http://twitter.com/blambeau/ > > > > # I think the following works for everything except data that contains code > itself (closures / methods) > > Datum = Struct.new :some_attribute > > data = [ > Datum.new("string"), > Datum.new(1234), > Datum.new(/regex/), > ] > > > serial = Marshal.dump data > serial # => > > "\x04\b[\bS:\nDatum\x06:\x13some_attributeI\"\vstring\x06:\x06ETS;\x00\x06;\x06i\x02\xD2\x04S;\x00\x06;\x06I/\nregex\x00\x06;\aF" > Marshal.load(serial) == data # => true > > require 'yaml' > serial = YAML.dump data > serial # => "--- \n- !ruby/struct:Datum \n > some_attribute: string\n- !ruby/struct:Datum \n some_attribute: 1234\n- > !ruby/struct:Datum \n some_attribute: !ruby/regexp /regex/\n" > YAML.load(serial) == data # => true > > --- > > I think the closest things that exist right now that would be able to do > this for closures as well, would be some of Ryan Davis' tools (last I > heard, > they don't work on 1.9, though): > https://rubygems.org/gems/ruby2ruby > https://rubygems.org/gems/ruby_parser > https://rubygems.org/gems/sexp_processor > > Rubinius might also be able to do something like this. > > > On Mon, Jun 20, 2011 at 12:20 PM, Steve Klabnik >wrote: > > > I believe pry has this kind of thing: https://github.com/banister/pry > > > > From its readme: > > > > pry(Pry):1> show-method rep -l > > > > From: /home/john/ruby/projects/pry/lib/pry/pry_instance.rb @ line 143: > > Number of lines: 6 > > > > 143: def rep(target=TOPLEVEL_BINDING) > > 144: target = Pry.binding_for(target) > > 145: result = re(target) > > 146: > > 147: show_result(result) if should_print? > > 148: end > > > > I'm admittedly uninformed, but I think they do this by keeping track of > where methods get defined, then opening that file and reading that > definition (as opposed to introspecting on the object itself) in the > example > above, for instance, they also report the file and line numbers of the rep > method. > -- PhD Student, Computer Science Department, EPL/INGI, UCLouvain, Belgium Mail: blambeau@gmail.com Mobile: +32 477 24 58 61 Blog: http://revision-zero.org/ Code: http://github.com/blambeau/ Follow: http://twitter.com/blambeau/ --bcaec50162fbc6d2be04a628877f--