yaml doesn't save Proc members

Discussion in 'Ruby' started by Dick Davies, Apr 21, 2004.

  1. Dick Davies

    Dick Davies Guest

    I'm twiddling around with a dependency tree implementation -
    a bit like rake, but for things like keeping track of what servers
    need shutting down if spamassassin has to bounce for some reason.

    It's still very theoretical, but effectively you have a node which
    has

    : a name (symbol)
    : a dependency list (array of nodes)
    : a 'users' list (array of nodes which depend on *it*)
    : a block (which gets called to 'resolve' this dependency

    I thought I'd bugger about with YAML to save and load the tree,
    but although the arrays all get laid down nicely, the blocks don't.

    When I call to_yaml, the proc is saved as an empty block,
    and when YAML.load() tries to pull it back, I get:

    NoMethodError: allocator undefined for Proc
    /data/ruby/lib/ruby/1.9/yaml.rb:171:in `load'
    /data/ruby/lib/ruby/1.9/yaml.rb:171:in `object_maker'
    /data/ruby/lib/ruby/1.9/yaml/rubytypes.rb:36
    /data/ruby/lib/ruby/1.9/yaml/rubytypes.rb:34:in `call'
    /data/ruby/lib/ruby/1.9/yaml.rb:39:in `load'
    /data/ruby/lib/ruby/1.9/yaml.rb:39:in `load'
    test/fuct_test_knot_yaml.rb:55:in `test_yaml_block'

    So I guess I need another way to attach behaviour to a node...
    would singleton methods have the same problem ?
    I'm not big on inheritance....

    --
    I don't like spinach, and I'm glad I don't, because if I
    liked it I'd eat it, and I just hate it.
    -- Clarence Darrow
    Rasputin :: Jack of All Trades - Master of Nuns
     
    Dick Davies, Apr 21, 2004
    #1
    1. Advertising

  2. Dick Davies

    Ara.T.Howard Guest

    On Thu, 22 Apr 2004, Dick Davies wrote:

    >
    > I'm twiddling around with a dependency tree implementation -
    > a bit like rake, but for things like keeping track of what servers
    > need shutting down if spamassassin has to bounce for some reason.
    >
    > It's still very theoretical, but effectively you have a node which
    > has
    >
    > : a name (symbol)
    > : a dependency list (array of nodes)
    > : a 'users' list (array of nodes which depend on *it*)
    > : a block (which gets called to 'resolve' this dependency
    >
    > I thought I'd bugger about with YAML to save and load the tree,
    > but although the arrays all get laid down nicely, the blocks don't.
    >
    > When I call to_yaml, the proc is saved as an empty block,
    > and when YAML.load() tries to pull it back, I get:
    >
    > NoMethodError: allocator undefined for Proc
    > /data/ruby/lib/ruby/1.9/yaml.rb:171:in `load'
    > /data/ruby/lib/ruby/1.9/yaml.rb:171:in `object_maker'
    > /data/ruby/lib/ruby/1.9/yaml/rubytypes.rb:36
    > /data/ruby/lib/ruby/1.9/yaml/rubytypes.rb:34:in `call'
    > /data/ruby/lib/ruby/1.9/yaml.rb:39:in `load'
    > /data/ruby/lib/ruby/1.9/yaml.rb:39:in `load'
    > test/fuct_test_knot_yaml.rb:55:in `test_yaml_block'
    >
    > So I guess I need another way to attach behaviour to a node...
    > would singleton methods have the same problem ?
    > I'm not big on inheritance....


    if the resolve code is not too dynamic you could create a command class that
    does the work differently based on how it is constructed:

    class Resolver
    def initialize(type, opts)
    case type
    when :foo
    @type = :foo
    @a, @b = opts[:a], opts[:b]
    when :bar
    @type = :bar
    @c, @d = opts[:c], opts[:d]
    end
    end

    def resovle deps
    case type
    when :foo
    # do something with deps and @a and @b
    when :bar
    # do something with deps and @c and @d
    end
    end
    end


    even simpler, and nice and ugly, is to do something like:

    ~ > cat foo.rb
    resolve_code = 'lambda{|x| p x}'
    resolve = eval resolve_code
    resolve.call 42

    ~ > ruby foo.rb
    42

    if you never store the actual proc object as an instance var you'll not have
    any problems marshaling/demarshaling - or you could define a custom to_yaml
    method...


    another approach i've taken with marshal is

    ~ > cat foo.rb
    class Node
    def initialize(*args)
    @args = args
    @a, @b = @args
    end
    def dump
    @args.dump
    end
    def to_s; "#{ @a }#{ @b }"; end
    def self.load data
    args = data.load
    self.new *args
    end
    end

    n = Node.new(1 << 2, 1 << 1)
    n = Marshal.load(Marshal.dump(n))
    puts n

    ~ > ruby foo.rb
    42

    you could do the same with to_yaml - simply re-create the object instead of
    restoring it...


    -a
    --
    ===============================================================================
    | EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
    | PHONE :: 303.497.6469
    | ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
    | URL :: http://www.ngdc.noaa.gov/stp/
    | TRY :: for l in ruby perl;do $l -e "print \"\x3a\x2d\x29\x0a\"";done
    ===============================================================================
     
    Ara.T.Howard, Apr 21, 2004
    #2
    1. Advertising

  3. Dick Davies wrote:

    > I thought I'd bugger about with YAML to save and load the tree,
    > but although the arrays all get laid down nicely, the blocks don't.
    >
    > When I call to_yaml, the proc is saved as an empty block,
    > and when YAML.load() tries to pull it back, I get:
    >
    > NoMethodError: allocator undefined for Proc


    I've written some code which will allow to serialize Procs under
    specific conditions. It's limited and won't work with everything even if
    it were more complete than my current version.

    It might however be able to do what you want, in this case.

    Anyway, it's available at
    http://noegnud.sourceforge.net/flgr/proc_source.rb -- it might be worth
    a try.

    Regards,
    Florian Gross
     
    Florian Gross, Apr 21, 2004
    #3
  4. Dick Davies

    Mark Hubbart Guest

    On Apr 21, 2004, at 8:59 AM, Dick Davies wrote:

    >
    > I'm twiddling around with a dependency tree implementation -
    > a bit like rake, but for things like keeping track of what servers
    > need shutting down if spamassassin has to bounce for some reason.
    >
    > It's still very theoretical, but effectively you have a node which
    > has
    >
    > : a name (symbol)
    > : a dependency list (array of nodes)
    > : a 'users' list (array of nodes which depend on *it*)
    > : a block (which gets called to 'resolve' this dependency
    >
    > I thought I'd bugger about with YAML to save and load the tree,
    > but although the arrays all get laid down nicely, the blocks don't.


    Ruby pretty much discards the code once it has been compiled; there is
    no way to get it back without re-parsing the script and selecting out
    the original definition.

    I would suggest that you might want to store the block/proc as a string
    form the beginning, and eval it when you want the actual block:

    block = "{|n| n * 3 }"
    (0..5).map &eval("proc " + block)

    that way you can store the block in a yaml document, albeit as a string.

    > When I call to_yaml, the proc is saved as an empty block,
    > and when YAML.load() tries to pull it back, I get:
    >
    > NoMethodError: allocator undefined for Proc
    > /data/ruby/lib/ruby/1.9/yaml.rb:171:in `load'
    > /data/ruby/lib/ruby/1.9/yaml.rb:171:in `object_maker'
    > /data/ruby/lib/ruby/1.9/yaml/rubytypes.rb:36
    > /data/ruby/lib/ruby/1.9/yaml/rubytypes.rb:34:in `call'
    > /data/ruby/lib/ruby/1.9/yaml.rb:39:in `load'
    > /data/ruby/lib/ruby/1.9/yaml.rb:39:in `load'
    > test/fuct_test_knot_yaml.rb:55:in `test_yaml_block'
    >
    > So I guess I need another way to attach behaviour to a node...
    > would singleton methods have the same problem ?
    > I'm not big on inheritance....
    >
    > --
    > I don't like spinach, and I'm glad I don't, because if I
    > liked it I'd eat it, and I just hate it.
    > -- Clarence Darrow
    > Rasputin :: Jack of All Trades - Master of Nuns
    >
     
    Mark Hubbart, Apr 21, 2004
    #4
  5. At 02:49 22/04/2004 +0900, you wrote:
    >Dick Davies wrote:
    >
    >>I thought I'd bugger about with YAML to save and load the tree,
    >>but although the arrays all get laid down nicely, the blocks don't.
    >>When I call to_yaml, the proc is saved as an empty block,
    >>and when YAML.load() tries to pull it back, I get:
    >>NoMethodError: allocator undefined for Proc

    >
    >I've written some code which will allow to serialize Procs under specific
    >conditions. It's limited and won't work with everything even if it were
    >more complete than my current version.
    >
    >It might however be able to do what you want, in this case.
    >
    >Anyway, it's available at
    >http://noegnud.sourceforge.net/flgr/proc_source.rb -- it might be worth a try.
    >
    >Regards,
    >Florian Gross


    I had a look at it. It basically uses Proc##inspect() to get the file/line
    where the proc is defined. Then, using IRB's Lexer, the proc's definition
    is grabbed. Some additional stuff handles cases where proc isn't defined
    in a file (if def in some eval() for example).

    I liked the code and I am injecting it (after some major refactoring) in my
    own code.

    Yamlizing Proc/s is for sure cool.

    Thanks Florian.


    -------------------------------------------------------------------------
    Web: http://hdl.handle.net/1030.37/1.1
    Phone: +33 (0) 4 92 27 74 17
     
    Jean-Hugues ROBERT, Apr 27, 2004
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. David Lozzi
    Replies:
    3
    Views:
    1,972
    David Lozzi
    Jun 1, 2005
  2. NevilleDNZ
    Replies:
    9
    Views:
    457
    NevilleDNZ
    Aug 16, 2006
  3. RubyQuestions
    Replies:
    0
    Views:
    241
    RubyQuestions
    Dec 3, 2003
  4. Jean-Hugues ROBERT

    Why no Proc##[]=() ? Why no Proc##replace() ?

    Jean-Hugues ROBERT, May 1, 2004, in forum: Ruby
    Replies:
    14
    Views:
    309
    Jean-Hugues ROBERT
    May 5, 2004
  5. Minkoo Seo

    Proc vs lambda vs proc

    Minkoo Seo, Feb 4, 2007, in forum: Ruby
    Replies:
    19
    Views:
    256
    Brian Candler
    Feb 6, 2007
Loading...

Share This Page