Forum: Ruby-core [ruby-trunk - Feature #8046][Open] allow Object#extend to take a block

3df767279ce7d81db0a5bb30f5136863?d=identicon&s=25 Matthew Kerwin (mattyk)
on 2013-03-08 03:49
(Received via mailing list)
Issue #8046 has been reported by phluid61 (Matthew Kerwin).

----------------------------------------
Feature #8046: allow Object#extend to take a block
https://bugs.ruby-lang.org/issues/8046

Author: phluid61 (Matthew Kerwin)
Status: Open
Priority: Normal
Assignee:
Category:
Target version: next minor


=begin
In #8038 david_macmahon proposed:

How about allowing Object#extend to take a block that would be executed
with the context such that methods defined therein would become
singleton methods of the object receiving #extend?

For example:
 foo = Object.new
 foo.extend do
   def bar
     # ...
   end
   def baz
     # ...
   end
 end
=end
Bcb6acc9d0d9bef99e033b36c3d32ca9?d=identicon&s=25 charliesome (Charlie Somerville) (Guest)
on 2013-03-08 03:56
(Received via mailing list)
Issue #8046 has been updated by charliesome (Charlie Somerville).


=begin
There are two ways to do this - make the extend block execute in the
context of the receiver's singleton class, or make it execute in the
context of a new module to be mixed in to the receiver's singleton
class.

For example:

    def extend(&bk)
      singleton_class.class_eval(&bk)
    end

or

    def extend(&bk)
      singleton_class.send(:include, Module.new(&bk))
    end

Which should it be?
=end
----------------------------------------
Feature #8046: allow Object#extend to take a block
https://bugs.ruby-lang.org/issues/8046#change-37376

Author: phluid61 (Matthew Kerwin)
Status: Open
Priority: Normal
Assignee:
Category:
Target version: next minor


=begin
In #8038 david_macmahon proposed:

How about allowing Object#extend to take a block that would be executed
with the context such that methods defined therein would become
singleton methods of the object receiving #extend?

For example:
 foo = Object.new
 foo.extend do
   def bar
     # ...
   end
   def baz
     # ...
   end
 end
=end
3df767279ce7d81db0a5bb30f5136863?d=identicon&s=25 Matthew Kerwin (mattyk)
on 2013-03-08 05:05
(Received via mailing list)
Issue #8046 has been updated by phluid61 (Matthew Kerwin).


charliesome (Charlie Somerville) wrote:
> There are two ways to do this - make the extend block execute in the
> context of the receiver's singleton class, or make it execute in the
> context of a new module to be mixed in to the receiver's singleton class.
> ...
> Which should it be?

I'd think more like the former, as that doesn't inject a new anonymous
Module into the singleton_class's #ancestors.

Does class_eval do anything dramatically different from module_eval
(i.e. is the block handled differently in either case)?
----------------------------------------
Feature #8046: allow Object#extend to take a block
https://bugs.ruby-lang.org/issues/8046#change-37377

Author: phluid61 (Matthew Kerwin)
Status: Open
Priority: Normal
Assignee:
Category:
Target version: next minor


=begin
In #8038 david_macmahon proposed:

How about allowing Object#extend to take a block that would be executed
with the context such that methods defined therein would become
singleton methods of the object receiving #extend?

For example:
 foo = Object.new
 foo.extend do
   def bar
     # ...
   end
   def baz
     # ...
   end
 end
=end
05ba106041716c821d3ab34bd60ea220?d=identicon&s=25 David MacMahon (Guest)
on 2013-03-08 07:45
(Received via mailing list)
On Mar 7, 2013, at 6:53 PM, charliesome (Charlie Somerville) wrote:

>    end
At the risk of being overly pedantic, since we're talking about
Object#extend, I think it would be more like:

  def extend(*modules, &bk)
    # extend singleton_class with modules, if any
    singleton_class.class_eval(&bk) if bk
  end

or

  def extend(module=nil, &bk)
    # extend singleton_class with modules, if any
    singleton_class.send(:include, Module.new(&bk)) if bk
  end

Which raises another question: what would be the order of extending if
#extend is passed one or more modules *and* given a block?  IOW, should
the passed in module(s) be included first thereby giving the block the
opportunity to override them or vice versa (or should this be explicitly
disallowed)?  I guess I'd favor the first way (include module(s) first,
then block can override).

On the original question I tend to agree with @phluid61 that it would be
preferable to avoid inserting an anonymous Module in the
singleton_class's ancestors.  Would having the anonymous module provide
any advantage over not having it?

Thanks,
Dave

P.S.  Why "singleton_class.send(:include, Module.new(&bk))" instead of
just "singleton_class.include(Module.new(&bk))"?  Are these somehow not
equivalent?
3df767279ce7d81db0a5bb30f5136863?d=identicon&s=25 Matthew Kerwin (mattyk)
on 2013-03-08 08:27
(Received via mailing list)
Issue #8046 has been updated by phluid61 (Matthew Kerwin).


david_macmahon (David MacMahon) wrote:
> Which raises another question: what would be the order of extending if
> #extend is passed one or more modules *and* given a block?  IOW, should
> the passed in module(s) be included first thereby giving the block the
> opportunity to override them or vice versa (or should this be explicitly
> disallowed)?  I guess I'd favor the first way (include module(s) first,
> then block can override).

That's the order Facets uses:
https://github.com/rubyworks/facets/blob/master/li...

> On the original question I tend to agree with @phluid61 that it would be
> preferable to avoid inserting an anonymous Module in the
> singleton_class's ancestors.  Would having the anonymous module provide
> any advantage over not having it?

My reasoning against was that on calling it a second time, there would
be a second anonymous module, and so on.

> P.S.  Why "singleton_class.send(:include, Module.new(&bk))" instead of
> just "singleton_class.include(Module.new(&bk))"?  Are these somehow not
> equivalent?

#include is private, so can't be called directly from outside the
singleton_class object.
----------------------------------------
Feature #8046: allow Object#extend to take a block
https://bugs.ruby-lang.org/issues/8046#change-37382

Author: phluid61 (Matthew Kerwin)
Status: Open
Priority: Normal
Assignee:
Category:
Target version: next minor


=begin
In #8038 david_macmahon proposed:

How about allowing Object#extend to take a block that would be executed
with the context such that methods defined therein would become
singleton methods of the object receiving #extend?

For example:
 foo = Object.new
 foo.extend do
   def bar
     # ...
   end
   def baz
     # ...
   end
 end
=end
F1d6cc2b735bfd82c8773172da2aeab9?d=identicon&s=25 Nobuyoshi Nakada (nobu)
on 2013-03-08 13:20
(Received via mailing list)
Issue #8046 has been updated by nobu (Nobuyoshi Nakada).


Without a module, it'd not be #extend but #singleton_class_eval.
----------------------------------------
Feature #8046: allow Object#extend to take a block
https://bugs.ruby-lang.org/issues/8046#change-37390

Author: phluid61 (Matthew Kerwin)
Status: Open
Priority: Normal
Assignee:
Category:
Target version: next minor


=begin
In #8038 david_macmahon proposed:

How about allowing Object#extend to take a block that would be executed
with the context such that methods defined therein would become
singleton methods of the object receiving #extend?

For example:
 foo = Object.new
 foo.extend do
   def bar
     # ...
   end
   def baz
     # ...
   end
 end
=end
This topic is locked and can not be replied to.