Is there a callback for when an instance variable is first used? I know they
are "instantiated" upon use and set to nil. I would like to set this to
something else dependent on the name of the variable.
Thanks,
T.
Is there a callback for when an instance variable is first used? I know they
are "instantiated" upon use and set to nil. I would like to set this to
something else dependent on the name of the variable.
Thanks,
T.
"T. Onoma" <transami@runbox.com> schrieb im Newsbeitrag
news:200408212304.28814.transami@runbox.com...
Is there a callback for when an instance variable is first used? I know
they
are "instantiated" upon use and set to nil.
No, they are instantiated on first assignment:
class Foo;end
=> nil
f=Foo.new
=> #<Foo:0x101858b8>
f.instance_eval { puts @bar }
nil
=> nil
f
=> #<Foo:0x101858b8>
f.instance_variables
=>
f.instance_eval { @bar = "yes" }
=> "yes"
f
=> #<Foo:0x101858b8 @bar="yes">
f.instance_variables
=> ["@bar"]
I would like to set this to
something else dependent on the name of the variable.
Which problem are you trying to solve? Usually attribute accessors can do
what you want.
class Foo
attr_accessor :bar
def bar=(b)
@bar = "foo #{b}"
end
end
f=Foo.new
=> #<Foo:0x1019f940>
f.bar = "bar"
=> "bar"
f.bar
=> "foo bar"
f
=> #<Foo:0x1019f940 @bar="foo bar">
Other than that if you need to intercept all variable settings a modified
Hash might be better for managing your instance vars:
class Foo
class FooHash < Hash
def =(k,v)
case k
when :foo
super(k, "bar #{v}")
else
super
end
end
end
def initialize
@vars = FooHash.new
end
def method_missing(sym, *args, &b)
case sym.to_s
when /^(\w+)=$/
@vars[$1.intern] = args[0]
when /^(\w+)$/
@vars[sym]
else
super
end
end
end
f=Foo.new
=> #<Foo:0x1018e690 @vars={}>
f.foo = 10
=> 10
f.bar = 20
=> 20
f
=> #<Foo:0x1018e690 @vars={:bar=>20, :foo=>"bar 10"}>
This of course is just an example. It depends on the real problem at hand
that you are trying to solve.
Regards
robert
> are "instantiated" upon use and set to nil.
No, they are instantiated on first assignment:
>> class Foo;end
Oh! I didn't realize b/c if you assign from one that doesn't exist, it returns
nil.
irb(main):001:0> x=@x
=> nil
irb(main):002:0> p x
nil
=> nil
> I would like to set this to
> something else dependent on the name of the variable.
Which problem are you trying to solve? Usually attribute accessors can do
what you want.
Actually, its esoteric. I've been thinking about methods as 1st class objects.
At one point I have suggested that constants be used. See:
http://www.rubygarden.org/ruby?FirstClassMethods
But constants are class-level while methods are actually instance level
(strangely enough). So I thought if they were instance level perhaps an
instance variable would be better. Using the capitalization idea from before,
something like:
def ameth(x)
puts x
end
p @Ameth # => #<Method: Object#ameth>
So I was trying to auto-assign @Ameth.
Other than that if you need to intercept all variable settings a modified
Hash might be better for managing your instance vars:
Perhaps something like that would be better. I'll give it some thought.
Thanks!
T.
On Sunday 22 August 2004 06:40 am, Robert Klemme wrote:
T. Onoma wrote:
Actually, its esoteric. I've been thinking about methods as 1st class objects. At one point I have suggested that constants be used. See:
Actually I think the best way to do this would be like this:
obj = Object.new
obj.method(:foo) = self.method(:puts)
obj.foo(5)
Regards,
Florian Gross
"T. Onoma" <transami@runbox.com> schrieb im Newsbeitrag
news:200408221316.47855.transami@runbox.com...
> > are "instantiated" upon use and set to nil.
>
> No, they are instantiated on first assignment:
> >> class Foo;endOh! I didn't realize b/c if you assign from one that doesn't exist, it
returns
nil.
irb(main):001:0> x=@x
=> nil
irb(main):002:0> p x
nil
=> nil> > I would like to set this to
> > something else dependent on the name of the variable.> Which problem are you trying to solve? Usually attribute accessors can
do
> what you want.
Actually, its esoteric. I've been thinking about methods as 1st class
objects.
Methods *are* first class objects:
class Foo; def bar;end ;end
=> nil
Foo.instance_method :bar
=> #<UnboundMethod: Foo#bar>
Foo.new.method :bar
=> #<Method: Foo#bar>
And similar to functional languages, functions are also first class objects
and you can work functional style in Ruby, too:
plus = lambda {|a, b| a + b}
=> #<Proc:0x10188438@(irb):1>
plus[ 1, 2 ]
=> 3
curry = lambda {|f, *args| lambda {|*x| f.call(*(args + x))} }
=> #<Proc:0x1017fa38@(irb):2>
plus5 = curry[ plus, 5 ]
=> #<Proc:0x1017fa80@(irb):2>
plus5[ 10 ]
=> 15
At one point I have suggested that constants be used. See:
But constants are class-level while methods are actually instance level
(strangely enough).
Not necessarily, see the first code example above (UnboundMethod). Note
also that you can convert between the two types:
Foo.new.method( :bar ).unbind
=> #<UnboundMethod: Foo#bar>
Foo.instance_method( :bar ).bind( Foo.new )
=> #<Method: Foo#bar>
So I thought if they were instance level perhaps an
instance variable would be better. Using the capitalization idea from
before,
something like:
def ameth(x)
puts x
endp @Ameth # => #<Method: Object#ameth>
So I was trying to auto-assign @Ameth.
> Other than that if you need to intercept all variable settings a
modified
> Hash might be better for managing your instance vars:
Perhaps something like that would be better. I'll give it some thought.
It seems the easiest to do would be to include a Hash for method instances
if you want to maintain state:
class Object
alias :old_method :method
def method(s)
( @methods ||= {} )[s] ||= old_method(s)
end
end
class Foo
def bar;end
end
=> nil
f= Foo.new
=> #<Foo:0x10186608>
f.method( :bar ).id
=> 135011952
f.method( :bar ).id
=> 135004308
class Object
alias :old_method :method
def method(s)
( @methods ||= {} )[s] ||= old_method(s)
end
end
=> nil
f.method( :bar ).id
=> 134638968
f.method( :bar ).id
=> 134638968
Kind regards
robert
On Sunday 22 August 2004 06:40 am, Robert Klemme wrote:
Not sure how that provides 1st class methods. The idea is to be able to store
state in methods and give them singletons, etc. For instance:
def ameth
puts Time.now
end
# if ameth were a first class object
def ameth.tag
:log
end
Calling method(:ameth) doesn't work because it creates a new method object
everytime and therefore looses state. Plus it is overly verbose.
There have been other suggested notations like:
::meth
\meth
On Sunday 22 August 2004 02:55 pm, Florian Gross wrote:
Actually I think the best way to do this would be like this:
obj = Object.new
obj.method(:foo) = self.method(:puts)
obj.foo(5)
--
T.
Methods *are* first class objects:
Yes, in one sense they are. That's true. But not in the sense that they
readily accessable and *carry state* (as in Python, FWIBT). That's the
important missing element.
> But constants are class-level while methods are actually instance level
> (strangely enough).Not necessarily, see the first code example above (UnboundMethod). Note
also that you can convert between the two types:
>> Foo.new.method( :bar ).unbind=> #<UnboundMethod: Foo#bar>
>> Foo.instance_method( :bar ).bind( Foo.new )
=> #<Method: Foo#bar>
Hmm... I see more clearly now how rebinding unbound methods "reinstates" the
method. But still, unbound methods seem useless. They can only be rebound to
the same kind of class. Until that changes what real use are they? But
perhaps in the future...(matz?) Then again I think someone did once show me
an example of how unbound methods could be useful, but it was rather tricky
and hence not very useful
Hmmm... but I do see that I might be able to finish my original proposal using
them. That might work. So the constant method would be the class-level
version. Oh, that might blend nicely with the capitalized methods for the
instance level version --they will look identical except for the parens.
Ameth - unbound
Ameth() - bound
Not bad. Perhaps with a little extra umph I can use that absent argument too.
Maybe for bounding to a different object? [just thinking out loud here]
class Object
alias :old_method :method
def method(s)
( @methods ||= {} )[s] ||= old_method(s)
end
end
nice. a bit more concise then my version. that will work, despite the extra
verbosity, method(:ameth) -or- @methods[:ameth].
thanks,
T.
On Monday 23 August 2004 03:41 am, Robert Klemme wrote:
T. Onoma wrote:
Calling method(:ameth) doesn't work because it creates a new method object everytime and therefore looses state. Plus it is overly verbose.
Oh, a cache could be added easily. Can't do anything about the verbosity however.
Regards,
Florian Gross
"T. Onoma" <transami@runbox.com> schrieb im Newsbeitrag
news:200408230415.32703.transami@runbox.com...
> Methods *are* first class objects:
Yes, in one sense they are. That's true. But not in the sense that they
readily accessable and *carry state* (as in Python, FWIBT). That's the
important missing element.> > But constants are class-level while methods are actually instance
level
> > (strangely enough).
>
> Not necessarily, see the first code example above (UnboundMethod). Note
>
> also that you can convert between the two types:
> >> Foo.new.method( :bar ).unbind
>
> => #<UnboundMethod: Foo#bar>
>
> >> Foo.instance_method( :bar ).bind( Foo.new )
>
> => #<Method: Foo#bar>Hmm... I see more clearly now how rebinding unbound methods "reinstates"
the
method. But still, unbound methods seem useless. They can only be rebound
to
the same kind of class.
And you can query arity. Plus you can store anything that you like to in
them (i.e. add state of your own). Just apply the pattern I presented for
#method to Class#instance_method and you'll get the same instance each time
you access a method. Note though that this approach doesn't take into
consideration changes of the method definition *after* it was put into the
hash. That might be a serious drawback depending on whether or not you need
to cope with this.
Hmmm... but I do see that I might be able to finish my original proposal
using
them. That might work. So the constant method would be the class-level
version. Oh, that might blend nicely with the capitalized methods for the
instance level version --they will look identical except for the parens.
Personally I don't like at all introducing a constant for each method in a
class. Plus, methods are not constant i.e. you can redefine them.
What kind of state do you want to attach to methods? I mean, what problem
are you trying to solve?
robert
On Monday 23 August 2004 03:41 am, Robert Klemme wrote:
Yes, perhaps I will add a cache to method. Then I'll have three working
implementations of this:
1. method(:ameth) # per above
2. :ameth[self] # modifies symbol class
3. Ameth() # using missing_method and capitalization
The later is of course a take-off of the constant version (non-implementable)
but in this case you have to use the parentheses. All of these, obviously,
have their disadvantages.
I think probably the best way to actually do this is to change how :: works.
Currently it works like this:
Foo.Bar() # method call
Foo.Bar # method call
Foo.bar() # method call
Foo.bar # method call
Foo::Bar() # method call
Foo::Bar # constant lookup
Foo::bar() # method call
Foo::bar # method call
I suggest this instead:
Foo.Bar() # method call
Foo.Bar # method call
Foo.bar() # method call
Foo.bar # method call
Foo::Bar() # method call
Foo::Bar # constant lookup
Foo::bar() # method call
Foo::bar # 1st class method
The only shortcoming here is that capitalized methods can't be accessed this
way b/c they interfere with constants. But that's very very minor point. With
this in place you could easily access 1st class methods like this:
::ameth
On Sunday 22 August 2004 06:15 pm, Florian Gross wrote:
T. Onoma wrote:
> Calling method(:ameth) doesn't work because it creates a new method
> object everytime and therefore looses state. Plus it is overly verbose.Oh, a cache could be added easily. Can't do anything about the verbosity
however.
--
T.
"T. Onoma" <transami@runbox.com> schrieb im Newsbeitrag
news:200408230415.32703.transami@runbox.com...Personally I don't like at all introducing a constant for each method in a
class. Plus, methods are not constant i.e. you can redefine them.
That what everybody says! (Because of the namespace pollution, I guess.)
On the later point, constants in Ruby aren't necessarily so constant.
Constants can be hashes or arrays and their internal contents can readily
change too --and that's useful.
What kind of state do you want to attach to methods? I mean, what problem
are you trying to solve?
AOP. In AOP advice wrap methods, so if methods have state, then wrapping can
be dependent on that state (like arity). On the other hand, just having a
clean syntax for accessing them is nice too.
I still like ::ameth, best.
On Monday 23 August 2004 04:30 am, Robert Klemme wrote:
> On Monday 23 August 2004 03:41 am, Robert Klemme wrote:
--
T.