Forum: Ruby once again looking for my module methods

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Trans (Guest)
on 2006-03-20 14:04
(Received via mailing list)
Gee. Once again I want my module methods inherited.
Robert Klemme (Guest)
on 2006-03-20 14:48
(Received via mailing list)
Trans wrote:
> Gee. Once again I want my module methods inherited.

How are they not?

	robert
58aa8536f985277ebef53fa931863a3e?d=identicon&s=25 James G. (bbazzarrakk)
on 2006-03-20 14:55
(Received via mailing list)
On Mar 20, 2006, at 7:48 AM, Robert Klemme wrote:

> Trans wrote:
>> Gee. Once again I want my module methods inherited.
>
> How are they not?

 >> module Example
 >>   def self.i_am_a_module_method
 >>     puts "Hello"
 >>   end
 >> end
=> nil
 >> include Example
=> Object
 >> i_am_a_module_method
NameError: undefined local variable or method `i_am_a_module_method'
for main:Object
         from (irb):10
         from :0

James Edward Gray II
E25d485841b8a642b0aceff64766961b?d=identicon&s=25 Edwin V. (blackedder)
on 2006-03-20 15:58
Trans wrote:
> Gee. Once again I want my module methods inherited.

I agree, I was actually going to look into it why it didn't work for me,
but now I know it's not my fault, but actually a problem with ruby :) So
thanks for saving me a couple of minutes of frustration :)
Iain D Broadfoot (Guest)
on 2006-03-20 16:19
(Received via mailing list)
Edwin van Leeuwen said something:
> Trans wrote:
>> Gee. Once again I want my module methods inherited.
>
> I agree, I was actually going to look into it why it didn't work for me,
> but now I know it's not my fault, but actually a problem with ruby :) So
> thanks for saving me a couple of minutes of frustration :)

One naive and ugly solution is:

module Foo
  def self.included c
    c.instance_eval{
      def self.foo
        :foo
      end

      def self.bar
        :bar
      end
    }
  end
end

which works, but it's far from perfect.

iain
unknown (Guest)
on 2006-03-20 16:46
(Received via mailing list)
Hi --

On Tue, 21 Mar 2006, Iain D Broadfoot wrote:

> module Foo
>  end
> end
>
> which works, but it's far from perfect.

You're taking the long road :-)

   module Foo
     def self.included(c)
       def c.foo
         :foo
       end
     end
     #...
   end


David

--
David A. Black (dblack@wobblini.net)
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

"Ruby for Rails" chapters now available
from Manning Early Access Program! http://www.manning.com/books/black
Trans (Guest)
on 2006-03-20 16:48
(Received via mailing list)
Actually, I have developed what is probably the most complete solution
out there. Check out Calibre's

  require 'calibre/classinherit'

Even so, any solution is still an ugly hack and imperfect to the real
solution. Hint. Hint.

---- classinherit.rb

#:title: ClassInherit
#
# This framework provides a very convenient way to have modules
# pass along class methods in the inheritance chain.
#
# Presently in Ruby the class/module methods of a module
# are not inherited when a module is included --contrary to
# the behavior of classes themselves when they are subclassed.
# To achieve the same behavior with modules requires some clever
# Ruby karate. ClassInherit provides a nice solution.
# Simply place the class inheritable methods in the block
# parameter of the special module method ClassInherit.
#
#   module Mix
#     def inst_meth
#       puts 'inst_meth'
#     end
#
#     ClassInherit do
#       def class_meth
#         "Class Method!"
#       end
#     end
#   end
#
#   class X
#     include Mix
#   end
#
#   X.class_meth  #=> "Class Method!"
#
# ClassInherit is a capitalized method. This is used because it
# indeed creates (or reopens) a ClassInherit module in which
# the given block is evaluated, then the ClassInherit module
# is extended against the current module.
#
# The above is actually equivalent to putting the class/module
# methods in a nested ClassInherit module and extending the
# module _manually_, eg.
#
#   module Mix
#     def inst_meth
#       puts 'inst_meth'
#     end
#
#     module ClassInherit
#       def class_meth
#         "Class Method!"
#       end
#     end
#
#     extend ClassInherit
#   end
#
#   class X
#     include Mix
#   end
#
#   X.class_meth  #=> "Class Method!"
#
# Lastly, #class_inherit is an available alias for #ClassInherit
# if you prefer only lowercase methods.
#
# == Notes
#
# Just a quick comment on the need for this behavior.
#
# A module is an encapsulation of code, hence when a module is included
# (or extends), the module itself should have discretion over how it
# effects the receiving class/module. That is the very embodiment of
# encapsulation. Having it otherwise, as Ruby now does, stymies the
# practice --and we end up with "hacks" like this to compensate.
#
# Ruby would be much improved by making this bevaivor standard.
# And making non-inheritance the exception, which is alwasy easy
# enough to achieve: just put the code in a separate
# (and thus uninherited) module.
#
# == Author(s)
#
# * Thomas Sawyer
# * Nobu Nakada
# * Ulysses
#

class Module

  alias_method :append_features_without_classinherit, :append_features

  def append_features( base )
    result = append_features_without_classinherit( base )
    if const_defined?( :ClassInherit )
      base.extend( self::ClassInherit )
      unless base.is_a?( Class )
        unless base.const_defined?( :ClassInherit )
          base.const_set( :ClassInherit, Module.new )
        end
        my = self
        base::ClassInherit.class_eval do
          include my::ClassInherit
        end
      end
    end
    result
  end

  def ClassInherit( &yld )
    if const_defined?( :ClassInherit )
      self::ClassInherit.class_eval( &yld )
    else
      self.const_set( :ClassInherit, Module.new( &yld ) )
    end
    extend( self::ClassInherit )
    self::ClassInherit
  end

  # For compatibility with old rendition
  alias_method :class_inherit, :ClassInherit

end

class Class
  undef_method :ClassInherit
  undef_method :class_inherit
end
Iain D Broadfoot (Guest)
on 2006-03-20 17:14
(Received via mailing list)
dblack@wobblini.net said something:
> You're taking the long road :-)
>
>    module Foo
>      def self.included(c)
>        def c.foo
>          :foo
>        end
>      end
>      #...
>    end

Ah, I made the classic mistake of simplifying working code to use as an
example. :)

I do more than just create methods, so the instance_eval is useful for
me. (and I'm not refactoring my code for a while, so if I've missed
something reeeeealy simple don't tell me!)

iain
6f830c1616361d3d814bc10198ab92c3?d=identicon&s=25 Andrew T. (vagabond)
on 2006-03-20 18:16
There's also Hyperextend:
http://redhanded.hobix.com/bits/hyperextended.html which is what I ended
up using :)

Vag
Ross Bamford (Guest)
on 2006-03-20 18:35
(Received via mailing list)
On Mon, 2006-03-20 at 22:03 +0900, Trans wrote:
> Gee. Once again I want my module methods inherited.

As usual, I have a feeling the answer is 'no', but doesn't this take
care of it (maybe with improved ignorance of callback methods)?

module Foo
  def self.included(c)
    singleton_methods.reject { |e| e == 'included' }.each do |m|
      mod = self
      c.class_eval do
        (class << self; self; end).class_eval do
          define_method(m, &(mod.method(m)))
        end
      end
    end
    nil
  end

  def self.foo
    :foo
  end

  def self.bar(baz)
    baz
  end

  def joe
    :joe
  end
end

class Baz
  include Foo
end

p Baz.foo
# => :foo
p Baz.bar(:bar)
# => :bar
p Baz.new.joe
# => :joe
unknown (Guest)
on 2006-03-20 19:01
(Received via mailing list)
On Tue, 21 Mar 2006, Trans wrote:

> Actually, I have developed what is probably the most complete solution
> out there. Check out Calibre's
>
>  require 'calibre/classinherit'
>
> Even so, any solution is still an ugly hack and imperfect to the real
> solution. Hint. Hint.
>

i just use this pattern:

     harp:~ > cat a.rb
     module M
       module ClassMethods
         def foo; "foo"; end
       end
       module InstanceMethods
         def bar; "bar"; end
       end

       recursive_inclusion = lambda { |other|
         other.module_eval {
           extend ClassMethods
           include InstanceMethods
           singleton_class = class << self; self; end
           singleton_class.module_eval {
             define_method "included", &recursive_inclusion
           }
           super
         }
       }

       singleton_class = class << self; self; end
       singleton_class.module_eval {
         define_method "included", &recursive_inclusion
       }
     end

     class C
       include M
     end
     class B < C
     end
     module N
       include M
     end
     class D
       include N
     end

     p C::foo
     p C::new.bar
     p B::foo
     p B::new.bar
     p D::foo
     p D::new.bar


     harp:~ > ruby a.rb
     "foo"
     "bar"
     "foo"
     "bar"
     "foo"
     "bar"




regards.

-a
unknown (Guest)
on 2006-03-20 21:01
(Received via mailing list)
Hi --

On Tue, 21 Mar 2006, Ross Bamford wrote:

>      c.class_eval do
>        (class << self; self; end).class_eval do

Is there any reason not to just do that as:

   (class << c; self; end).class_eval

?  (I'm not sure whether there's some other hidden snag or not, as,
per your original question, but that leapt out at me.)


David

--
David A. Black (dblack@wobblini.net)
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

"Ruby for Rails" chapters now available
from Manning Early Access Program! http://www.manning.com/books/black
Ross Bamford (Guest)
on 2006-03-20 22:06
(Received via mailing list)
On Tue, 2006-03-21 at 05:01 +0900, dblack@wobblini.net wrote:
> > module Foo
> >  def self.included(c)
> >    singleton_methods.reject { |e| e == 'included' }.each do |m|
> >      mod = self
> >      c.class_eval do
> >        (class << self; self; end).class_eval do
>
> Is there any reason not to just do that as:
>
>    (class << c; self; end).class_eval
>

No, I don't think so. I just missed it during refactoring :)
unknown (Guest)
on 2006-03-21 04:08
(Received via mailing list)
BTW, There's an RCP asking for this.

I know that a lot of people would really like this (myself included).
Has anyone voiced any serious reasons why *not* to make this the
default behavior?
unknown (Guest)
on 2006-03-21 04:17
(Received via mailing list)
Hi --

On Tue, 21 Mar 2006, eastcoastcoder@gmail.com wrote:

> BTW, There's an RCP asking for this.
>
> I know that a lot of people would really like this (myself included).
> Has anyone voiced any serious reasons why *not* to make this the
> default behavior?

I guess that means you don't think the reasons given in the comment
section of the RCR are serious :-)

I don't think it's a good idea, because I see no reason to favor the
hypothesis that a module's singleton methods are appropriate for a
class, just because the module's instance methods are appropriate for
instances of the class.  That's one possible scenario (and it can
easily be done, already, though I think it's not necessarily a sign of
optimal design), but I don't see why it should be the starting point
and everything else a deviation from it.  See the RCR site for more
comments from me and others.


David

--
David A. Black (dblack@wobblini.net)
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

"Ruby for Rails" chapters now available
from Manning Early Access Program! http://www.manning.com/books/black
unknown (Guest)
on 2006-03-21 05:09
(Received via mailing list)
On Tue, 21 Mar 2006 dblack@wobblini.net wrote:

> I guess that means you don't think the reasons given in the comment
> section of the RCR are serious :-)
>
> I don't think it's a good idea, because I see no reason to favor the
> hypothesis that a module's singleton methods are appropriate for a
> class, just because the module's instance methods are appropriate for
> instances of the class.  That's one possible scenario (and it can
> easily be done, already, though I think it's not necessarily a sign of
> optimal design), but I don't see why it should be the starting point
> and everything else a deviation from it.  See the RCR site for more
> comments from me and others.

indeed:

   class B
   end

   module M
     def M.new() B.new end
   end

   class C
     include M
   end

not least of which.

-a
Trans (Guest)
on 2006-03-21 06:03
(Received via mailing list)
ara.t.howard@noaa.gov wrote:

>
> not least of which.

Your example is misguided.

    class B
    end

    class M
      def M.new() B.new end
    end

    class C < M
    end

T.
Trans (Guest)
on 2006-03-21 17:43
(Received via mailing list)
> I don't think it's a good idea, because I see no reason to favor the
> hypothesis that a module's singleton methods are appropriate
> for a class

What "hypothesis"? It's being used in *practice*.

According to your argument we should not have class method inheritance
either.

T.
Wilson Bilkovich (Guest)
on 2006-03-21 18:45
(Received via mailing list)
I wonder if there's a way to make several groups of people happy by
allowing this:
module Z
  def method; end
end

class A < Z
end

..which would let modules act as abstract classes if necessary.
unknown (Guest)
on 2006-03-21 18:52
(Received via mailing list)
Hi --

On Wed, 22 Mar 2006, Wilson Bilkovich wrote:

> I wonder if there's a way to make several groups of people happy by
> allowing this:
> module Z
>  def method; end
> end
>
> class A < Z
> end
>
> ..which would let modules act as abstract classes if necessary.

There's definitely a school of thought that modules and classes should
be merged, though I am not of it and Matz isn't either :-)


David


>> T.
>>
>>
>>
>
>

--
David A. Black (dblack@wobblini.net)
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

"Ruby for Rails" chapters now available
from Manning Early Access Program! http://www.manning.com/books/black
Trans (Guest)
on 2006-03-21 19:08
(Received via mailing list)
"""
module Z
  def method; end
end

class A < Z
end
"""

Interesting. Although David has taken this to mean a merger of Classes
and Modules, that's not necessarily the case. It simply indicates a
different treatment of said module. It would be as if a method other
than #include were used.

  module Z
    def method; end
  end

  class A
    integrate Z
  end

That really does seem like a win-win solution for all.

Nice catch Wilson!

T.
Trans (Guest)
on 2006-03-21 21:08
(Received via mailing list)
> I don't think it's a good idea, because I see no reason to favor the
> hypothesis that a module's singleton methods are appropriate
> for a class

What "hypothesis"? It's being used in *practice*.

According to your argument we should not have class method inheritance
either.

T.
unknown (Guest)
on 2006-03-21 21:57
(Received via mailing list)
On Wed, 22 Mar 2006, Trans wrote:

>> I don't think it's a good idea, because I see no reason to favor the
>> hypothesis that a module's singleton methods are appropriate
>> for a class
>
> What "hypothesis"? It's being used in *practice*.
>
> According to your argument we should not have class method inheritance
> either.

yeah!   down with inheritance!  up with common blocks!

;-)

-a
Yukihiro Matsumoto (Guest)
on 2006-03-22 01:24
(Received via mailing list)
Hi,

In message "Re: once again looking for my module methods"
    on Tue, 21 Mar 2006 12:17:04 +0900, dblack@wobblini.net writes:

|I don't think it's a good idea, because I see no reason to favor the
|hypothesis that a module's singleton methods are appropriate for a
|class, just because the module's instance methods are appropriate for
|instances of the class.  That's one possible scenario (and it can
|easily be done, already, though I think it's not necessarily a sign of
|optimal design), but I don't see why it should be the starting point
|and everything else a deviation from it.  See the RCR site for more
|comments from me and others.

Thanks, David.  I don't want to make

  include Math

at the toplevel to add sin, cos, etc. to Object class.

							matz.
Trans (Guest)
on 2006-03-22 02:08
(Received via mailing list)
> Thanks, David.  I don't want to make
>
>  include Math
>
> at the toplevel to add sin, cos, etc. to Object class.

It already does. They are there you just can't access them b/c they're
private.

  Object.cos(1)
  NoMethodError: undefined method `cos' for Object:Class
          from (irb):1
  irb(main):002:0> include Math
  => Object
  irb(main):003:0> Object.cos(1)
  NoMethodError: private method `cos' called for Object:Class
          from (irb):3
  irb(main):004:0> class << Object
  irb(main):005:1>   public :cos
  irb(main):006:1> end
  => #<Class:Object>
  irb(main):007:0> Object.cos(1)
  => 0.54030230586814

T.
Wilson Bilkovich (Guest)
on 2006-03-22 15:10
(Received via mailing list)
Speaking of "<<", what about making more use of that piece of syntax?

For example:
class ConcreteThing << Module
end

I don't think that would be precisely "unifying" modules and classes.
I feel pretty comfortable with Ruby these days, and I feel like my
code is highly Ruby-like.
On the other hand, I occasionally miss interfaces and abstract classes
for readability reasons.
This topic is locked and can not be replied to.