Callback for instance var creation?

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;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.

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:

  Captcha

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
  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.

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 :wink:

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.