Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > yaml doesn't save Proc members

Reply
Thread Tools

yaml doesn't save Proc members

 
 
Dick Davies
Guest
Posts: n/a
 
      04-21-2004

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


 
Reply With Quote
 
 
 
 
Ara.T.Howard
Guest
Posts: n/a
 
      04-21-2004
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
================================================== =============================

 
Reply With Quote
 
 
 
 
Florian Gross
Guest
Posts: n/a
 
      04-21-2004
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
 
Reply With Quote
 
Mark Hubbart
Guest
Posts: n/a
 
      04-21-2004

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
>




 
Reply With Quote
 
Jean-Hugues ROBERT
Guest
Posts: n/a
 
      04-27-2004
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



 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Proc vs lambda vs proc Minkoo Seo Ruby 19 02-06-2007 11:13 AM
proc A def/calls proc B: variable scoping rules. NevilleDNZ Python 9 08-16-2006 04:36 AM
Convert VB.NET to TSQL PROC & Reference a Proc from another Proc David Lozzi ASP .Net 3 06-01-2005 06:35 PM
Why no Proc##[]=() ? Why no Proc##replace() ? Jean-Hugues ROBERT Ruby 14 05-05-2004 01:20 PM
What is the diff btwn 'sho proc' and 'sho proc cpu' William J King Cisco 1 12-18-2003 11:50 PM



Advertisments