Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > returning symbols

Reply
Thread Tools

returning symbols

 
 
Daniel Cremer
Guest
Posts: n/a
 
      08-16-2004
I want to write a method to store a list of some instance variables in
an Array that will later be run through to access their data. Normally
in another language I would do this by passing them by reference when I
store them into the Array.

Using the object_id doesn't work because that's to the object the
variable is pointing to and this may change.
So, to sum it up:

Is there a way to get variables to return their symbol so you can access
what they will be referencing in the future ?

thanks,
Daniel



 
Reply With Quote
 
 
 
 
Dave Thomas
Guest
Posts: n/a
 
      08-16-2004

On Aug 16, 2004, at 7:47, Daniel Cremer wrote:
> Is there a way to get variables to return their symbol so you can
> access
> what they will be referencing in the future ?


You could use a closure, but more typically you'd want to enapsulate he
set of variables into a class and return that class.


Cheers

Dave



 
Reply With Quote
 
 
 
 
Kristof Bastiaensen
Guest
Posts: n/a
 
      08-16-2004
Hi,

On Mon, 16 Aug 2004 21:47:59 +0900, Daniel Cremer wrote:

> I want to write a method to store a list of some instance variables in an
> Array that will later be run through to access their data. Normally in
> another language I would do this by passing them by reference when I store
> them into the Array.
>
> Using the object_id doesn't work because that's to the object the variable
> is pointing to and this may change. So, to sum it up:
>
> Is there a way to get variables to return their symbol so you can access
> what they will be referencing in the future ?
>
> thanks,
> Daniel


You can use the name as a string or symbol, and retrieve
the value with instance_variable_get.

> ri instance_variable_get



------------------------------------------- Object#instance_variable_get
obj.instance_variable_get(symbol) => obj
------------------------------------------------------------------------
Returns the value of the given instance variable (or throws a
NameError exception). The @ part of the variable name should be
included for regular instance variables

class Fred
def initialize(p1, p2)
@a, @b = p1, p2
end
end
fred = Fred.new('cat', 99)
fred.instance_variable_get(:@a) #=> "cat"
fred.instance_variable_get("@b") #=> 99

Cheers,
KB
 
Reply With Quote
 
Mikael Brockman
Guest
Posts: n/a
 
      08-16-2004
Daniel Cremer <> writes:

> I want to write a method to store a list of some instance variables in
> an Array that will later be run through to access their data. Normally
> in another language I would do this by passing them by reference when I
> store them into the Array.
>
> Using the object_id doesn't work because that's to the object the
> variable is pointing to and this may change.
> So, to sum it up:
>
> Is there a way to get variables to return their symbol so you can access
> what they will be referencing in the future ?
>
> thanks,
> Daniel


It's kind of a hack, and you should avoid using it, but

| class Box
| def initialize (&accessor)
| @accessor = accessor
| end
|
| def set! (new)
| @accessor.call new
| end
|
| def get
| @accessor.call
| end
| end
|
| class Object
| def box (variable)
| Box.new do |*value|
| if value.empty?
| instance_variable_get variable
| else
| instance_variable_set variable, value.first
| end
| end
| end
| end

> foo = Foo.new

=> #<Foo:0x402f94c4 @a=5>
> box = foo.box(:@a)

=> #<Box:0x402f68dc @accessor=#<Proc:0x4030f530@./boxes.rb:18>>
> box.get

=> 5
> box.set! 10

=> 10
> box.get

=> 10
> foo.instance_variable_get(:@a)

=> 10



 
Reply With Quote
 
T. Onoma
Guest
Posts: n/a
 
      08-16-2004
On Monday 16 August 2004 08:47 am, Daniel Cremer wrote:
> Is there a way to get variables to return their symbol so you can access
> what they will be referencing in the future ?


class C
attr_accessor :a, :b, :c
def initialize
@a, @b, @c = 1, 2, 3
end
def bump
@a, @b, @c = 100, 200, 300
end
def ref
return [ lambda { @a }, lambda { @b }, lambda { @c } ]
end
end

c = C.new
v = c.ref
v.each { |q| puts q.call }
c.bump
v.each { |q| puts q.call }

--
T.


 
Reply With Quote
 
Daniel Cremer
Guest
Posts: n/a
 
      08-16-2004
On Mon, 2004-08-16 at 14:53, T. Onoma wrote:
> On Monday 16 August 2004 08:47 am, Daniel Cremer wrote:
> > Is there a way to get variables to return their symbol so you can access
> > what they will be referencing in the future ?

>
> class C
> attr_accessor :a, :b, :c
> def initialize
> @a, @b, @c = 1, 2, 3
> end
> def bump
> @a, @b, @c = 100, 200, 300
> end
> def ref
> return [ lambda { @a }, lambda { @b }, lambda { @c } ]
> end
> end
>
> c = C.new
> v = c.ref
> v.each { |q| puts q.call }
> c.bump
> v.each { |q| puts q.call }


Interesting example... What I don't understand is how would you
implement object pools in Ruby ? If I understand correctly with object
pools you often have data representing state stored separately. Then
when needed you can grab an instance of the object from the pool and
populate it with this data.
For an example like that I would like to have a base-class that
implements a persist() method. This way developers working on a class
can inherit this class and simply pass the objects representing state to
this persist() method.

def persist(*state_objs)
...
persistent_objects = Array.new()
state_objs.each { |obj| persistent_objects << obj }
...
end

>From then on it could be included into object pools with no further work

from the developer.

But this is were I have problems. Implementing this in the base class
such that it can take any list of variables without any knowledge of
their names and being able to get back to the contents of the variables
to store the state before returning the object to the pool.
I hope this makes sense, I might be confusing myself

On Mon, 2004-08-16 at 14:04, Dave Thomas wrote:
> You could use a closure, but more typically you'd want to enapsulate he
> set of variables into a class and return that class.


Could someone elaborate on the part about returning a class. I'm not
sure if I captured the full meaning.

thanks,
Daniel



 
Reply With Quote
 
Florian Gross
Guest
Posts: n/a
 
      08-16-2004
Daniel Cremer wrote:

> Is there a way to get variables to return their symbol so you can access
> what they will be referencing in the future ?


For ordinary variables you can use the code that I attached.

> thanks,
> Daniel


Regards,
Florian Gross

require 'binding_of_caller'

class Variable
def self.new(name, context = nil)
return super(name, context) unless context.nil?
Binding.of_caller do |context|
super(name, context)
end
end
class << self; alias :[] :new; end

attr_reader :context, :name

def initialize(name, context)
unless /^[a-z_][\w\d_]*$/.match(name.to_s)
raise(NameError, "Illegal variable name: #{name.inspect}")
end

@name, @context = name, context
@setter = lambda do |value|
eval "#{@name} = ObjectSpace._id2ref(#{value.id})", context
end
exists = lambda do
eval "local_variables.include?(#{@name.to_s.inspect })", context
end
@getter = lambda do
eval("#{@name}", context) if exists.call
end
end

def []=(value); @setter.call(value); end
def []; @getter.call; end
alias :value= :[]=
alias :value :[]

def inspect
"Variable[#{@name.inspect}, #{@context.inspect}]"
end
end

begin
require 'simplecc'
rescue LoadError
def Continuation.create(*args, &block)
cc = nil; result = callcc {|c| cc = c; block.call(cc) if block and args.empty?}
result ||= args
return *[cc, *result]
end
end

# This method returns the binding of the method that called your
# method. It will raise an Exception when you're not inside a method.
#
# It's used like this:
# def inc_counter
# Binding.of_caller do |binding|
# eval("counter += 1", binding)
# end
# end
# counter = 0
# 2.times { inc_counter }
# counter # => 2
#
# You will have to put the whole rest of your method into the
# block that you pass into this method. If you don't do this
# an Exception will be raised. Because of the way that this is
# implemented it has to be done this way. If you don't do it
# like this it will raise an Exception.
def Binding.of_caller(&block)
old_critical = Thread.critical
Thread.critical = true
count = 0
cc, result, error = Continuation.create(nil, nil)
error.call if error

tracer = lambda do |*args|
type, context = args[0], args[4]
if type == "return"
count += 1
# First this method and then calling one will return --
# the trace event of the second event gets the context
# of the method which called the method that called this
# method.
if count == 2
# It would be nice if we could restore the trace_func
# that was set before we swapped in our own one, but
# this is impossible without overloading set_trace_func
# in current Ruby.
set_trace_func(nil)
cc.call(eval("binding", context), nil)
end
elsif type != "line"
set_trace_func(nil)
error_msg = "Binding.of_caller used in non-method context or " +
"trailing statements of method using it aren't in the block."
cc.call(nil, lambda { raise(ArgumentError, error_msg ) })
end
end

unless result
set_trace_func(tracer)
return nil
else
Thread.critical = old_critical
yield result
end
end

 
Reply With Quote
 
Ara.T.Howard
Guest
Posts: n/a
 
      08-16-2004
On Mon, 16 Aug 2004, T. Onoma wrote:

> On Monday 16 August 2004 08:47 am, Daniel Cremer wrote:
>> Is there a way to get variables to return their symbol so you can access
>> what they will be referencing in the future ?

>
> class C
> attr_accessor :a, :b, :c
> def initialize
> @a, @b, @c = 1, 2, 3
> end
> def bump
> @a, @b, @c = 100, 200, 300
> end
> def ref
> return [ lambda { @a }, lambda { @b }, lambda { @c } ]
> end
> end
>
> c = C.new
> v = c.ref
> v.each { |q| puts q.call }
> c.bump
> v.each { |q| puts q.call }
>
> --
> T.


what does this give you over this?

~ > cat a.rb
class C
VARS = :a, :b, :c
VARS.each{|v| attr_accessor v}
def initialize
@a, @b, @c = 1, 2, 3
end
def bump
@a, @b, @c = 100, 200, 300
end
def ref
VARS
end
end

c = C.new
vars = c.ref
vars.each { |v| puts(c.send(v)) }
c.bump
vars.each { |v| puts(c.send(v)) }


~ > ruby a.rb
1
2
3
100
200
300


what am i missing here?

-a
--
================================================== =============================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| A flower falls, even though we love it;
| and a weed grows, even though we do not love it.
| --Dogen
================================================== =============================
 
Reply With Quote
 
T. Onoma
Guest
Posts: n/a
 
      08-16-2004
On Monday 16 August 2004 10:51 am, Ara.T.Howard wrote:
> what does this give you over this?
> ...
> what am i missing here?


Reference to c. With the lambda example the context is embedded. Send on the
other hand requires the applicable object be remembered separately.

vars.each { |q| puts q.call } # no c
vars.each { |v| puts(c.send(v)) }

--
T.


 
Reply With Quote
 
Daniel Cremer
Guest
Posts: n/a
 
      08-16-2004
On Mon, 2004-08-16 at 15:23, Daniel Cremer wrote:
> ... What I don't understand is how would you
> implement object pools in Ruby ? If I understand correctly with object
> pools you often have data representing state stored separately. Then
> when needed you can grab an instance of the object from the pool and
> populate it with this data.
> For an example like that I would like to have a base-class that
> implements a persist() method. This way developers working on a class
> can inherit this class and simply pass the objects representing state to
> this persist() method.
>
> def persist(*state_objs)
> ...
> persistent_objects = Array.new()
> state_objs.each { |obj| persistent_objects << obj }
> ...
> end
>
> >From then on it could be included into object pools with no further work

> from the developer.
>
> But this is were I have problems. Implementing this in the base class
> such that it can take any list of variables without any knowledge of
> their names and being able to get back to the contents of the variables
> to store the state before returning the object to the pool.
> I hope this makes sense, I might be confusing myself


Ok I think I cleared my brain a bit on my particular example and did a
quick implementation:

--------------------------------
require 'set'

class MyBaseClass
@@persist = Set.new()

def MyBaseClass.persist(*symbol)
symbol.each do |symbol|
instance_symbol = "@" + symbol.to_s
@@persist.add(instance_symbol)
end
end

def return_persistent_vars()
output = Array.new()
@@persist.each {|val| output << self.instance_variable_get(val) }
return output
end
end


class ObjPoolObj < MyBaseClass
attr_accessor :var1, :var2, :var3
persist :var1, :var2

def initialize
@var1 = "hello"
@var2 = "world"
@var3 = "nothingHere"
end

end

test_obj = ObjPoolObj.new()
puts test_obj.return_persistent_vars() #=> hello
#=> world

test_obj.var1 = "hellomodified"
puts test_obj.return_persistent_vars() #=> hellomodified
#=> world

---------------------------

The part I find cool is being able to call: "persist :var1, :var2" in
the same manner as attr_accessor. Of course the whole storing of the
data and stuffing it back into the object from the pool would need to be
implemented but that should be simple enough. I'll think about
generalising this stuff...
thanks for keeping my neurons firing.
Daniel






 
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
returning none when it should be returning a list? randomtalk@gmail.com Python 11 05-02-2006 10:26 AM
<% symbols Brian Henry ASP .Net 5 07-06-2004 06:07 PM
Displaying Special Symbols Gibs ASP .Net 3 06-29-2004 07:33 PM
cisco router/switch symbols dave-au Cisco 0 02-15-2004 10:01 PM
Debug symbols not for all .aspx forms. =?Utf-8?B?QUs=?= ASP .Net 1 01-23-2004 11:48 AM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57