Using #include at the instance level?

I would like to use #include at an instance level, such that it
behaves just as it does at a class level. After a number of
experiments I thought for sure it would work if I ran the include
through the object's singleton. Alas, submodules remain inaccessible,
eg.

  module M
    def m1; "m1"; end
    module N
      def self.n1; "n1"; end
    end
  end

  class X
    def initialize(*mods)
      (class << self; self; end).class_eval do
        include *mods
      end
    end
    def m ; m1 ; end
    def n ; N.n1 ; end
  end

  x = X.new(M)
  p x.m
  p x.n #=> uninitialized constant X::N (NameError)

Is there any way to achieve this?

You may write:

class X
   def eigenclass
     class << self; self; end;
   end
   
   def initialize(*mods)
     eigenclass.instance_eval do
       include *mods
     end
   end
   def m ; m1 ; end
   def n; eigenclass::N.n1 ; end
end

I guess constants not like methods are not searched within eigenclass, and that's the reason why you are getting an error.

···

On Dec 28, 2009, at 10:29 PM, Intransition wrote:

I would like to use #include at an instance level, such that it
behaves just as it does at a class level. After a number of
experiments I thought for sure it would work if I ran the include
through the object's singleton. Alas, submodules remain inaccessible,
eg.

module M
   def m1; "m1"; end
   module N
     def self.n1; "n1"; end
   end
end

class X
   def initialize(*mods)
     (class << self; self; end).class_eval do
       include *mods
     end
   end
   def m ; m1 ; end
   def n ; N.n1 ; end
end

x = X.new(M)
p x.m
p x.n #=> uninitialized constant X::N (NameError)

Is there any way to achieve this?

--
Fedor Kocherga
http://sidenotes.kocherga.info/

I would like to use #include at an instance level, such that it
behaves just as it does at a class level. After a number of
experiments I thought for sure it would work if I ran the include
through the object's singleton. Alas, submodules remain inaccessible,
eg.

module M
def m1; "m1"; end
module N
def self.n1; "n1"; end
end
end

class X
def initialize(*mods)
(class << self; self; end).class_eval do
include *mods
end
end
def m ; m1 ; end
def n ; N.n1 ; end

Hm, this method above won't work as scope resolution rules for
constants are different.

end

x = X.new(M)
p x.m
p x.n #=> uninitialized constant X::N (NameError)

Is there any way to achieve this?

Did you consider using #extend?

class X
   def initialize(*mods)
     extend *mods
   end
end

What do you really want to achieve? Do you have a more telling example?

Kind regards

robert

···

2009/12/29 Intransition <transfire@gmail.com>:

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

It's for encapsulating test cases. Eg.

  TestCase.new(SomeClass) do
    ...
  end

Within the test case block it would help to handle #include, to make
tests less verbose.

Instead of making an instance of TestCase for each case, at this point
it looks like I'll have to create a new subclass of it.

···

On Dec 29, 3:29 am, Robert Klemme <shortcut...@googlemail.com> wrote:

2009/12/29 Intransition <transf...@gmail.com>:

> I would like to use #include at an instance level, such that it
> behaves just as it does at a class level. After a number of
> experiments I thought for sure it would work if I ran the include
> through the object's singleton. Alas, submodules remain inaccessible,
> eg.

> module M
> def m1; "m1"; end
> module N
> def self.n1; "n1"; end
> end
> end

> class X
> def initialize(*mods)
> (class << self; self; end).class_eval do
> include *mods
> end
> end
> def m ; m1 ; end
> def n ; N.n1 ; end

Hm, this method above won't work as scope resolution rules for
constants are different.

> end

> x = X.new(M)
> p x.m
> p x.n #=> uninitialized constant X::N (NameError)

> Is there any way to achieve this?

Did you consider using #extend?

class X
def initialize(*mods)
extend *mods
end
end

What do you really want to achieve? Do you have a more telling example?

You are right. That appears to be the case. I tried setting a constant
directly in the eigenclass and the instance could not see it either.
The behavior surprises me.

···

On Dec 29, 1:35 am, fkocherga <fkoche...@gmail.com> wrote:

I guess constants not like methods are not searched within eigenclass, and that's the reason why you are getting an error.

> I would like to use #include at an instance level, such that it
> behaves just as it does at a class level. After a number of
> experiments I thought for sure it would work if I ran the include
> through the object's singleton. Alas, submodules remain inaccessible,
> eg.

> module M
> def m1; "m1"; end
> module N
> def self.n1; "n1"; end
> end
> end

> class X
> def initialize(*mods)
> (class << self; self; end).class_eval do
> include *mods
> end
> end
> def m ; m1 ; end
> def n ; N.n1 ; end

Hm, this method above won't work as scope resolution rules for
constants are different.

> end

> x = X.new(M)
> p x.m
> p x.n #=> uninitialized constant X::N (NameError)

> Is there any way to achieve this?

Did you consider using #extend?

class X
def initialize(*mods)
extend *mods
end
end

What do you really want to achieve? Do you have a more telling example?

It's for encapsulating test cases. Eg.

TestCase.new(SomeClass) do
...
end

Within the test case block it would help to handle #include, to make
tests less verbose.

I see to be a bit slow today: how do you want to use modules there?
Do you want to include them in the test code? What about:

class TestCase
  def new(cl, &bl)
     @cl = cl
     instance_eval(&bl)
  end

  alias include extend
end

TestCase.new String do
  extend Foo
  include Bar
end

Instead of making an instance of TestCase for each case, at this point
it looks like I'll have to create a new subclass of it.

Sorry, you lost me here.

Cheers

robert

···

2009/12/29 Intransition <transfire@gmail.com>:

On Dec 29, 3:29 am, Robert Klemme <shortcut...@googlemail.com> wrote:

2009/12/29 Intransition <transf...@gmail.com>:

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

I see to be a bit slow today: how do you want to use modules there?
Do you want to include them in the test code? What about:

class TestCase
def new(cl, &bl)
@cl = cl
instance_eval(&bl)
end

alias include extend
end

TestCase.new String do
extend Foo
include Bar
end

No no. You got it exactly. Problem is the module's constants are not
coming through the #extend (which is effectively the same as the
include in the singleton class). Let say I have a library:

  module MyApp
    module SomeSpace
      class FooClass
        ...
       end
    end
  end

In the test cases, instead of having to spell out
MyApp::SomeSpace::FooClass everywhere it is needed, it would be nice
to include MyApp::SomeSpace, and then just reference FooClass in the
tests.

> Instead of making an instance of TestCase for each case, at this point
> it looks like I'll have to create a new subclass of it.

Sorry, you lost me here.

Instead of the code you presented I'd have to do something like:

  class TestCase
    alias :_new, :new
    def self.new(&block)
      Class.new(self, &block)._new
    end
  end

Haven't tested it yet, but that should allow #include to work no
problem. Unfortunately it means defining all my dsl methods at the
class level --not even sure the instance level would be of any use in
this case either, in which case the ._new can be dropped -- kind of
stupid, just to get #include to work. But what else can I do?

I almost feel like I'm having a mental block and there is actually an
easy way to do this.

···

On Dec 29, 9:37 am, Robert Klemme <shortcut...@googlemail.com> wrote:

2009/12/29 Intransition <transf...@gmail.com>:

Maybe this gets you on track:

"One of those pleasing little Ruby snippets: module Helpers; include *constants.map(&amp;:const_get); end"
http://twitter.com/pragdave/status/7147303788

···

On 29.12.2009 17:37, Intransition wrote:

I almost feel like I'm having a mental block and there is actually an
easy way to do this.

--
Phillip Gawlowski

I see to be a bit slow today: how do you want to use modules there?
Do you want to include them in the test code? What about:

class TestCase
def new(cl, &bl)

Btw, that method's name should have read "initialize".

 @cl = cl
 instance\_eval\(&amp;bl\)

end

alias include extend
end

TestCase.new String do
extend Foo
include Bar
end

No no. You got it exactly. Problem is the module's constants are not
coming through the #extend (which is effectively the same as the
include in the singleton class). Let say I have a library:

module MyApp
module SomeSpace
class FooClass
...
end
end
end

In the test cases, instead of having to spell out
MyApp::SomeSpace::FooClass everywhere it is needed, it would be nice
to include MyApp::SomeSpace, and then just reference FooClass in the
tests.

> Instead of making an instance of TestCase for each case, at this point
> it looks like I'll have to create a new subclass of it.

Sorry, you lost me here.

Instead of the code you presented I'd have to do something like:

class TestCase
alias :_new, :new
def self.new(&block)
Class.new(self, &block)._new
end
end

Then your block needs to contain a class definition. You can use the
block only for _one_ thing - either class / module def or code you
want to execute. Granted, you can have code executed in a class
definition as well but the definition becomes only usable *after* the
definition has been executed in its entirety. Maybe you haven't
decided yet what you want the block for and that is causing your
headaches.

Haven't tested it yet, but that should allow #include to work no
problem. Unfortunately it means defining all my dsl methods at the
class level --not even sure the instance level would be of any use in
this case either, in which case the ._new can be dropped -- kind of
stupid, just to get #include to work. But what else can I do?

I almost feel like I'm having a mental block and there is actually an
easy way to do this.

What stops you from doing the include outside?

include Your::Module::Of::Choice

TestCase.new Foo do
  x = ChoiceClass.new
  x.method_invocation(123)
end

Kind regards

robert

···

2009/12/29 Intransition <transfire@gmail.com>:

On Dec 29, 9:37 am, Robert Klemme <shortcut...@googlemail.com> wrote:

2009/12/29 Intransition <transf...@gmail.com>:

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

Then your block needs to contain a class definition. You can use the
block only for _one_ thing - either class / module def or code you
want to execute. Granted, you can have code executed in a class
definition as well but the definition becomes only usable *after* the
definition has been executed in its entirety.

That's true. But the execution of the block is only for the definition
of things which get run later.

Maybe you haven't
decided yet what you want the block for and that is causing your
headaches.

The block is for defining unit tests. Eg.

  testcase SomeClass do
    testunit :somemethod => "some concern" do
      ...
    end
  end

> Haven't tested it yet, but that should allow #include to work no
> problem. Unfortunately it means defining all my dsl methods at the
> class level --not even sure the instance level would be of any use in
> this case either, in which case the ._new can be dropped -- kind of
> stupid, just to get #include to work. But what else can I do?

> I almost feel like I'm having a mental block and there is actually an
> easy way to do this.

What stops you from doing the include outside?

include Your::Module::Of::Choice

TestCase.new Foo do
x = ChoiceClass.new
x.method_invocation(123)
end

Yes, I am able to do that. But I want to avoid polluting the top
level.

You know what really gets me is that even though I get an
"uninitialized constant" error, there is no place I seem to be able to
define a #const_missing method to catch it.

···

On Dec 29, 11:55 am, Robert Klemme <shortcut...@googlemail.com> wrote:

This is really becoming annoying. I can't even do it via a dynamic
class definitions either.

  module M
    def m1; "m1"; end
    module N
      def self.n1; "n1"; end
    end
  end

  class X
    class << self
      alias _new new
      def new(&block)
        klass = Class.new(self)
        klass.class_eval(&block)
        klass._new
      end
    end

    def m ; m1 ; end
    def n ; N.n1 ; end
  end

  x = X.new do
    include M
  end

  p x.m
  p x.n #=> uninitialized constant X::N (NameError)

Did constant lookup change between 1.8.6 and 1.8.7? Seems to me this
used to be possible, and I find it unacceptable that normal constant
lookup would not apply to dynamic class definitions, let alone the
singleton classes.

AFAIK it hasn't changed and your code could never work in any version
of Ruby because the const lookup in method #n is done _statically_.
Apart from that you are defining method X#n and not <subclass of X>#n
so the lookup could never work if you would instantiate X.

Also, on a more abstract level: it is at least a bit odd to define
class X which can only ever work if you make sure you include "N"
(whichever way).

I believe you haven't yet fully analyzed the problem you want to
solve. I suggest to put it to sleep for a while and then get back
later to it. I can't help you any more because to me it is not clear
what you are trying to achieve. So far we only went through technical
issues but the problem you are trying to solve isn't cleat to me yet.

Kind regards

robert

···

2009/12/29 Intransition <transfire@gmail.com>:

This is really becoming annoying. I can't even do it via a dynamic
class definitions either.

module M
def m1; "m1"; end
module N
def self.n1; "n1"; end
end
end

class X
class << self
alias _new new
def new(&block)
klass = Class.new(self)
klass.class_eval(&block)
klass._new
end
end

def m ; m1 ; end
def n ; N.n1 ; end
end

x = X.new do
include M
end

p x.m
p x.n #=> uninitialized constant X::N (NameError)

Did constant lookup change between 1.8.6 and 1.8.7? Seems to me this
used to be possible, and I find it unacceptable that normal constant
lookup would not apply to dynamic class definitions, let alone the
singleton classes.

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

All I am trying to do is emulate test/unit but using a DSL.
Essentially:

  class MyTest < Test::Unit::TestCase

    include M

    def test_N_n1
       assert_equal(N.n1, "n1")
     end

  end

Becomes:

  testcase :MyTest do

    include M

    testunit :N_n1 do
       assert_equal(N.n1, "n1")
     end

  end

That's it. But I can't do it exactly b/c I can't make the include
work.

···

On Dec 29, 3:16 pm, Robert Klemme <shortcut...@googlemail.com> wrote:

2009/12/29 Intransition <transf...@gmail.com>:

> This is really becoming annoying. I can't even do it via a dynamic
> class definitions either.

> module M
> def m1; "m1"; end
> module N
> def self.n1; "n1"; end
> end
> end

> class X
> class << self
> alias _new new
> def new(&block)
> klass = Class.new(self)
> klass.class_eval(&block)
> klass._new
> end
> end

> def m ; m1 ; end
> def n ; N.n1 ; end
> end

> x = X.new do
> include M
> end

> p x.m
> p x.n #=> uninitialized constant X::N (NameError)

> Did constant lookup change between 1.8.6 and 1.8.7? Seems to me this
> used to be possible, and I find it unacceptable that normal constant
> lookup would not apply to dynamic class definitions, let alone the
> singleton classes.

AFAIK it hasn't changed and your code could never work in any version
of Ruby because the const lookup in method #n is done _statically_.
Apart from that you are defining method X#n and not <subclass of X>#n
so the lookup could never work if you would instantiate X.

Also, on a more abstract level: it is at least a bit odd to define
class X which can only ever work if you make sure you include "N"
(whichever way).

I believe you haven't yet fully analyzed the problem you want to
solve. I suggest to put it to sleep for a while and then get back
later to it. I can't help you any more because to me it is not clear
what you are trying to achieve. So far we only went through technical
issues but the problem you are trying to solve isn't cleat to me yet.

AFAIK it hasn't changed and your code could never work in any version
of Ruby because the const lookup in method #n is done _statically_.

But it should not, consider:

module M
  module N
  end
end

#Class.new do <---- This does not work in 1.8.7!
class B < Object
  include M
  N
end

When 'class B < Object' replaced with 'Class.new do' the Ruby 1.8.7 interpreter complains about uninitialized constant N. What is the big reason for dynamically defined class to behave so differently? It would be very non obvious and unexpected behavior. Actually both cases work as expected in Ruby 1.9.1 and this is correct behavior according to the Ruby Draft.

···

--
Fedor Kocherga
http://sidenotes.kocherga.info/

All I am trying to do is emulate test/unit but using a DSL.
Essentially:

class MyTest < Test::Unit::TestCase

   include M

   def test_N_n1
      assert_equal(N.n1, "n1")
    end

end

Becomes:

testcase :MyTest do

   include M

   testunit :N_n1 do
      assert_equal(N.n1, "n1")
    end

end

Not sure why you need a DSL for, but technically it is doable (in Ruby 1.9.1):
http://gist.github.com/265864

···

--
Fedor Kocherga
http://sidenotes.kocherga.info/

Thanks for the test case! It never occurred to me to do a const
lookup in a class defined with a class body so I never stumbled across
this. I did a bit of research and this is what I found:

Statement from Matz about the change: "In 1.8, constant uses lexical
look-up, even within the block given to instance_eval(). We changed
this behavior in 1.9 to simplify things."
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/181646

Found via http://eigenclass.org/hiki/withdrawn-experimental-ruby-features
- I am not so sure about the "experimental" status of this though -
maybe this is due to the last update date of the page in 2007...

Adam Gardner also made an interesting observation about the difference
between const_get and direct constant lookup:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/333677
(I have changed the test output to easier interpret it. See attachment.)

There's also this discussion
http://blade.nagaokaut.ac.jp/cgi-bin/vframe.rb/ruby/ruby-core/25865?25832-26487

And this
http://blade.nagaokaut.ac.jp/cgi-bin/vframe.rb/ruby/ruby-talk/334016?333995-335445

To sum it up: Ruby 1.9 changed lookup rules from lexical (aka static)
to dynamic. IMHO this explains the observed different behavior.
Thanks again for poking.

Kind regards

robert

const-lookup-2.rb (734 Bytes)

···

2009/12/30 fkocherga <fkocherga@gmail.com>:

AFAIK it hasn't changed and your code could never work in any version
of Ruby because the const lookup in method #n is done _statically_.

But it should not, consider:

module M
module N
end
end

#Class.new do <---- This does not work in 1.8.7!
class B < Object
include M
N
end

When 'class B < Object' replaced with 'Class.new do' the Ruby 1.8.7 interpreter complains about uninitialized constant N. What is the big reason for dynamically defined class to behave so differently? It would be very non obvious and unexpected behavior. Actually both cases work as expected in Ruby 1.9.1 and this is correct behavior according to the Ruby Draft.

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

Ah, now I see. I believe your problem comes from the fact that you
are mixing two styles: DSL and "regular" Ruby. If you integrate
defining those modules into your DSL (i.e. not via "module ... end")
then integrating lookups might be easier as well. I don't have a
clear idea yet how to do that but maybe it's worth exploring.

Kind regards

robert

···

2009/12/29 Intransition <transfire@gmail.com>:

On Dec 29, 3:16 pm, Robert Klemme <shortcut...@googlemail.com> wrote:

I believe you haven't yet fully analyzed the problem you want to
solve. I suggest to put it to sleep for a while and then get back
later to it. I can't help you any more because to me it is not clear
what you are trying to achieve. So far we only went through technical
issues but the problem you are trying to solve isn't cleat to me yet.

All I am trying to do is emulate test/unit but using a DSL.
Essentially:

class MyTest < Test::Unit::TestCase

include M

def test_N_n1
assert_equal(N.n1, "n1")
end

end

Becomes:

testcase :MyTest do

include M

testunit :N_n1 do
assert_equal(N.n1, "n1")
end

end

That's it. But I can't do it exactly b/c I can't make the include
work.

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

Nice clarification.

Are there two issues here? This issue and the resolution of constants
via instance_eval? Or are these two aspects of the same issue?

In either case, there is no doubt in my mind that 'class B' and 'B =
Class.new do' should work the same.

···

On Dec 29, 9:04 pm, fkocherga <fkoche...@gmail.com> wrote:

> AFAIK it hasn't changed and your code could never work in any version
> of Ruby because the const lookup in method #n is done _statically_.

But it should not, consider:

module M
module N
end
end

#Class.new do <---- This does not work in 1.8.7!
class B < Object
include M
N
end

When 'class B < Object' replaced with 'Class.new do' the Ruby 1.8.7 interpreter complains about uninitialized constant N. What is the big reason for dynamically defined class to behave so differently? It would be very non obvious and unexpected behavior. Actually both cases work as expected in Ruby 1.9.1 and this is correct behavior according to the Ruby Draft.

That change may not be permanent.

There was a long thread on ruby-core a month or two ago, prompted by a
question raised by Yehuda Katz about the problems the change was
causing for existing DSLs like ActiveRecord and RSpec. After various
proposals to modify the 1.9 behavior to make it more compatible,
Maeda-san posted this:

Matz seems to be in favor of returning to the 1.8 behavior.

···

On Wed, Dec 30, 2009 at 4:34 AM, Robert Klemme <shortcutter@googlemail.com> wrote:

To sum it up: Ruby 1.9 changed lookup rules from lexical (aka static)
to dynamic.

--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

Very helpful. Thanks for going to all the trouble, Robert. I now see
the issue I am facing laser clear.

···

On Dec 30, 4:34 am, Robert Klemme <shortcut...@googlemail.com> wrote:

Thanks for the test case! It never occurred to me to do a const
lookup in a class defined with a class body so I never stumbled across
this. I did a bit of research and this is what I found:

Statement from Matz about the change: "In 1.8, constant uses lexical
look-up, even within the block given to instance_eval(). We changed
this behavior in 1.9 to simplify things."http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/181646

Found viahttp://eigenclass.org/hiki/withdrawn-experimental-ruby-features
- I am not so sure about the "experimental" status of this though -
maybe this is due to the last update date of the page in 2007...

Adam Gardner also made an interesting observation about the difference
between const_get and direct constant lookup:http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/333677
(I have changed the test output to easier interpret it. See attachment.)

There's also this discussionhttp://blade.nagaokaut.ac.jp/cgi-bin/vframe.rb/ruby/ruby-core/25865?2...

And thishttp://blade.nagaokaut.ac.jp/cgi-bin/vframe.rb/ruby/ruby-talk/334016?...

To sum it up: Ruby 1.9 changed lookup rules from lexical (aka static)
to dynamic. IMHO this explains the observed different behavior.
Thanks again for poking.