From: Maurizio De Santis on
David A. Black wrote:
>
> module ExtendedSlicer
> def slice(*args)
> arg0 = args[0]
> case arg0
> when Regexp
> grep(arg0)
> else
> super
> end
> end
> end
>
> a = %w{ one two three four }.extend(ExtendedSlicer)
> a.slice(0,2) # ["one", "two"]
> a.slice(/o/) # ["one", "two", "four"]
>
> The main advantage here is that it's a better fit: you need an object to
> behave a certain way, and you teach that object to behave that way.
> Another advantage is that it makes you work a little harder, and
> therefore helps you evaluate more carefully whether or not you need to
> perform the modification at all.
>

Ok, I've learned more from these posts than in two months of
experiments.

Said that "is a bad idea to override a built-in method", I'm trying to
think in this way now: "what happens if I...", so I tried this:


class MyArray < Array; end

module ExtendedSlicer
def slice(*args)
arg0 = args[0]
case arg0
when Regexp
grep(arg0)
else
super
end
end
end

class MyArray
include ExtendedSlicer
end

arr = MyArray.new %w{a b c ab}
puts arr.slice(/a/).inspect => it writes ["a", "ab"] ; correct


instead, if I execute:

module ExtendedSlicer
def slice(*args)
arg0 = args[0]
case arg0
when Regexp
grep(arg0)
else
super
end
end
end

class Array
include ExtendedSlicer
end

arr = Array.new %w{a b c ab}
puts arr.slice(/a/).inspect # => can't convert Regexp into Integer
(TypeError)


Why? Maybe it is forbidden to include a Module in a built-in class, for
security reasons, or... boh! :) Can you explain that?
--
Posted via http://www.ruby-forum.com/.

From: Rick DeNatale on
On Sun, Aug 1, 2010 at 12:07 PM, Maurizio De Santis
<desantis.maurizio(a)gmail.com> wrote:

> Said that "is a bad idea to override a built-in method", I'm trying to
> think in this way now: "what happens if I...", so I tried this:

...

> instead, if I execute:
>
> module ExtendedSlicer
>  def slice(*args)
>    arg0 = args[0]
>    case arg0
>      when Regexp
>        grep(arg0)
>      else
>        super
>    end
>  end
> end
>
> class Array
>  include ExtendedSlicer
> end
>
> arr = Array.new %w{a b c ab}
> puts arr.slice(/a/).inspect # => can't convert Regexp into Integer
> (TypeError)
>
>
> Why? Maybe it is forbidden to include a Module in a built-in class, for
> security reasons, or... boh! :) Can you explain that?

It's because included modules are inserted after the class in the
method lookup chain. They act more like a superclass in that regard,
methods defined in a module don't override methods defined in classes
which include the module.

consider:

module FooModule
def foo
"FooModule brand foo."
end
end

class FooMaker
def foo
"FooMaker brand foo."
end
end

class FooFighter < FooMaker
include FooModule
def foo
"I'll do my own foo thank you."
end
end

class FooInheritor < FooMaker
end

class FooIncluder
include FooModule
end

class FooBothInheritAndInclude < FooMaker
include FooModule
end

FooMaker.new.foo # => "FooMaker brand foo."
FooFighter.new.foo # => "I'll do my own foo thank you."
FooInheritor.new.foo # => "FooMaker brand foo."
FooBothInheritAndInclude.new.foo # => "FooModule brand foo."

# The ancestors method shows the order in which classes and modules
are searched for a method:

FooMaker.ancestors # => [FooMaker, Object, Kernel]
FooFighter.ancestors # => [FooFighter, FooModule,
FooMaker, Object, Kernel]
FooInheritor.ancestors # => [FooInheritor, FooMaker,
Object, Kernel]
FooBothInheritAndInclude.ancestors # => [FooBothInheritAndInclude,
FooModule, FooMaker, Object, Kernel]

# Note that in the last case the leaf class doesn't define foo, and
the method in FooModule overrides the one in FooMaker

# And of course singleton methods trump everything:

monty = FooBothInheritAndInclude.new
monty.foo # => "FooModule brand foo."

def monty.foo
"and now for something completely different"
end

monty.foo # => "and now for something completely different"


--
Rick DeNatale

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

From: Jean-Julien Fleck on
Hello,

> Why? Maybe it is forbidden to include a Module in a built-in class, for
> security reasons, or... boh! :) Can you explain that?

I think it has to do with inheritance when looking for methods.

First, ruby look in the class itself to see if there is a method named
'slice'. When you try to extend Array, it find Array's original
'slice' and so does not need to look at the module (and never find
your redefinition).

If no method of that name is found in the class (like MyArray), it
looks in the modules (if any) included in your class (and find one
'slice' in ExtendedSlicer) before looking at the ancestor class (which
is Array).

If I'm not mistaken, it should explain the observed behavior.

All that (and more ! :o) is explained in David's book (The
Well-Grounded Rubyist) in a crystal-clear manner around p100 of my
version.

Cheers,

--
JJ Fleck
PCSI1 Lycée Kléber

From: Maurizio De Santis on
Clear as spring wat - better do not mention Spring! - bright as a
flawless Ruby! :D Thanks to everyone! And forgive me for the joke :P
--
Posted via http://www.ruby-forum.com/.