"Anonymous classes or modules", what they are? (Marshaling)

I’m trying to find out if is possible to serialize a class object, with
their own instance variables, something like this:

class Foo
@x = 10
@y = 20
end

Then I went to Dave T. book: Programming Ruby 1.9 to the section
which talk about Marshal. It say literaly:

“Some objects cannot be dumped: if the objects to be dumped include
bindings, procedure or method objects, instances of class IO, or
singleton objects, or if you try to dump anonymous classes or modules, a
TypeError will be raised.”

So obvious Foo is not a singleton object, is a class object. I’ve tried
to Marshal this class in the common way and succed, no TypeError arised.
But when I restore, no clue about his own instance variables. I wonder
what does mean Dave when he say “anonymous classes or modules”…
I’ve opened a topic short time ago related with this, asking about
marshaling classes and his class variables, I surrendered trying to save
classes with his class variables but what about his own instance
variables, It is not a common object? I just can’t? What is the option
to serialize this kind of data? Do I have to appeal to metaprogramming?
Thank you guys.

Damián M. González писал 16.09.2012 02:49:

which talk about Marshal. It say literaly:
arised.
metaprogramming?
Thank you guys.

Ruby does not support serializing code. At all. If you serialize
something
that includes methods, these methods will not be written to disk.

In other words, you cannot meaningfully serialize classes. When you
serialize
a Class instance, only its name gets written. See:
irb > class Klass; @x = 0; end
=> 0
irb > Marshal.dump Klass
=> “\x04\bc\nKlass”
irb > Object.send :remove_const, :Klass
=> A
irb > Klass = 0
=> 0
irb > Marshal.load “\x04\bc\nKlass”
TypeError: Klass does not refer to class/module
from (irb):10:in load' from (irb):10 from /home/whitequark/.rvm/rubies/ruby-1.9.3-p194/bin/irb:16:in

Also, as the name is used to find a class, you cannot meaningfully
serialize
instances of anonymous classes either. see:
irb > k = Class.new
=> #Class:0x0000000085ea80
irb > Marshal.dump k.new
TypeError: can’t dump anonymous class #Class:0x0000000085ea80
from (irb):13:in dump' from (irb):13 from /home/whitequark/.rvm/rubies/ruby-1.9.3-p194/bin/irb:16:in

I’m not sure as what was mentioned in the book as I don’t have it, but
I guess
that it was only talking about instances of anonymous classes. You
don’t often
need to serialize classes themselves, and, as I’ve mentioned, you
cannot serialize
code, be that closures or methods. Objects with singleton methods will
have those
singleton methods lost:
irb > obj = Object.new
=> #Object:0x000000008833a8
irb > def obj.bark
irb > puts “Howl!”
irb > end
=> nil
irb > serial = Marshal.dump(obj)
TypeError: singleton can’t be dumped
from (irb):18:in dump' from (irb):18 from /home/whitequark/.rvm/rubies/ruby-1.9.3-p194/bin/irb:16:in

Damián M. González wrote in post #1076192:

“Some objects cannot be dumped: if the objects to be dumped include
bindings, procedure or method objects, instances of class IO, or
singleton objects, or if you try to dump anonymous classes or modules, a
TypeError will be raised.”

Here are examples of each of these in turn, presented as a member of a
vanilla Hash object. They all fail.

Marshal.dump(“foo” => binding)
Marshal.dump(“foo” => Proc.new { 0 })
Marshal.dump(“foo” => method(:puts))
Marshal.dump(“foo” => File.open("/etc/passwd"))

a = “bar”
def a.baz; 0; end
Marshal.dump(“foo” =>a)

Marshal.dump(“foo” => Class.new)
Marshal.dump(“foo” => Module.new)

So obvious Foo is not a singleton object, is a class object. I’ve tried
to Marshal this class in the common way and succed, no TypeError arised.
But when I restore, no clue about his own instance variables.

Correct, for more info see http://www.ruby-forum.com/topic/4405722

I wonder
what does mean Dave when he say “anonymous classes or modules”…

A class which is not assigned to a constant.

an anonymous class

k = Class.new
p k # => #Class:0x10640d5d8

But there is special voodoo the first time you do assign it to a
constant.

Foo = k
p k # => Foo

The class “knows” that its name is Foo. Normally, objects don’t know
what variables and/or constants reference them.

I’ve opened a topic short time ago related with this, asking about
marshaling classes and his class variables, I surrendered trying to save
classes with his class variables but what about his own instance
variables, It is not a common object?

It is, but this is a special case.

{“foo” => String, “bar” => Array}
is serialised as just references to the class named “String” and “Array”

If it worked the way you wanted, then instead of serializing the name it
would have to serialize everything needed to reconstruct the classes
“String” and “Array” - including the methods.

So what we gain is the ability to have objects which contain references
to (named) classes, which is useful, without being able to serialize the
classes themselves.

Peter Z. wrote in post #1076193:

I’m not sure as what was mentioned in the book as I don’t have it, but
I guess
that it was only talking about instances of anonymous classes. You
don’t often
need to serialize classes themselves, and, as I’ve mentioned, you
cannot serialize
code, be that closures or methods. Objects with singleton methods will
have those
singleton methods lost:
irb > obj = Object.new
=> #Object:0x000000008833a8
irb > def obj.bark
irb > puts “Howl!”
irb > end
=> nil
irb > serial = Marshal.dump(obj)
TypeError: singleton can’t be dumped
from (irb):18:in dump' from (irb):18 from /home/whitequark/.rvm/rubies/ruby-1.9.3-p194/bin/irb:16:in

Is not code what I’m trying to serialize just the state of a class, of
the class object itself, so when the program start it require all the
files needed, included the file which have the class definition, let
say:

#encoding: utf-8
class Foo
@re = 5
def initialize(nickname)
@nickname = nickname
end
def self.change_re(n)
@re = n
end
def self.get_re
@re
end
end

Then I want to “refresh” the state of this object, the class object.
Let’s suppose that when the program was closed, @re was 56, so I want to
“start” in some way, with this variable settled to 56, not 5. I’m clear
explaining? That is just what I need to do, if you can give me a trick
about what’s the best way to save this state and restore it I’ll be very
thankfull. :slight_smile:

Damián M. González wrote in post #1076236:

Brian C. wrote in post #1076224:

It is, but this is a special case.

{“foo” => String, “bar” => Array}
is serialised as just references to the class named “String” and “Array”

If it worked the way you wanted, then instead of serializing the name it
would have to serialize everything needed to reconstruct the classes
“String” and “Array” - including the methods.

So what we gain is the ability to have objects which contain references
to (named) classes, which is useful, without being able to serialize the
classes themselves.

Can you give me a short example?

Any object which includes a Class in an instance variable. I dunno:

class Factory
def initialize(klass)
@klass = klass
end
def make(*args)
@klass.new(*args)
end
end

class Foo
class <<self; attr_accessor :count; end
@count = 1
end

f = Factory.new(Foo)
f.make
p Marshal.dump(f)

Now I can happily Marshal.dump(f), even though it contains a reference
to a class (Foo). When I reload the object later, it will still contain
a reference to class Foo. However no attempt is made to restore the
state of Foo itself; that would be an unwanted side-effect, to have the
current class Foo’s state changed to how it was at the time when f was
serialized.

The alternative would be to return an anonymous class with the state of
Foo at the time when f was serialized. However that’s not an accurate
representation of f (it wasn’t pointing to an anonymous class, it was
pointing to Foo). Moreover, we can’t serialise anonymous classes anyway,
because that would mean serializing all the methods of that class.

The alternative would be to return an anonymous class with the state of
Foo at the time when f was serialized. However that’s not an accurate
representation of f (it wasn’t pointing to an anonymous class, it was
pointing to Foo). Moreover, we can’t serialise anonymous classes anyway,
because that would mean serializing all the methods of that class.

Correct me if I’m wrong: the only way that I see to save the state of a
class object(like Foo in your example with his variable @count), is
appeal to some methods that save the current state and then load it
again when the programm start, something like this:

######################################################

class Foo
@x = 1
class << self
attr_accessor :x
def save_state
a = Object.new
a.instance_eval do
@x = Foo.x
end
File.open(‘Foo_state.mrs’, ‘w+’) do |f|
Marshal.dump(a, f)
end
end
def load_state
b = Marshal.load(File.open(‘Foo_state.mrs’).read)
Foo.x = b.instance_variable_get(:@x)
end
end
end

if File.exist?(‘Foo_state.mrs’) then Foo.load_state end

########################################################

#Start the program for the first time
Foo.x
#=> 1
Foo.x = 5
#=> 5
Foo.save_state
#=> #<File:Foo_state.mrs (closed)>
#Here I close the program…

#Then I start it again
Foo.x
#=> 5
#Was correctly saved and loaded

I’ll wait for your answers :slight_smile:

Brian C. wrote in post #1076224:

It is, but this is a special case.

{“foo” => String, “bar” => Array}
is serialised as just references to the class named “String” and “Array”

If it worked the way you wanted, then instead of serializing the name it
would have to serialize everything needed to reconstruct the classes
“String” and “Array” - including the methods.

So what we gain is the ability to have objects which contain references
to (named) classes, which is useful, without being able to serialize the
classes themselves.

Can you give me a short example?

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs