From: Intransition on 6 Jun 2010 15:41 Do singleton classes not get the same namespace treatment as normal classes? module M class X; end end o = Object.new => #<Object:0x7fc61f1a1e58> (class << o; self; end).class_eval{ include M } => #<Object:0x7fc61f1a1e58> def o.x; X; end o.x => NameError: uninitialized constant X from (irb):6:in `x' from (irb):7 The "(class << o; self; end).class_eval{ include M }" is effectively the same as "o.extend M" but I want to emphasize the use of #include. It of course works fine if I use an explicit class. class O include M def x; X; end end O.new.x => M::X
From: Robert Klemme on 7 Jun 2010 05:34 2010/6/6 Intransition <transfire(a)gmail.com>: > Do singleton classes not get the same namespace treatment as normal > classes? I think so. > module M > class X; end > end > > o = Object.new > => #<Object:0x7fc61f1a1e58> > > (class << o; self; end).class_eval{ include M } > => #<Object:0x7fc61f1a1e58> > > def o.x; X; end This cannot work since X is not statically in scope. > o.x > => NameError: uninitialized constant X > from (irb):6:in `x' > from (irb):7 > > The "(class << o; self; end).class_eval{ include M }" is effectively > the same as "o.extend M" but I want to emphasize the use of #include. > > It of course works fine if I use an explicit class. > > class O > include M > def x; X; end > end > > O.new.x > => M::X Yes, but you also changed something else: you defined the method inside the class body. So you did not only switch from class to singleton class but you also changed the lookup. It works if you define the method in the class body in the same way as you did for class O: irb(main):001:0> module M irb(main):002:1> class X; end irb(main):003:1> end => nil irb(main):004:0> o = Object.new => #<Object:0x1016f240> irb(main):005:0> (class << o; self; end).class_eval do irb(main):006:1* include M irb(main):007:1> def x; X; end irb(main):008:1> end => nil irb(main):009:0> o.x => M::X irb(main):010:0> (class << o; self; end).class_eval do irb(main):011:1* def y; X; end irb(main):012:1> end => nil irb(main):013:0> o.y => M::X irb(main):014:0> Kind regards robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/
From: Caleb Clausen on 7 Jun 2010 09:52 On 6/7/10, Robert Klemme <shortcutter(a)googlemail.com> wrote: > 2010/6/6 Intransition <transfire(a)gmail.com>: >> Do singleton classes not get the same namespace treatment as normal >> classes? > > I think so. > >> module M >> class X; end >> end >> >> o = Object.new >> => #<Object:0x7fc61f1a1e58> >> >> (class << o; self; end).class_eval{ include M } >> => #<Object:0x7fc61f1a1e58> >> >> def o.x; X; end > > This cannot work since X is not statically in scope. Ah, but constant lookup is supposed to check the ancestors if the constant is not found in the scope. M should be among the ancestors of o's singleton class, shouldn't it? I would have expected this to work. OTOH, constant lookup is confusing. This way works: module M class X; end end o = Object.new # => #<Object:0x7fc61f1a1e58> (class << o; self; end).class_eval{ include M } # => #<Object:0x7fc61f1a1e58> #or o.extend M as well, presumably class<<o def x; X end end o.x #=>M::X See http://ruby.runpaint.org/variables#constants in which the lookup rules are summarized as: (Module.nesting + container.ancestors + Object.ancestors).uniq #slightly paraphrased I guess the key point to understand is that for singleton methods, container is the (static) module of class enclosing the singleton method, NOT the singleton class that they affect.
From: Robert Klemme on 7 Jun 2010 10:18 2010/6/7 Caleb Clausen <vikkous(a)gmail.com>: > On 6/7/10, Robert Klemme <shortcutter(a)googlemail.com> wrote: >> 2010/6/6 Intransition <transfire(a)gmail.com>: >>> Do singleton classes not get the same namespace treatment as normal >>> classes? >> >> I think so. >> >>> module M >>> class X; end >>> end >>> >>> o = Object.new >>> => #<Object:0x7fc61f1a1e58> >>> >>> (class << o; self; end).class_eval{ include M } >>> => #<Object:0x7fc61f1a1e58> >>> >>> def o.x; X; end >> >> This cannot work since X is not statically in scope. > > Ah, but constant lookup is supposed to check the ancestors if the > constant is not found in the scope. M should be among the ancestors of > o's singleton class, shouldn't it? It does but you are not in the scope of the singleton class. Rather you are in the toplevel (or any other) scope when you do "def o.x; X; end". > I would have expected this to work. > OTOH, constant lookup is confusing. > > This way works: > > module M > class X; end > end > > o = Object.new # => #<Object:0x7fc61f1a1e58> > > (class << o; self; end).class_eval{ include M } # => #<Object:0x7fc61f1a1e58> > #or o.extend M as well, presumably > > class<<o > def x; X end > end > > o.x #=>M::X That's basically the same what I did: you create the method in the singleton class's scope. > See http://ruby.runpaint.org/variables#constants in which the lookup > rules are summarized as: > (Module.nesting + container.ancestors + Object.ancestors).uniq > #slightly paraphrased > > I guess the key point to understand is that for singleton methods, > container is the (static) module of class enclosing the singleton > method, NOT the singleton class that they affect. Not sure I can follow you here. IMHO the key point is to understand that it is a difference whether you open a scope (class, module) or access the scope from the outside: irb(main):001:0> module M irb(main):002:1> class X; end irb(main):003:1> O = Object.new irb(main):004:1> end => #<Object:0x101792b4> irb(main):005:0> def (M::O).x; X; end => nil irb(main):006:0> M::O.x NameError: uninitialized constant X from (irb):5:in `x' from (irb):6 from /opt/bin/irb19:12:in `<main>' irb(main):007:0> module M irb(main):008:1> def O.y; X; end irb(main):009:1> end => nil irb(main):010:0> M::O.y => M::X irb(main):011:0> def (M::O).x; M::X; end => nil irb(main):012:0> M::O.x => M::X Kind regards robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/
From: Caleb Clausen on 7 Jun 2010 11:42 On 6/7/10, Robert Klemme <shortcutter(a)googlemail.com> wrote: > 2010/6/7 Caleb Clausen <vikkous(a)gmail.com>: >> Ah, but constant lookup is supposed to check the ancestors if the >> constant is not found in the scope. M should be among the ancestors of >> o's singleton class, shouldn't it? > > It does but you are not in the scope of the singleton class. Rather > you are in the toplevel (or any other) scope when you do "def o.x; X; > end". >> I guess the key point to understand is that for singleton methods, >> container is the (static) module of class enclosing the singleton >> method, NOT the singleton class that they affect. > > Not sure I can follow you here. IMHO the key point is to understand > that it is a difference whether you open a scope (class, module) or > access the scope from the outside: Sorry, I meant 'module or class', not 'module of class'. Basically, I'm agreeing with what you said just above. It just took me a little longer to get to the same point of understanding about constant lookup that you were at. (Like I said: constant lookup is confusing.)
|
Next
|
Last
Pages: 1 2 Prev: inject method of Array class Next: [ANN] io_splice 2.0.0 - IO::Splice.copy_stream fixes |