Module This::Encompassing::That

Hi,

Do you worry about which namespace D searched in? I guess it must be
top level (not A nor B).

Yes, my problem is with

class D
end

module A
class D
end
end

if I’m right

class A::B < D
end

it’s not the same than

module A
class B < D
end
end

Yes, you’re right as always. It should be treated as if

tmp = D
module A
class B < tmp
end
end

If you want the latter, you have to

class A::B < A::smiley:
end
matz.

···

In message “Re: module This::Encompassing::That” on 03/02/18, ts decoux@moulon.inra.fr writes:

Isn’t

class A::B < ::smiley:

equivalent here?

Gavin

···

On Tuesday, February 18, 2003, 11:56:41 PM, Yukihiro wrote:

Hi,

In message “Re: module This::Encompassing::That” > on 03/02/18, ts decoux@moulon.inra.fr writes:

Do you worry about which namespace D searched in? I guess it must be
top level (not A nor B).

Yes, my problem is with

class D
end

module A
class D
end
end

if I’m right

class A::B < D
end

it’s not the same than

module A
class B < D
end
end

Yes, you’re right as always. It should be treated as if

tmp = D
module A
class B < tmp
end
end

Hi,

tmp = D
module A
class B < tmp
end
end

Isn’t

class A::B < ::smiley:

equivalent here?

Yes. But it can be something like

module Foo
class A::B < D
end
end

where search for D start from Foo, then toplevel (Object).

						matz.
···

In message “Re: module This::Encompassing::That” on 03/02/19, Gavin Sinclair gsinclair@soyabean.com.au writes:

Best to be explicit, IMO. This is syntax sugar, not the solution to
every problem.

Gavin

···

On Wednesday, February 19, 2003, 3:05:48 PM, Yukihiro wrote:

Hi,

In message “Re: module This::Encompassing::That” > on 03/02/19, Gavin Sinclair gsinclair@soyabean.com.au writes:

tmp = D
module A
class B < tmp
end
end

Isn’t

class A::B < ::smiley:

equivalent here?

Yes. But it can be something like

module Foo
class A::B < D
end
end

where search for D start from Foo, then toplevel (Object).

Hi,

···

At Wed, 19 Feb 2003 13:05:48 +0900, Yukihiro Matsumoto wrote:

tmp = D
module A
class B < tmp
end
end

Isn’t

class A::B < ::smiley:

equivalent here?

Yes. But it can be something like

module Foo
class A::B < D
end
end

where search for D start from Foo, then toplevel (Object).

Like this?

Index: node.h

RCS file: //sharui/cvs/ruby/src/ruby/node.h,v
retrieving revision 1.41
diff -u -2 -p -r1.41 node.h
— node.h 16 Jan 2003 07:34:01 -0000 1.41
+++ node.h 19 Feb 2003 01:16:44 -0000
@@ -219,5 +219,5 @@ typedef struct RNode {
#define nd_argc u2.argc

-#define nd_cname u1.id
+#define nd_cpath u1.node
#define nd_super u3.node

Index: eval.c

RCS file: //sharui/cvs/ruby/src/ruby/eval.c,v
retrieving revision 1.397
diff -u -2 -p -r1.397 eval.c
— eval.c 18 Feb 2003 14:30:17 -0000 1.397
+++ eval.c 19 Feb 2003 01:37:51 -0000
@@ -2220,4 +2220,26 @@ svalue_to_avalue(v)
}

+static VALUE
+class_prefix(self, cpath)

  • VALUE self;
  • NODE *cpath;
    +{
  • if (!cpath) {
  • rb_bug(“class path missing”);
  • }
  • if (cpath->nd_head) {
  • return rb_eval(self, cpath->nd_head);
  • }
  • else if (nd_type(cpath) == NODE_COLON2) {
  • return ruby_cbase;
  • }
  • else if (ruby_wrapper) {
  • return ruby_wrapper;
  • }
  • else {
  • return rb_cObject;
  • }
    +}

static void return_check _((void));
#define return_value(v) do {
@@ -3301,5 +3323,6 @@ rb_eval(self, n)
case NODE_CLASS:
{

  •   VALUE super, klass, tmp;
    
  •   VALUE super, klass, tmp, cbase;
    
  •   ID cname;
    
      if (NIL_P(ruby_cbase)) {
    

@@ -3313,12 +3336,14 @@ rb_eval(self, n)
}

  •   if ((ruby_cbase == rb_cObject) && rb_autoload_defined(node->nd_cname)) {
    
  •   rb_autoload_load(node->nd_cname);
    
  •   cbase = class_prefix(self, node->nd_cpath);
    
  •   cname = node->nd_cpath->nd_mid;
    
  •   if ((cbase == rb_cObject) && rb_autoload_defined(cname)) {
    
  •   rb_autoload_load(cname);
      }
    
  •   if (rb_const_defined_at(ruby_cbase, node->nd_cname)) {
    
  •   klass = rb_const_get(ruby_cbase, node->nd_cname);
    
  •   if (rb_const_defined_at(cbase, cname)) {
    
  •   klass = rb_const_get(cbase, cname);
      if (TYPE(klass) != T_CLASS) {
          rb_raise(rb_eTypeError, "%s is not a class",
    
  •   	     rb_id2name(node->nd_cname));
    
  •   	     rb_id2name(cname));
      }
      if (super) {
    

@@ -3336,7 +3361,7 @@ rb_eval(self, n)
override_class:
if (!super) super = rb_cObject;

  •   klass = rb_define_class_id(node->nd_cname, super);
    
  •   rb_set_class_path(klass,ruby_cbase,rb_id2name(node->nd_cname));
    
  •   rb_const_set(ruby_cbase, node->nd_cname, klass);
    
  •   klass = rb_define_class_id(cname, super);
    
  •   rb_set_class_path(klass, cbase, rb_id2name(cname));
    
  •   rb_const_set(cbase, cname, klass);
      }
      if (ruby_wrapper) {
    

@@ -3351,17 +3376,20 @@ rb_eval(self, n)
case NODE_MODULE:
{

  •   VALUE module;
    
  •   VALUE module, cbase;
    
  •   ID cname;
    
      if (NIL_P(ruby_cbase)) {
      rb_raise(rb_eTypeError, "no outer class/module");
      }
    
  •   if ((ruby_cbase == rb_cObject) && rb_autoload_defined(node->nd_cname)) {
    
  •   rb_autoload_load(node->nd_cname);
    
  •   cbase = class_prefix(self, node->nd_cpath);
    
  •   cname = node->nd_cpath->nd_mid;
    
  •   if ((cbase == rb_cObject) && rb_autoload_defined(cname)) {
    
  •   rb_autoload_load(cname);
      }
    
  •   if (rb_const_defined_at(ruby_cbase, node->nd_cname)) {
    
  •   module = rb_const_get(ruby_cbase, node->nd_cname);
    
  •   if (rb_const_defined_at(cbase, cname)) {
    
  •   module = rb_const_get(cbase, cname);
      if (TYPE(module) != T_MODULE) {
          rb_raise(rb_eTypeError, "%s is not a module",
    
  •   	     rb_id2name(node->nd_cname));
    
  •   	     rb_id2name(cname));
      }
      if (ruby_safe_level >= 4) {
    

@@ -3370,7 +3398,7 @@ rb_eval(self, n)
}
else {

  •   module = rb_define_module_id(node->nd_cname);
    
  •   rb_set_class_path(module,ruby_cbase,rb_id2name(node->nd_cname));
    
  •   rb_const_set(ruby_cbase, node->nd_cname, module);
    
  •   module = rb_define_module_id(cname);
    
  •   rb_set_class_path(module, cbase, rb_id2name(cname));
    
  •   rb_const_set(cbase, cname, module);
      }
      if (ruby_wrapper) {
    

Index: gc.c

RCS file: //sharui/cvs/ruby/src/ruby/gc.c,v
retrieving revision 1.121
diff -u -2 -p -r1.121 gc.c
— gc.c 31 Jan 2003 04:00:15 -0000 1.121
+++ gc.c 19 Feb 2003 03:13:56 -0000
@@ -649,4 +649,5 @@ rb_gc_mark_children(ptr)
case NODE_RESCUE:
case NODE_RESBODY:

  • case NODE_CLASS:
      rb_gc_mark((VALUE)obj->as.node.u2.node);
      /* fall through */
    

@@ -685,4 +686,5 @@ rb_gc_mark_children(ptr)
case NODE_OP_ASGN_OR:
case NODE_OP_ASGN_AND:

  • case NODE_MODULE:
      rb_gc_mark((VALUE)obj->as.node.u1.node);
      /* fall through */
    

@@ -697,5 +699,4 @@ rb_gc_mark_children(ptr)
case NODE_CVDECL:
case NODE_CVASGN:

  • case NODE_MODULE:
    case NODE_COLON3:
    case NODE_OPT_N:
    

@@ -720,5 +721,4 @@ rb_gc_mark_children(ptr)

  case NODE_SCOPE:	/* 2,3 */
  • case NODE_CLASS:
    case NODE_BLOCK_PASS:
      rb_gc_mark((VALUE)obj->as.node.u3.node);
    

Index: parse.y

RCS file: //sharui/cvs/ruby/src/ruby/parse.y,v
retrieving revision 1.255
diff -u -2 -p -r1.255 parse.y
— parse.y 13 Feb 2003 09:11:08 -0000 1.255
+++ parse.y 19 Feb 2003 05:15:58 -0000
@@ -241,5 +241,5 @@ static void top_local_setup();
%type string_contents xstring_contents string_content
%type words qwords word_list qword_list word
-%type literal numeric dsym
+%type literal numeric dsym cbase cpath
%type bodystmt compstmt stmts stmt expr arg primary command command_call method_call
%type expr_value arg_value primary_value
@@ -838,4 +838,25 @@ cname : tIDENTIFIER
;

+cbase : tCOLON3 cname

  •       {
    
  •   	$$ = NEW_COLON3($2);
    
  •       }
    
  •   | cname
    
  •       {
    
  •   	$$ = NEW_CONST($1);
    
  •       }
    
  •   | cbase tCOLON2 cname
    
  •       {
    
  •   	$$ = NEW_COLON2($1, $3);
    
  •       }
    
  •   ;
    

+cpath : cbase

  •       {
    
  •   	if (nd_type($$ = $1) == NODE_CONST)
    
  •   	    $$ = NEW_COLON2(0, $$->nd_vid);
    
  •       }
    
  •   ;
    

fname : tIDENTIFIER
> tCONSTANT
@@ -1526,5 +1547,5 @@ primary : literal
fixpos($$, $2);
}

  •   | kCLASS cname superclass
    
  •   | kCLASS cpath superclass
          {
      	if (in_def || in_single)
    

@@ -1564,5 +1585,5 @@ primary : literal
in_single = $6;
}

  •   | kMODULE cname
    
  •   | kMODULE cpath
          {
      	if (in_def || in_single)
    


Nobu Nakada

Hi,

Like this?

Oops, missed.

— eval.c~ Wed Feb 19 10:37:51 2003
+++ eval.c Wed Feb 19 14:34:07 2003
@@ -2229,5 +2229,14 @@ class_prefix(self, cpath)
}
if (cpath->nd_head) {

  • return rb_eval(self, cpath->nd_head);
  • VALUE c = rb_eval(self, cpath->nd_head);
  • switch (TYPE(c)) {
  • case T_CLASS:
    
  • case T_MODULE:
    
  •   break;
    
  • default:
    
  •   rb_raise(rb_eTypeError, "%s is not a class/module",
    
  •        RSTRING(rb_obj_as_string(c))->ptr);
    
  • }
  • return c;
    }
    else if (nd_type(cpath) == NODE_COLON2) {
···

At Wed, 19 Feb 2003 14:27:18 +0900, nobu.nokada@softhome.net wrote:


Nobu Nakada

Hi,

···

In message “Re: module This::Encompassing::That” on 03/02/19, nobu.nokada@softhome.net nobu.nokada@softhome.net writes:

At Wed, 19 Feb 2003 13:05:48 +0900, >Yukihiro Matsumoto wrote:

tmp = D
module A
class B < tmp
end
end

Isn’t

class A::B < ::smiley:

equivalent here?

Yes. But it can be something like

module Foo
class A::B < D
end
end

where search for D start from Foo, then toplevel (Object).

Like this?

I think class_prefix should be a sequence of modules, so that type
check in [ruby-talk:65161] should detect classes as error. But I like
the idea. Can you commit this patch? I’d like to see how this works.

						matz.

I think class_prefix should be a sequence of modules, so that
type check in [ruby-talk:65161] should detect classes as
error. But I like the idea. Can you commit this patch? I’d
like to see how this works.

Do you mean that

module A
end

class A::B
end

and

class C
end

module C::smiley:
end

would both be errors? Why? It seems that if I already created the
container(s) (which I think should be required), I should be able to put
either a module or a class inside of them, regardless of whether they’re
a module, a class, or both.

Just wondering,

Nathaniel

<:((><

···

Yukihiro Matsumoto [mailto:matz@ruby-lang.org] wrote:

RoleModel Software, Inc.
EQUIP VI

Hi,

Do you mean that

module A
end

class A::B
end

and

class C
end

module C::smiley:
end

would both be errors?

No, the former would not be an error, since

class A::B
end

is equivalent to

module A
class B
end
end

The latter would be an error, because

module C::smiley:
end

is equivalent to

module C
module D
end
end

that causes class/module contradiction.

Why? It seems that if I already created the
container(s) (which I think should be required), I should be able to put
either a module or a class inside of them, regardless of whether they’re
a module, a class, or both.

Because classes and modules are not always exchangeable. Making them
too “smart” delays error detection. For example, two files use name A
for different purpose, one for module, one for class:

a.rb:
class A
end

b.rb:
module A::B
end

then if you load “b.rb” first, you will get error. What if you load
“a.rb” first? I think it should report error. Otherwise you can’t
tell whether A is a class or a module from the source without global
analysis, or worse, it might vary time to time.

						matz.
···

In message “Re: module This::Encompassing::That” on 03/02/20, nathaniel@NOSPAMtalbott.ws nathaniel@NOSPAMtalbott.ws writes:

Hi –

Hi,

Do you mean that

module A
end

class A::B
end

and

class C
end

module C::smiley:
end

would both be errors?

No, the former would not be an error, since

class A::B
end

is equivalent to

module A
class B
end
end

The latter would be an error, because

module C::smiley:
end

is equivalent to

module C
module D
end
end

that causes class/module contradiction.

But why is module C::smiley: equivalent to module/module, more than to
class/module? It isn’t equivalent in the reference syntax (include
C::D, etc.), and I think the creation syntax, if any, should be as
close as possible to the reference syntax.

Why? It seems that if I already created the
container(s) (which I think should be required), I should be able to put
either a module or a class inside of them, regardless of whether they’re
a module, a class, or both.

Because classes and modules are not always exchangeable. Making them
too “smart” delays error detection. For example, two files use name A
for different purpose, one for module, one for class:

a.rb:
class A
end

b.rb:
module A::B
end

then if you load “b.rb” first, you will get error. What if you load
“a.rb” first? I think it should report error. Otherwise you can’t
tell whether A is a class or a module from the source without global
analysis, or worse, it might vary time to time.

But that’s always true of the A::B notation; if it’s in a separate
file, you can’t tell what it is. Or if you do this in b.rb instead:

A.module_eval { module B; end }

the same thing is true: it’s an error if you load it first, and you
can’t tell what A is (just from the b.rb source). But it’s legal.

My feeling is that module A::B should be even less smart than you’re
saying :slight_smile: To me, “module A::b::C::D” should mean: “Create (or reopen)
a module called D, with a path through A, B, and C”. An error should
only happen if that path is impossible (e.g., if B is an integer
instead of a class or module).

David

···

On Thu, 20 Feb 2003, Yukihiro Matsumoto wrote:

In message “Re: module This::Encompassing::That” > on 03/02/20, nathaniel@NOSPAMtalbott.ws nathaniel@NOSPAMtalbott.ws writes:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

Hi,

The latter would be an error, because

module C::smiley:
end

is equivalent to

module C
module D
end
end

that causes class/module contradiction.

But why is module C::smiley: equivalent to module/module, more than to
class/module? It isn’t equivalent in the reference syntax (include
C::D, etc.), and I think the creation syntax, if any, should be as
close as possible to the reference syntax.

I can remain “don’t care” for referencing, but not for creation.
That’s the reason. If “module C::D” form requires C to be defined
previously, we don’t care whether it’s a class or module, but I
thought it suppose to define C if it doesn’t exist.

But that’s always true of the A::B notation; if it’s in a separate
file, you can’t tell what it is.

Again, referencing is different from creation.

Or if you do this in b.rb instead:

A.module_eval { module B; end }

the same thing is true: it’s an error if you load it first, and you
can’t tell what A is (just from the b.rb source). But it’s legal.

But ugly. It’s the sign of discouragement. Once

module A::B
end

is available, everybody runs for it.

My feeling is that module A::B should be even less smart than you’re
saying :slight_smile: To me, “module A::b::C::D” should mean: “Create (or reopen)
a module called D, with a path through A, B, and C”. An error should
only happen if that path is impossible (e.g., if B is an integer
instead of a class or module).

So you require A, B and C to be either class or module predefined.
That’s reasonable. But I feel like it’s less useful, but without any
concrete rationale. Let us discuss.

						matz.
···

In message “Re: module This::Encompassing::That” on 03/02/20, dblack@candle.superlink.net dblack@candle.superlink.net writes:

Hi –

I can remain “don’t care” for referencing, but not for creation.
That’s the reason. If “module C::D” form requires C to be defined
previously, we don’t care whether it’s a class or module, but I
thought it suppose to define C if it doesn’t exist.

That’s the autovivification we were talking about earlier in the
thread. I think the consensus is against it. I certainly think it
would be very bad.

My feeling is that module A::B should be even less smart than you’re
saying :slight_smile: To me, “module A::b::C::D” should mean: “Create (or reopen)
a module called D, with a path through A, B, and C”. An error should
only happen if that path is impossible (e.g., if B is an integer
instead of a class or module).

So you require A, B and C to be either class or module predefined.

Yes.

That’s reasonable. But I feel like it’s less useful, but without any
concrete rationale. Let us discuss.

I guess the rationale would mainly be consistency with the reference
notation:

module A
module B
Thing = 1
end
end

puts A::b::Thing

module A::b::SomeModule # likewise with a new module
# …
end

and to save some space. I don’t think it’s urgently needed (original
poster? are you still here? :slight_smile: and if the subclassing syntax/scoping
problems mentioned earlier are too much, it’s probably not a good
idea.

David

···

On Thu, 20 Feb 2003, Yukihiro Matsumoto wrote:
A::b::OtherThing = 2 # create OtherThing, using shorthand path


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

matz@ruby-lang.org (Yukihiro Matsumoto) writes:

So you require A, B and C to be either class or module predefined.
That’s reasonable. But I feel like it’s less useful, but without
any concrete rationale. Let us discuss.

I would be very happy with this restriction (stuff to left of :: must
already exist).

I’m reading this thread in the light of “fixing” autoload. The same
kind of argument against “class A::b::C” applies to not implementing
“autoload(A::b::C, )”.

Being able to do this would be useful, I think:

module Utils; end
autoload Utils::ClassA, 'utils/classa'
autoload Utils::ClassB, 'utils/classb'
autoload Utils::ClassC, 'utils/classc'
autoload Utils::ClassD, 'utils/classd'

In fact, I have written a file like the above and was surprised that
it didn’t work. :wink:

This makes maintaining larger libraries easier, since there is one
place where a class name is associated with a file name.

···


matt

Hi,

That’s the autovivification we were talking about earlier in the
thread. I think the consensus is against it. I certainly think it
would be very bad.

Probably I missed some of the discussion. I will check the archive.

A::b::OtherThing = 2 # create OtherThing, using shorthand path

It’s not on the topic, is it? It is interesting though.

						matz.
···

In message “Re: module This::Encompassing::That” on 03/02/20, dblack@candle.superlink.net dblack@candle.superlink.net writes:

Would it not be clearer to eliminate the duplication of all those prefixes
though? e.g.

  module Utils
    autoload :ClassA, 'utils/classa'
    autoload :ClassB, 'utils/classb'
    autoload :ClassC, 'utils/classc'
    autoload :ClassD, 'utils/classd'
  end

This works for me, as long as 'utils/classa' contains just the definition
of ClassA, i.e. not wrapped in 'module Utils .. end'

That in turn means you can't explicitly "require 'utils/classa'" without
wrapping it inside a module declaration. Is that what the problem is?

Regards,

Brian.

···

On Thu, Feb 20, 2003 at 06:41:24AM +0900, Matt Armstrong wrote:

I'm reading this thread in the light of "fixing" autoload. The same
kind of argument against "class A::b::C" applies to not implementing
"autoload(A::b::C, <file>)".

Being able to do this would be useful, I think:

    module Utils; end
    autoload Utils::ClassA, 'utils/classa'
    autoload Utils::ClassB, 'utils/classb'
    autoload Utils::ClassC, 'utils/classc'
    autoload Utils::ClassD, 'utils/classd'

In fact, I have written a file like the above and was surprised that
it didn't work. :wink:

dblack@candle.superlink.net wrote:

I don’t think it’s urgently needed (original
poster? are you still here? :slight_smile:

No it’s not urgently needed. On the surface, I thought that autovivication
would be a nice thing, but it sounds like there are too many cases to handle.

I was just getting lazy, not wanting to type

module This
module Encompassing
module That
some code
end
end
end

Regards,

···


Bil Kleb
NASA Langley Research Center
Hampton, Virginia, USA

Hi –

···

On Thu, 20 Feb 2003, Yukihiro Matsumoto wrote:

Hi,

In message “Re: module This::Encompassing::That” > on 03/02/20, dblack@candle.superlink.net dblack@candle.superlink.net writes:

A::b::OtherThing = 2 # create OtherThing, using shorthand path

It’s not on the topic, is it? It is interesting though.

Well, I snuck it in :slight_smile: It’s pretty much the same principle.

David


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

Brian Candler B.Candler@pobox.com writes:

···

On Thu, Feb 20, 2003 at 06:41:24AM +0900, Matt Armstrong wrote:

I’m reading this thread in the light of “fixing” autoload. The same
kind of argument against “class A::b::C” applies to not implementing
“autoload(A::b::C, )”.

Being able to do this would be useful, I think:

module Utils; end
autoload Utils::ClassA, 'utils/classa'
autoload Utils::ClassB, 'utils/classb'
autoload Utils::ClassC, 'utils/classc'
autoload Utils::ClassD, 'utils/classd'

In fact, I have written a file like the above and was surprised that
it didn’t work. :wink:

Would it not be clearer to eliminate the duplication of all those prefixes
though? e.g.

module Utils
autoload :ClassA, ‘utils/classa’
autoload :ClassB, ‘utils/classb’
autoload :ClassC, ‘utils/classc’
autoload :ClassD, ‘utils/classd’
end

Yep, that works too. Though if Ruby supports “class Foo::Bar” I would
expect it to support autoload(“Foo::Bar”, …) too.


matt

I made some self-contradictory points during the discussion. I now
believe it’s better to restrict the shorthand syntax to
modules/classes that already exist.

Rationale: YAGNI (it == autovivification of intermediate modules)

If you want to create nested modules without having created, say, the
top-level one, well, it’s pretty easy to put a small definition in,
and that is a good place for a comment.

···

On Thursday, February 20, 2003, 5:53:49 AM, Yukihiro wrote:

That’s the autovivification we were talking about earlier in the
thread. I think the consensus is against it. I certainly think it
would be very bad.

Probably I missed some of the discussion. I will check the archive.

Namespace for Test::Unit framework.

module Test
end

Defines common Test::Unit capabilities.

module Test::Unit

end

The original reason for the suggestion, 37 messages ago, was that

module Test
module Unit
… 200 lines
# we get indentation blindness here.
… 200 lines
end
end

Gavin

Hi,

···

At Thu, 20 Feb 2003 07:06:20 +0900, Brian Candler wrote:

Would it not be clearer to eliminate the duplication of all those prefixes
though? e.g.

module Utils
autoload :ClassA, ‘utils/classa’
autoload :ClassB, ‘utils/classb’
autoload :ClassC, ‘utils/classc’
autoload :ClassD, ‘utils/classd’
end

This modification had been discussed in ruby-dev, from
[ruby-dev:16165] and [ruby-dev:18103]. Perhaps, the final
patch is [ruby-dev:18184].


Nobu Nakada