How to duplicate a object changing the class without attributes memory copy

Hi, I’m doing a server and want to avoid memory innecesary operations.
I have an array of headers:
headers_array

Each header is an object of “Header” class:

class Header
attr_accessor :name, :body
def initialize(name, body)
@name = name
@body = body
end
end

There are also others specific headers soons of “Header” class:

class From < Header
attr_accessor :uri
end

At the beggining “headers_array” just contain “Header” objects but
after inspection I want to replace the header with @name=‘From’ with a
“From” object but since “name” and “body” attributes are the same I
don’t want a memory copy operation to allocate space for new object.

This is: I just want to change the Class of a “Header” object to
“From” class, keeping the attributes without memory copy operation, is
there any way? I imagine in C I’d do it by using pointers.

Thanks for any help.

2008/4/12, Joel VanderWerf [email protected]:

Why do you need a From class that is distinct from Header?

Because in an initial parsing I just get a headers array, whiotu
inspecting each of them.
Later, if I need, I look for some specific headers (From, To…) and
need to add some methods to them.

end

or maybe something like:

h.extend const_get(h.name)

end

Thanks, this is great! I didn’t know “extend” method.

Iñaki Baz C. wrote:

  @body = body

At the beggining “headers_array” just contain “Header” objects but
after inspection I want to replace the header with @name=‘From’ with a
“From” object but since “name” and “body” attributes are the same I
don’t want a memory copy operation to allocate space for new object.

This is: I just want to change the Class of a “Header” object to
“From” class, keeping the attributes without memory copy operation, is
there any way? I imagine in C I’d do it by using pointers.

Why do you need a From class that is distinct from Header? Depending on
the reason, it might work to make From a module:

module From

special From methods here

end

headers.each do |h|
if h.name == “From”
h.extend From
end

or maybe something like:

h.extend const_get(h.name)

end

2008/4/12, Iñaki Baz C. [email protected]:

2008/4/12, Joel VanderWerf [email protected]:

Why do you need a From class that is distinct from Header?

Because in an initial parsing I just get a headers array, whiotu
inspecting each of them.
Later, if I need, I look for some specific headers (From, To…) and
need to add some methods to them.

IMHO it is more efficient and less error prone if you create
appropriate instances during initial parsing. You have all the
information at that point in time plus you you save one additional
pass through the collection.

end

or maybe something like:

h.extend const_get(h.name)

end

Thanks, this is great! I didn’t know “extend” method.

Well, you can even do it during construction:

class Header
attr_accessor :name, :body
def initialize(name, body)
@name = name
@body = body
extend From if /From/ =~ name
end
end

But I’d rather leave the decision to the parsing code.

Cheers

robert

El Lunes, 14 de Abril de 2008, Robert K.
escribió:> appropriate instances during initial parsing. You have all the

information at that point in time plus you you save one additional
pass through the collection.

Yes, but let me explain:

I’m doing a SIP protocol parser. In SIP a repeated request can be
received
because retransmissions and there is no need at all of parsing the
entire
request to know if it’s a retransmission (since it will be discarded).
Also, I don’t need to parse all the headers, but I cannot know which
headers
I’ll need to parse since that is a application layer decission instead
of
transport layer decission.
For example: If I implement a SIp proxy I just need to parse some
headers, if
I do a SIP server UAS I need to parse others. Transport layer is common
but
application layer not, so I don’t need to do all the parsing in
transport
layer.

Thanks a lot for all you suggestions and help. Best regards.

On Apr 11, 2008, at 7:41 AM, Iñaki Baz C. wrote:

At the beggining “headers_array” just contain “Header” objects but
after inspection I want to replace the header with @name=‘From’ with a
“From” object but since “name” and “body” attributes are the same I
don’t want a memory copy operation to allocate space for new object.

This is: I just want to change the Class of a “Header” object to
“From” class, keeping the attributes without memory copy operation, is
there any way? I imagine in C I’d do it by using pointers.

You can not change the class of an object in Ruby.

You’ll have to instantiate a new object and copy the
attributes. If you just do something like:

from_obj.name = header_obj.name

You are simply copying object references, you aren’t
copying all the associated data.

Gary W.

El Lunes, 14 de Abril de 2008, Gary W.
escribió:> If you just do something like:

from_obj.name = header_obj.name

You are simply copying object references, you aren’t
copying all the associated data.

Hi, that’s not true: if an attribute is a String then there will be
memory
copy:

class Header
attr_accessor :name
end

class From
attr_accessor :name
end

header = Header.new
header.name = “AAAA”
=> “AAAA”

from = From.new
from.name = header.name
=> “AAAA”

from.name = “BBBB”
=> “BBBB”

header.name
=> “AAAA”

As you see in the example above if the attribute is a String (or a
Fixnum and
so) attribute copy means memory dupplication. Unfortunatelly in my case
the
attribute is a String.

Regards.

Iñaki Baz C. wrote:

class Header

As you see in the example above if the attribute is a String (or a
Fixnum and so) attribute copy means memory dupplication.
Unfortunatelly in my case the attribute is a String.

Regards.

Not true. To verify it, after you do “from.name = header.name”, try
this:

puts header.name.object_id
puts from.name.object_id

You will see same object id, meaning that you have a reference, not a
new object. To make it a copy, do this:

from.name = header.name.dup

Gennady.

2008/4/15, Gennady B. [email protected]:

Not true. To verify it, after you do “from.name = header.name”, try this:

puts header.name.object_id
puts from.name.object_id

You will see same object id, meaning that you have a reference, not a new object.

Ohh, that’s annoying for me!
You are right, both are the same objects until I modify one of them.
I mean:

from.name = header.name
=> “AAAA”
from.name. object_id == header.name.object_id
=> true

So in this moment from.name. object_id == header.name.object_id. But
if I change the value:

from.name = “BBBB”
from.name. object_id == header.name.object_id
=> false

Then from.name. object_id != header.name.object_id, so then there are
two values in memory at same time.

Regards.

Iñaki Baz C. wrote:

Ohh, that’s annoying for me!

from.name = “BBBB”
from.name. object_id == header.name.object_id
=> false

Then from.name. object_id != header.name.object_id, so then there are
two values in memory at same time.

Regards.

You do not change the value, you just assign a reference to a new
string. To change the content of a string object you need to use
replace() on it. It looks like it omits you that “AAAA” and “BBBB” make
string objects already and not just when you assign them to a variable.

Gennady.

2008/4/15, Gennady B. [email protected]:

You do not change the value, you just assign a reference to a new string. To change the content of a string object you need to use replace() on it. It looks like it omits you that “AAAA” and “BBBB” make string objects already and not just when you assign them to a variable.

Thanks to both, I’ve understood now:

a=“AAAA”
=> “AAAA”

a.object_id
=> -606056138

a=“BBBB”
=> “BBBB”

a.object_id
=> -606063498

Thanks :slight_smile:

On Tue, Apr 15, 2008 at 10:26 AM, Iñaki Baz C. [email protected] wrote:

You are right, both are the same objects until I modify one of them. I mean:
This sentence is confusing: you don’t modify one of them, you assign
the variable
a different object:

a = “header”
b = a

a --------> “header”
^
|
|
b

b = “new header”

a --------> “header”
b --------> “new header”

The object previously referenced by both a and b has not been modified.
When you assigned a new string to b, then b referenced a different
object.

Jesus.

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