Duping a class causes error

Maybe someone can offer me a possible reason for this. I have a set of
classes in a module called Markers. I have a module method,
Markers#list, that does nothing more than collects them into an array.
Then in my program when I do:

markers = Markers.list

It works. But when I do:

markers = Markers.list.collect { |m| nm = m.dup ; nm }

It does not work.

I don't understand why. Obviously my initial thought is that something
about my Marker classes must not be shallow, but they're just classes,
made of methods and have no state, so I don't see how that can be.
(Actually they do have a small bit of boolean state in a class instance
var, but I check and it is being duplicated.)
I just don't get it. Any ideas?

Thanks,
T.

"Trans" <transfire@gmail.com> schrieb im Newsbeitrag
news:1106832987.976217.139210@f14g2000cwb.googlegroups.com...

Maybe someone can offer me a possible reason for this. I have a set of
classes in a module called Markers. I have a module method,
Markers#list, that does nothing more than collects them into an array.
Then in my program when I do:

> markers = Markers.list

It works. But when I do:

> markers = Markers.list.collect { |m| nm = m.dup ; nm }

You can also do:

markers = Markers.list.collect { |m| m.dup }

It does not work.

I don't understand why. Obviously my initial thought is that something
about my Marker classes must not be shallow, but they're just classes,
made of methods and have no state, so I don't see how that can be.

So Markers.list returns a list of class objects?

(Actually they do have a small bit of boolean state in a class instance
var, but I check and it is being duplicated.)
I just don't get it. Any ideas?

What exactly goes wrong?

    robert

Robert Klemme wrote:

"Trans" <transfire@gmail.com> schrieb im Newsbeitrag
news:1106832987.976217.139210@f14g2000cwb.googlegroups.com...
> Maybe someone can offer me a possible reason for this. I have a set

of

> classes in a module called Markers. I have a module method,
> Markers#list, that does nothing more than collects them into an

array.

> Then in my program when I do:
>
> > markers = Markers.list
>
> It works. But when I do:
>
> > markers = Markers.list.collect { |m| nm = m.dup ; nm }

You can also do:

markers = Markers.list.collect { |m| m.dup }

Thanks. That true, but the line I ultimately want is:

markers = Markers.list.collect { |m| nm = m.dup ; nm.parser = self;

nm }

I need to pass the current parser object down to the markers themselves
b/c I do "reentrant" pasrsing. But obviously I don't want to effect the
Classes themselves with this state info in case they are used by
another parser, so I'm duplicating them.

> It does not work.
>
> I don't understand why. Obviously my initial thought is that

something

> about my Marker classes must not be shallow, but they're just

classes,

> made of methods and have no state, so I don't see how that can be.

So Markers.list returns a list of class objects?

Yes. Here, Markers.list returns

[MarkUps::Markers::Command, MarkUps::Markers::Verbatim,
MarkUps::Markers::Outline, MarkUps::Markers::Document,
MarkUps::Markers::Paragraph, MarkUps::Markers::Table]

and the dup'd collection returns:

[#<Class:0x4033a584>, #<Class:0x4033a534>, #<Class:0x4033a4f8>,
#<Class:0x4033a4a8>, #<Class:0x4033a480>, #<Class:0x4033a444>]

> (Actually they do have a small bit of boolean state in a class

instance

> var, but I check and it is being duplicated.)
> I just don't get it. Any ideas?

What exactly goes wrong?

Unfortunately it is strange. The Outline Marker which tells the parser
how to identify and parse an outline fails.

T.

Up. I figured it out.

And take a wild guess what the problem was! There's a riddle for you:
What gets lost when you copy a class to a variable?
Ex-

x = String.dup

Answer coming up....

No stabs? Okay well the answer is: the name.
x = String.dup
p x.name
=> ""

T.

"Trans" <transfire@gmail.com> schrieb im Newsbeitrag
news:1106836381.414471.268130@c13g2000cwb.googlegroups.com...

Up. I figured it out.

And take a wild guess what the problem was! There's a riddle for you:
What gets lost when you copy a class to a variable?
Ex-
>
> x = String.dup
>

Answer coming up....

The name

    robert

Correct!

Unfortunately you were a minute late on the buzzer so we can only off
you the consolation prize --a virtual pat on the back. "pat, pat" :slight_smile:

But seriously, thanks robert, your questioning spurred me to dig in and
find the problem. And its a good thing to remember!

T.

"Trans" <transfire@gmail.com> schrieb im Newsbeitrag
news:1106841626.063762.97840@f14g2000cwb.googlegroups.com...

Correct!

Yippieh!

Unfortunately you were a minute late on the buzzer so we can only off
you the consolation prize --a virtual pat on the back. "pat, pat" :slight_smile:

Darn...

But seriously, thanks robert, your questioning spurred me to dig in and
find the problem. And its a good thing to remember!

Glad I could help. Btw, why is it that you dup classes? It seems strange
to me and there might some dangers, especially if those classes to be
duped refer each other:

class Foo; end

=> nil

class Bar; XX = Foo; end

=> Foo

Bar::XX

=> Foo

Bar::XX == Foo

=> true

bd = Bar.dup

=> #<Class:0x10181848>

bd::XX

=> Foo

bd::XX == Foo

=> true

class Box; def test() Foo; end end

=> nil

Box.new.test

=> Foo

Box.dup.new.test

Even Marshal doesn't help:

=> Foo>> Marshal::load(Marshal::dump(Box)).new.test == Foo
=> true

Marshal::load(Marshal::dump(Bar))::XX == Foo

=> true

Kind regards

    robert

Good point. Fortunately these classes are all self contained beyond
being subclasses of Marker.

The reason has to do with some trouble I alsways seem to run into with
these types of apps. Basically I have a Parser instance that gets fed
Token classes (Markers) which contain class level information on how to
recognize the relavent text they will parse. Here a very simple
example:

require 'yaml'

s = "[test]THIS IS A [b]TEST[b.]&tm;[test.]"

class XmlTagToken < Parser::Token
normal!
def self.start( match ) ; %r{ \[ (.*?) \] }mx ; end
def self.stop( match ) ; %r{ \[ [ ]* (#{Regexp.escape(match[1])})
(.*?) \. \] }mx ; end
end

class XmlEntityToken < Parser::Token
unit!
def self.start( match ) ; %r{ \& (.*?) \; }x ; end
end

registry = Parser::Registry.new
registry.register( XmlTagToken )
registry.register( XmlEntityToken )

cp = Parser.new( registry )
d = cp.parse( s )
y d

The I take this further and add instance methods to the tokens to parse
sepecialize content. Sometimes that content is "reentrant", that is to
say I need to reparse it --like an embedded document.

So the problem? How do I talk to my Parser instance from within an
instance of a Token?

If you have an elgant solution to that I'll give you more than a pat on
the back!

T.

Good point. Fortunately these classes are all self contained beyond
being subclasses of Marker.

The reason has to do with some trouble I alsways seem to run into with
these types of apps. Basically I have a Parser instance that gets fed
Token classes (Markers) which contain class level information on how to
recognize the relavent text they will parse. Here a very simple
example:

         [...]

registry = Parser::Registry.new
registry.register( XmlTagToken )
registry.register( XmlEntityToken )

cp = Parser.new( registry )
d = cp.parse( s )
y d

The I take this further and add instance methods to the tokens to parse
sepecialize content. Sometimes that content is "reentrant", that is to
say I need to reparse it --like an embedded document.

So the problem? How do I talk to my Parser instance from within an
instance of a Token?

I think you need the Token to be aware of the Parser, as well as the
Parser being aware of the Token. You need to pass the one to the
other in both cases.

If I have anything like a grasp on the topic of the rest of this
sentence, then Dependency Injection may be of use here. I think
D.I. can work like a Personal Assistant, so /s?he/ tells the
colleague classes to arrange the meeting you want to have.
All the arrangements are done through /h(im|er)/, so you don't have
to worry about the details.

I might have this wrong, and it might be Model, View, Controller
that is needed here, because the controller mediates between the
Model and the View. This would suggest that the ownership
relationship is not really a factor in this communication problem,
except in so far as it is where the problem arises. The analogy
might be better expressed as "Bosses can get on better with Workers
if there is a Union committed to doing something mutually beneficial
where possible", but this is probably stretching things...!

I have run into this problem myself, and have not seen a good
solutoin to it. I have a suspicion that it probably means the
separation of the two classes, in this case Parser and Token, is an incorrect model, because they both need access to each other.

If you have an elgant solution to that I'll give you more than a
pat on the back!

T.

         Hugh

···

On Fri, 28 Jan 2005, Trans wrote:

I have run into this problem myself, and have not seen a good
solutoin to it. I have a suspicion that it probably means the
separation of the two classes, in this case Parser and Token,
is an incorrect model, because they both need access to each
other.

Hmm... I'm not sure how that can be outside of through OOP out the
window. If I combine the Token and the Parser into a single thing then
that will really be the only thing there is :wink:

I'll think on it some more though.
I take it you've looked at parser.rb then?

T.

I have run into this problem myself, and have not seen a good
solutoin to it. I have a suspicion that it probably means the
separation of the two classes, in this case Parser and Token,
is an incorrect model, because they both need access to each
other.

Hmm... I'm not sure how that can be outside of through OOP out the
window. If I combine the Token and the Parser into a single thing then
that will really be the only thing there is :wink:

Yes. That's why I only consider it a suspicion, and why I say I
haven't seen a good answer to it yet.

Thinking out loud: What if when instance vars were created they got
a container() method which returned the containing class? Or maybe
have a contains keyword like attr (and friends) that sets this up
for you. It feels like unwanted coupling, though.

In thinking Forth (http://thinking-forth.sourceforge.net/\) Leo
Brodie says that such a case should have the commonality extracted
into an interface, each side talking to the interface in the way
that is most suitable. Then outsiders can get at the interface.
[This is paraphrased from memory. Oh, just a minute...]
"Tip
Both data structures and the commands involved in the communication
of data
between modules should be localized in an interface component."
This means you can change the interface easily later.

This begins to look like "model, view, controller" to me.

I'll think on it some more though.
I take it you've looked at parser.rb then?

Yes, it looks good but I've not got far with it yet.

T.

         Hugh

···

On Fri, 28 Jan 2005, Trans wrote:

"Hugh Sasse Staff Elec Eng" <hgs@dmu.ac.uk> schrieb im Newsbeitrag news:Pine.GSO.4.60.0501271730040.4366@brains.eng.cse.dmu.ac.uk...

I have run into this problem myself, and have not seen a good
solutoin to it. I have a suspicion that it probably means the
separation of the two classes, in this case Parser and Token,
is an incorrect model, because they both need access to each
other.

Hmm... I'm not sure how that can be outside of through OOP out the
window. If I combine the Token and the Parser into a single thing then
that will really be the only thing there is :wink:

Yes. That's why I only consider it a suspicion, and why I say I
haven't seen a good answer to it yet.

Not much time, so just a short anwer in between: I think the proper model is a parsing context. Part of that context could be a stack of parsers or a current parser that knows its ancestor. I would definitely not use classes here but instances.

Thinking out loud: What if when instance vars were created they got
a container() method which returned the containing class? Or maybe
have a contains keyword like attr (and friends) that sets this up
for you. It feels like unwanted coupling, though.

Yeah, but that's the solution. The context can have factory methods for this.

module ContextAware
  attr_accessor :context
end

class Context
def create(cl,*a, &b)
  x = cl.new(*a, &b)
  x.context = self if ContextAware === x
  x
end

....

Cheers

    robert

···

On Fri, 28 Jan 2005, Trans wrote:

In thinking Forth (http://thinking-forth.sourceforge.net/\) Leo
Brodie says that such a case should have the commonality extracted
into an interface, each side talking to the interface in the way
that is most suitable. Then outsiders can get at the interface.
[This is paraphrased from memory. Oh, just a minute...]
"Tip
Both data structures and the commands involved in the communication
of data
between modules should be localized in an interface component."
This means you can change the interface easily later.

This begins to look like "model, view, controller" to me.

I'll think on it some more though.
I take it you've looked at parser.rb then?

Yes, it looks good but I've not got far with it yet.

T.

        Hugh

Yes, it looks good but I've not got far with it yet.

Great.

FYI, I'm still improving on it. Will send update later today. I have
made one improvement to the inteface and another bug has been rooted
out.

T.

Sorry for delay. Struggled with a couple nasty/subtle bugs. But now it
looks alot better. I have one more thing to do. I'm gogin to make the
parser it self tell the tokens about it, though I wuold like to figure
out how to copy classes and give them a name, instead of them appearing
as numbers on #inspect.

T.

Trans schrieb:

(...) though I would like to figure
out how to copy classes and give them a name, instead of them appearing
as numbers on #inspect.

   c = String.dup

   def c.to_s
     "MySpecialString"
   end

Regards,
Pit

"Pit Capitain" <pit@capitain.de> schrieb im Newsbeitrag
news:41F9E97C.2030006@capitain.de...

Trans schrieb:
> (...) though I would like to figure
> out how to copy classes and give them a name, instead of them

appearing

> as numbers on #inspect.

I would not do this. IMHO even from a conceptual point of view you rather
want instances and not classes. Did you consider my remark about parsing
context?

   c = String.dup

   def c.to_s
     "MySpecialString"
   end

I guess that's not the same as there is some magic involved with class
names:

c = Class.new

=> #<Class:0x1018ab00>

c.name

=> ""

Foo = c

=> Foo

c.name

=> "Foo"

Foo.name

=> "Foo"

Bar = c

=> Foo

Bar.name

=> "Foo"

c.name

=> "Foo"

Kind regards

    robert

Robert Klemme schrieb:

"Pit Capitain" <pit@capitain.de> schrieb im Newsbeitrag
news:41F9E97C.2030006@capitain.de...

Trans schrieb:

(...) though I would like to figure
out how to copy classes and give them a name, instead of them
appearing as numbers on #inspect.

...

  c = String.dup

  def c.to_s
    "MySpecialString"
  end

...
>

I guess that's not the same as there is some magic involved with class
names:

...

Hi Robert,

I thought Tom was talking about the textual representation of his class copies when calling inspect on them. My simple code was an answer to this problem.

I didn't talk about the name of a class object as returned by the name method. IIRC it has been mentioned at least once on this mailing list that the name of a class object is the name of the first constant this class object is assigned to, as your code shows.

Regards,
Pit

Hi,

I guess that's not the same as there is some magic involved with class
names:

>> c = Class.new
=> #<Class:0x1018ab00>
>> c.name
=> ""
>> Foo = c
=> Foo
>> c.name
=> "Foo"
>> Foo.name
=> "Foo"
>> Bar = c
=> Foo
>> Bar.name
=> "Foo"
>> c.name
=> "Foo"

There's nothing magic. The first constant's name that the
class is assigned to will be the classes name.

  c=Class.new #=> #<Class:0x401e8874>
  d=c #=> #<Class:0x401e8874>
  e=d #=> #<Class:0x401e8874>
  F=e #=> F
  G=c #=> F
  c.name #=> "F"

Bertram

···

Am Freitag, 28. Jan 2005, 19:05:54 +0900 schrieb Robert Klemme:

--
Bertram Scharpf
Stuttgart, Deutschland/Germany
http://www.bertram-scharpf.de

"Pit Capitain" <pit@capitain.de> schrieb im Newsbeitrag
news:41FA17DF.1060206@capitain.de...

Robert Klemme schrieb:
> "Pit Capitain" <pit@capitain.de> schrieb im Newsbeitrag
> news:41F9E97C.2030006@capitain.de...
>
>>Trans schrieb:
>>
>>>(...) though I would like to figure
>>>out how to copy classes and give them a name, instead of them
>>>appearing as numbers on #inspect.
>>>
..
>>
>> c = String.dup
>>
>> def c.to_s
>> "MySpecialString"
>> end
>>
..
>
> I guess that's not the same as there is some magic involved with class
> names:
>
..

Hi Robert,

I thought Tom was talking about the textual representation of his class

copies

when calling inspect on them. My simple code was an answer to this

problem.

Ah, ok. Although in that case you probably want to override #inspect.

I didn't talk about the name of a class object as returned by the name

method.

IIRC it has been mentioned at least once on this mailing list that the

name of a

class object is the name of the first constant this class object is

assigned to,

as your code shows.

Yep.

Regards

    robert