When a required module redefine another module => problem

Here is the sample code:

module SomeModule
require 'set’
class InModule
include Enumerable
def initialize
@index=0
end
def each
if @index == 10
@index=0
else
yield @index
end
end
end
end

class OutModule
include Enumerable
def initialize
@index=0
end
def each
if @index == 10
@index=0
else
yield @index
end
end
end

in_module = SomeModule::InModule.new
out_module = OutModule.new
in_module_set = in_module.to_set
p in_module_set

should raise NoMethodError exception

out_module_set = out_module.to_set
p out_module_set

#<Set: {0}>
#<Set: {0}>

The fact is that it would be more adequate to have Enumerable modified
in SomeModule only. This case is simple, but we can imagine more vicious
sample codes, with some method redefined => it will affect the whole
program! This is a problem, isn’t it?

What do you think about this?

Lio

this is a problem that I have’nt faced yet, but people talk about it
from time to time. Matz said in the latest ruby conf that ruby2 could
have a construct like:

namespace ‘foo’ do
do bad stuff
end

do other stuff

but I believ that could be quite bad in performance.

Talking about your problem:
you may add
private :to_set
to OutModule, or you could just lock Enumerable:
Enumerable.freeze.
require ‘set’ rescue nil

and add to_set by yourself:
class InModule
def to_set
Set.new(self)
end
end

Btw I agree that a require should affect the actual scope not the
toplevel one.

(bad idea inside: change the semantic of
class K end
to be implicitly
class K < ::K end
to avoid namespace clashes and still get the feeling of singletons :stuck_out_tongue_winking_eye:
)

···

il Tue, 09 Mar 2004 16:07:17 +0100, shasckaw shasckaw@skynet.be ha scritto::

The fact is that it would be more adequate to have Enumerable modified
in SomeModule only. This case is simple, but we can imagine more vicious
sample codes, with some method redefined => it will affect the whole
program! This is a problem, isn’t it?

What do you think about this?

“shasckaw” shasckaw@skynet.be schrieb im Newsbeitrag
news:404ddab0$0$13860$ba620e4c@news.skynet.be…

The fact is that it would be more adequate to have Enumerable modified
in SomeModule only. This case is simple, but we can imagine more vicious
sample codes, with some method redefined => it will affect the whole
program! This is a problem, isn’t it?

What do you think about this?

I think this is not limited to modules but to all situations in Ruby
where you can redefine existing things (classes, methods, instance methods
etc.) and where this is done in different places that don’t know anything
about each other. But since this feature is mentioned as one of the
strengths of Ruby (“flexibility”) most of the time, I’d say apparently
it’s not a problem. After all, most of us around here are aware of this
and it doesn’t stop us from using Ruby, does it? :slight_smile:

My 0.02 EUR…

Kind regards

robert

Robert Klemme wrote:

I think this is not limited to modules but to all situations in Ruby
where you can redefine existing things (classes, methods, instance methods
etc.) and where this is done in different places that don’t know anything
about each other. But since this feature is mentioned as one of the
strengths of Ruby (“flexibility”) most of the time, I’d say apparently
it’s not a problem. After all, most of us around here are aware of this
and it doesn’t stop us from using Ruby, does it? :slight_smile:
Well, I must tell I wasn’t aware of this until recently. But that’s
true, I won’t stop using ruby for that. But there is a thing that seems
strange to me with that fact.

When using extend, the extension act only for the instance. Here is a
sample code:
module Thing
def test
print “in Thing\n”
end
end

class Stuff
def test
print “in Stuff\n”
end
end

thing = Stuff.new
stuff = Stuff.new
thing.test
stuff.test
thing.extend(Thing)
thing.test
stuff.test

Which output:
in Stuff
in Stuff
in Thing
in Stuff

If extend can mix in a module in the class of an instance and be
available only for that instance, why requiring wouldn’t be local to the
module where require is called? Or at least only its class
redefinitions? (same remark for include)

Lio

“shasckaw” shasckaw@skynet.be schrieb im Newsbeitrag
news:404ef6ac$0$780$ba620e4c@news.skynet.be…

Robert Klemme wrote:

I think this is not limited to modules but to all situations in Ruby
where you can redefine existing things (classes, methods, instance
methods
etc.) and where this is done in different places that don’t know
anything
about each other. But since this feature is mentioned as one of the
strengths of Ruby (“flexibility”) most of the time, I’d say apparently
it’s not a problem. After all, most of us around here are aware of
this
and it doesn’t stop us from using Ruby, does it? :slight_smile:
Well, I must tell I wasn’t aware of this until recently. But that’s
true, I won’t stop using ruby for that. But there is a thing that seems
strange to me with that fact.

It’s only strange for you because you have certain expectations that don’t
match require’s behavior. Maybe you’re coming from a C / C++ background
and expect require to behave similar to #include.

If extend can mix in a module in the class of an instance and be
available only for that instance, why requiring wouldn’t be local to the
module where require is called? Or at least only its class
redefinitions? (same remark for include)

Because require and extend are two fundamentally different things: require
is agnostic of scopes and other programming language artefacts. It merely
loads (and possibly interprets) a file if that hasn’t been loaded already.
So it’s logical that the required file is always evaluated from main
scope. Apart from that, since require can also load shared libraries,
dealing with scopes here would be even more difficult.

Regards

robert