[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Sytem hook for instance names?

Jeff Patterson

3/23/2008 3:15:00 PM

Is there a system hook that allows a method to get an instance's symbol
from its' object id?

i.e.

a=SomeObject.new
SomeSystemhook(a) => :a (or "a" I suppose)

For the curious, here's a rather long winded explanation of what I need.

I'm writing a system simulator in ruby (think systemC). The snippet
below shows a typical invocation:

class MySim
def initialize
#
# instantiate components
@g1=Buffer.new(:g1)
@a2=Adder.new(:a2)
@d1=Dflop.new(:d1)
@d2=Dflop.new(:d2)
@clk=Clk.new(:clk)
@p3=Probe.new("d2Q") #trace d2's Q output
@d2[:Q].bind(@p3[:In])
..

# make connections
#note:
#the component master class defines:
# def [](name)
# return (@outputs+@inputs).find{|pin| name == pin.name}
# end
# so @g[:Out] returns a reference to its output pin object

@g1[:Out].bind(@a2[:I2]) # g1's Out pin -> a2's I2 pin
@d1[:Q].bind(@a2[:I1]) # etc
@clk.bind(@d1[:Clk])
..
end

def run # required call back routine for simulator engine
#control code goes here
@d1[:Rst]=set(true)
@d2[:Rst].set(true)
yield(1) # advance the simulation 1 clock period

@g1[:In].set(0.001)
@d1[:Rst].set(false)
@d2[:Rst].set(false)
yield(1000) #advance 1000 cycles
end
end

#run the simulation
sim=Simulation.new(MySim.new)
sim.run

Notice that the Sim object (with all off its components) is passed to
the Simulation engine (sim) for execution. The Simulation engine uses
Kernel#ObjectSpace to find and schedule objects it needs to manage. For
efficiency it flattens the netlist and extracts only the input pins and
clocked output pins it needs to manage. But for messaging, netlisting
etc, I want the sim engine to know the _name_ of the pins parent (as
opposed to its object_id) and I would also like to obviate the need to
redundantly pass the component's symbol name to its constructor. i.e.

instead of
@d1 = Dflop.new(:d1)

I want to be able to do:

@d1=Dflop.new

and then when the sim engine needs a human readable component name, it
somehow gets it from a system hook based on the object id.


Any help?

Jeff
--
Posted via http://www.ruby-....

14 Answers

botp

3/23/2008 4:10:00 PM

0

On Sun, Mar 23, 2008 at 11:15 PM, Jeff Patterson
<jeff_patterson@agilent.com> wrote:
> Is there a system hook that allows a method to get an instance's symbol from its' object id?

i do not understand what you mean by instance symbol but you can refer
fr an id back to the actual object if you want to. so but how about,

irb(main):021:0> a="testing"
=> "testing"
irb(main):022:0> x=a.object_id
=> -606066648
irb(main):023:0> ObjectSpace._id2ref(x)
=> "testing"
irb(main):024:0> ObjectSpace._id2ref(x).upcase!
=> "TESTING"
irb(main):025:0> a
=> "TESTING"
irb(main):026:0> b=Class.new
=> #<Class:0xb7bf9214>
irb(main):027:0> y=b.object_id
=> -606090998
irb(main):028:0> ObjectSpace._id2ref(y)
=> #<Class:0xb7bf9214>
irb(main):029:0> ObjectSpace._id2ref(y).class_eval "def hello; 'hello'; end"
=> nil
irb(main):031:0> b.new.hello
=> "hello"

hth.
kind regards -botp

Mark Bush

3/23/2008 6:30:00 PM

0

Jeff Patterson wrote:
> Is there a system hook that allows a method to get an instance's symbol
> from its' object id?
>
> i.e.
>
> a=SomeObject.new
> SomeSystemhook(a) => :a (or "a" I suppose)

The problem is that the variable is not the object, just a pointer to
it. And there can be multiple variables pointing to the object. So:

a = SomeObject.new
b = a

Now "a" and "b" both point to the same object. How would you choose
between returning :a and :b?

If you don't mind, then for instance variables you can do something
like:

def get_instance_variable_symbol_for_object v
instance_variables.each do |var|
if value = instance_variable_get(var)
return var if value.object_id.eql?(v.object_id)
end
end
end

Untested.

--
Posted via http://www.ruby-....

Robert Klemme

3/23/2008 9:33:00 PM

0

On 23.03.2008 19:30, Mark Bush wrote:
> Jeff Patterson wrote:
>> Is there a system hook that allows a method to get an instance's symbol
>> from its' object id?
>>
>> i.e.
>>
>> a=SomeObject.new
>> SomeSystemhook(a) => :a (or "a" I suppose)
>
> The problem is that the variable is not the object, just a pointer to
> it. And there can be multiple variables pointing to the object. So:
>
> a = SomeObject.new
> b = a
>
> Now "a" and "b" both point to the same object. How would you choose
> between returning :a and :b?

Plus, what would you do in this case?

a=[SomeClass.new]

Basically it makes no sense...

Cheers

robert

Robert Klemme

3/23/2008 9:55:00 PM

0

On 23.03.2008 16:15, Jeff Patterson wrote:
> Is there a system hook that allows a method to get an instance's symbol
> from its' object id?
>
> i.e.
>
> a=SomeObject.new
> SomeSystemhook(a) => :a (or "a" I suppose)
>
> For the curious, here's a rather long winded explanation of what I need.
>
> I'm writing a system simulator in ruby (think systemC). The snippet
> below shows a typical invocation:

<snip/>

> Notice that the Sim object (with all off its components) is passed to
> the Simulation engine (sim) for execution. The Simulation engine uses
> Kernel#ObjectSpace to find and schedule objects it needs to manage.

IMHO that is bad design. The Sim instance needs to know about all
objects that belong to it. You should do that within your application
and not traverse all objects (of some kind). That is not very efficient
and has some problems of its own (threads, multiple Sim instances etc.).

> For
> efficiency it flattens the netlist and extracts only the input pins and
> clocked output pins it needs to manage. But for messaging, netlisting
> etc, I want the sim engine to know the _name_ of the pins parent (as
> opposed to its object_id) and I would also like to obviate the need to
> redundantly pass the component's symbol name to its constructor. i.e.
>
> instead of
> @d1 = Dflop.new(:d1)
>
> I want to be able to do:
>
> @d1=Dflop.new

That's easily solved:

Base = Struct.new :owner, :name

class Sim
def initialize
@elements = {}
end

def create(name,cl,*args,&b)
x = cl.new(*args,&b)
x.owner = self
x.name = name
@elements[name] = x
end

# or

def create2(name)
x = yield
x.owner = self
x.name = name
@elements[name] = x
end

def some_other_method
create :d1, Dflop
create2(:d1) { Dflop.new }
end
end

> and then when the sim engine needs a human readable component name, it
> somehow gets it from a system hook based on the object id.

> Any help?

Yes, do this yourself. As has been pointed out, there are various
issues with the concept of "the name of an instance" notably that every
object can have any number (including zero) references pointing to it.

Kind regards

robert

Mark Bush

3/23/2008 10:33:00 PM

0

Robert Klemme wrote:
> Plus, what would you do in this case?
>
> a=[SomeClass.new]

Actually, in this case it's not so bad. The variable "a" refers to the
array (so you're not interested in the array contents) so you can use
similar methods on local variables to get it's name, then do:

eval var

on each local variable to see if the object returned is your original
one, just not easily in a method as local variables are now in a
different scope, albeit the scope of the caller (and being very, very
careful about exceptions and side effects). What really made me cringe
was:

a = nil

Now what?

That's when I went and opened a bottle of wine and watched a movie.

I agree 100% though that the real issue here is that Jeff wants the name
of an object to be an attribute and the best way to do that is to, well,
make the name an attribute.

--
Posted via http://www.ruby-....

Marc Heiler

3/23/2008 10:36:00 PM

0

> As has been pointed out, there are various
> issues with the concept of "the name of an instance" notably that every
> object can have any number (including zero) references pointing to it.


That may be correct, but "a number-based system" can be beautiful. Any
LPC MUD should convince a sceptic that finding all the various objects
in the system based on their id (or cloned instance in case of the LPC
world) is nice to have.

For me it seems visually appealing to have all the various objects
floating around in one's mind - with their id tag attached to them
directly :)
--
Posted via http://www.ruby-....

Jeff Patterson

3/24/2008 12:06:00 AM

0

Robert Klemme wrote:
> On 23.03.2008 19:30, Mark Bush wrote:
>> it. And there can be multiple variables pointing to the object. So:
>>
>> a = SomeObject.new
>> b = a
>>
>> Now "a" and "b" both point to the same object. How would you choose
>> between returning :a and :b?
>
> Plus, what would you do in this case?
>
> a=[SomeClass.new]
>
> Basically it makes no sense...
>
> Cheers
>
> robert

Thanks for the response. It seems to me that both of these issue could
be covered by simply returning an array of the symbol names which point
to a object or [] if an object has no name associated with it.
--
Posted via http://www.ruby-....

Jeff Patterson

3/24/2008 12:58:00 AM

0

Robert Klemme wrote:
> On 23.03.2008 16:15, Jeff Patterson wrote:
>> I'm writing a system simulator in ruby (think systemC). The snippet
>> below shows a typical invocation:
>
> <snip/>
>
>> Notice that the Sim object (with all off its components) is passed to
>> the Simulation engine (sim) for execution. The Simulation engine uses
>> Kernel#ObjectSpace to find and schedule objects it needs to manage.
>
> IMHO that is bad design. The Sim instance needs to know about all
> objects that belong to it.

Hmmm. Certainly the Sim instance does contain all of the component
objects and their connections. The actual simulation logic though (i.e.
the dynamic manipulations of those objects in simulation time) IMHO
needs to be relegated to a black box (the Simulation engine) that the
user doesn't need to concern himself with. The Sim object is the netlist
that the user must write for each system model so it's syntax needs to
be a clean as possible.

As for efficiency:
1) it is probably (hopefully?) more efficient to use the system hook
than to write a method to do the same thing but which confines the
traversal to the Sim object passed to the engine, although I agree that
the latter would be desirable from a purist OO standpoint.

2) efficiency isn't important here since it only occurs once, before the
start of the simulation.

> You should do that within your application
> and not traverse all objects (of some kind). That is not very efficient
> and has some problems of its own (threads, multiple Sim instances etc.).

That's a good point. I suppose its possible that there be more than one
sim instance (although the thought hadn't occurred to me) whereby the
user wants to model cooperation between two systems. I may have to write
that method after all :>)
>
>> I want to be able to do:
>>
>> @d1=Dflop.new
>
> That's easily solved:
>
> Base = Struct.new :owner, :name
>
> class Sim
> def initialize
> @elements = {}
> end
>
> def create(name,cl,*args,&b)
> x = cl.new(*args,&b)
> x.owner = self
> x.name = name
> @elements[name] = x
> end
>
> # or
>
> def create2(name)
> x = yield
> x.owner = self
> x.name = name
> @elements[name] = x
> end
>
> def some_other_method
> create :d1, Dflop
> create2(:d1) { Dflop.new }
> end
> end

I like the first approach (Thanks!) But I don't see where you've use the
Base struct you created. I'm new to ruby (but not to Structs) so I'll
have to do some digging here.

>
>> and then when the sim engine needs a human readable component name, it
>> somehow gets it from a system hook based on the object id.
>
>> Any help?
>
> Yes, do this yourself.
> As has been pointed out, there are various
> issues with the concept of "the name of an instance" notably that every
> object can have any number (including zero) references pointing to it.

Sorry if I'm being dense here but I don't see the issue. Simply
returning some sort of Enumeration (array, hash, linked list etc) with
all or none would do the trick. If it's reasonable for the kernel to
associate a unique id# with an object (and it is :>) then its also
reasonable to associate a name (or names) upon assignment of that object
to an instance variable. Further, such an association _must_ already
exist (otherwise when I write @d1.some_method, the kernel wouldn't know
which object I'm referencing). If the kernel has a hash of references,
why can't we access it?

Programmers have fought C's (and therefore C++'s) lack of introspection
(reflection) since the DoT. With a compiled language it is impossible
(or at least very very hard) to do these kinds of things. It seems to me
that Ruby should fully capitalize at every turn on the advantages
interpretation brings

Thank you kindly for your suggestions
Jeff
--
Posted via http://www.ruby-....

Jeff Patterson

3/24/2008 1:11:00 AM

0

Mark Bush wrote:
> Robert Klemme wrote:
>> Plus, what would you do in this case?
>>
>> a=[SomeClass.new]
>
> Actually, in this case it's not so bad. The variable "a" refers to the
> array (so you're not interested in the array contents) so you can use
> similar methods on local variables to get it's name, then do:
>
> eval var
>
> on each local variable to see if the object returned is your original
> one, just not easily in a method as local variables are now in a
> different scope, albeit the scope of the caller (and being very, very
> careful about exceptions and side effects). What really made me cringe
> was:
>
> a = nil

Since nil is an instance of NilClass, I suppose
MyProposedSystemHook(nil) would return [:a,...any other variable
_assigned_ to nil]

><I agree 100% though that the real issue here is that Jeff wants the name
> of an object to be an attribute

No! (unless you meant Kernel attribute, which it already is, at least
indirectly). The symbol name cannot belong to the object because rvalues
can not know about lvalues at instantiation. Howeevr, the kernel owns
both and so can manage associations between them!
--
Posted via http://www.ruby-....

Mark Bush

3/24/2008 1:31:00 AM

0

Jeff Patterson wrote:
> Thanks for the response. It seems to me that both of these issue could
> be covered by simply returning an array of the symbol names which point
> to a object or [] if an object has no name associated with it.

Potentially. You could fudge it with something like (in Object):

def get_variable_names context, locals, instances
names = []
(locals + instances + global_variables).each do |var_name|
if value = eval(var_name, context)
names << var_name if value.object_id.eql?(object_id)
end
end
names
end

and use it like:

foo.get_variable_names binding, local_variables, instance_variables

You need to pass in local and instance variable names because the
context of the method call is different to the context of the caller and
the caller's binding is needed to evaluate these. There may be a way of
getting the callers context which would give you these, but I don't know
how offhand.

This is not a clean solution, and if Ruby doesn't give you the caller's
context then the only other solution I can see is to carry the
information around with the object.

--
Posted via http://www.ruby-....