From: thoran Date: 2009-08-31T12:32:00+09:00 Subject: [ruby-core:25214] Re: Module#prepend and Array#prepend --Apple-Mail-12-651882621 Content-Type: text/plain; charset=US-ASCII; format=flowed; delsp=yes Content-Transfer-Encoding: 7bit Hi Yehuda and all, I started burbling away and haven't done any intros. That's a bit rude of me! I've been using Ruby for almost seven years. In large part it is Ruby's lispiness that sucked me in---after having used lisp at uni. For that time I've mostly been lurking, but feel like I half-know what I'm talking about now! And so, after a self-imposed exile from ruby- talk after I was given the shits, I thought I should properly jump back in. (I needed to supply the list bot with a surname, so I chose "because", for reasons which may be apparent to some.) In that time, I've been bad by having been a bit of a hoarder, but I will release at least a few thousand of lines of code in the context of a code distribution system I've been working on for a while (It plays in a rudimentary way nicely with Rubygems and I'm going to have to do something with git too...)(HINT: $REMOTE_LOAD_PATH), including several hundreds of additional methods on the standard classes, some of which is sugar, many of which are small, a few outright rip-offs (mostly acknowledged), and some simply inspired by other code (also mostly acknowledged). I just need to spend a month or two cleaning it up... (NB. Someone harass me please! Perhaps start by harassing me about Options (a gorgeous little wrapper for OptionParser) and Attributes, which creates default attribute values, sets up getters and setters, setter and getter aliases and integrates with Options optionally for the defaults. I need a bit of encouragement... K? :-) Anyway, to the matter at hand... I don't mind shift/unshift, though I do have aliases Array#first!/ last! for Array#shift/pop in my standard kit as it seems to make more sense sometimes that way. Programming Ruby has Array#unshift as "Prepends object(s) to arr." Don't fight it huh? Might this feature also go some ways to addressing my desire for module-specific behaviours on objects? However this is, in a sense, more explicit than I was desiring. Is it preferable that this be as explicit as Module.append/prepend (I might add those aliases to Array as well, since I made some methods up for String by those names.) only, rather than include an implicit append/prepend by virtue of definitions for methods in the context of a module? I don't mind both, since removing a feature by such a means might be preferable over eval'ing symmetric code. This also relates to my quizzications over Module.ancestors. (I note that Programming Ruby states that it "Returns a list of modules included in mod (including mod itself)." So the behaviour of returning itself as an ancestor is apparently OK! So, is it too much to have: Module.mixins; Module.ancestors/inherits/inherits_from (which only has the super class chain, but flattened to a list); Module.influences/behaves_like/friends_and_family (for mixins and ancestors combined); and Module.behaviours/method_sources (for the lot, as per ancestors now)? Or something like that. (Naming things is hard sometimes.) I use introspection quite a bit, so this is very much an area of interest for me. I've written a number of methods on ObjectSpace and elsewhere to do somewhat related stuff to this, so as I can automate discovery of behaviour. It is slow, but fun. Anyone for "implements"? t On 31/08/2009, at 8:51 AM, Yehuda Katz wrote: > Matz, > > As we discussed at LoneStar, I have the following proposal: > > given the following class: > > class Person > def speak(words) > puts words > end > end > > It should be possible to do the following: > > module Exclaimer > def speak(words) > super("#{words}!") > end > end > > class Person > prepend Exclaimer > end > > and then have: > > Person.new.speak("matz") #=> matz! > > Effectively, prepend would prepend a module to the class' ancestor > chain. Implementation-wise, it means that all methods on a class are > put into an implicit module, or an implicit subclass is created for > each new class that can have modules mixed into it (via prepend). > > We also discussed aliasing unshift to prepend for Arrays, since > shift/unshift is a source of much confusion. > > -- > Yehuda Katz > Developer | Engine Yard > (ph) 718.877.1325 --Apple-Mail-12-651882621 Content-Type: text/html; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Hi Yehuda and = all, 

I started burbling away and haven't done = any intros.  That's a bit rude of me! =  

I've been using Ruby for almost seven = years.  In large part it is Ruby's lispiness that sucked me = in---after having used lisp at uni.  For that time I've = mostly been lurking, but feel like I half-know what I'm talking = about now!  And so, after a self-imposed exile from ruby-talk after = I was given the shits, I thought I should properly jump back in. =  (I needed to supply the list bot with a surname, so I chose = "because", for reasons which may be apparent to some.) =  

In that time, I've been bad by having = been a bit of a hoarder, but I will release at least a few thousand of = lines of code in the context of a code distribution system I've been = working on for a while (It plays in a rudimentary way nicely with = Rubygems and I'm going to have to do something with git too...)(HINT: = $REMOTE_LOAD_PATH), including several hundreds of additional methods on = the standard classes, some of which is sugar, many of which are small, a = few outright rip-offs (mostly acknowledged), and some simply inspired by = other code (also mostly acknowledged).  I just need to spend a = month or two cleaning it up...  

(NB. = Someone harass me please!  Perhaps start by harassing me about = Options (a gorgeous little wrapper for OptionParser) and Attributes, = which creates default attribute values, sets up getters and = setters, setter and getter aliases and integrates with Options = optionally for the defaults.  I need a bit of encouragement... =  K?  :-)  

Anyway, to the = matter at hand...  

I don't mind = shift/unshift, though I do have aliases Array#first!/last! for = Array#shift/pop in my standard kit as it seems to make more sense = sometimes that way.  Programming Ruby has Array#unshift as "Prepends object(s) = to arr."  Don't = fight it huh?  

Might this = feature also go some ways to addressing my desire for module-specific = behaviours on objects?  However this is, in a sense, more explicit = than I was desiring.  

Is it = preferable that this be as explicit as Module.append/prepend (I might = add those aliases to Array as well, since I made some methods up for = String by those names.) only, rather than include an implicit = append/prepend by virtue of definitions for methods in the context of a = module?  

I don't mind both, since = removing a feature by such a means might be preferable over eval'ing = symmetric code.  

This also relates to my = quizzications over Module.ancestors.  (I note that Programming Ruby = states that it "Returns a list of modules included in mod = (including mod itself)."  So the = behaviour of returning itself as an ancestor is apparently OK! =  

So, is it too much to = have: 

Module.mixins; 
Module= .ancestors/inherits/inherits_from (which only has the super class chain, = but flattened to a = list); 
Module.influences/behaves_like/friends_and_family = (for mixins and ancestors combined); = and
Module.behaviours/method_sources (for the lot, as per = ancestors now)?  

Or something like that. =  (Naming things is hard sometimes.) =  

I use introspection quite a bit, so this = is very much an area of interest for me.  I've written a number of = methods on ObjectSpace and elsewhere to do somewhat related stuff to = this, so as I can automate discovery of behaviour.  It is slow, but = fun.  

Anyone for "implements"? =  


t

=
On 31/08/2009, at 8:51 AM, Yehuda Katz wrote:

Matz,

As we discussed at LoneStar, I = have the following proposal:

given the = following class:

class = Person
  def speak(words)
   =  puts words
=
  end
end

It should be = possible to do the following:

module = Exclaimer
  def speak(words)
   =  super("#{words}!")
  end
=
end

class = Person
  prepend = Exclaimer
end

and then = have:

Person.new.speak("matz") #=3D> = matz!

Effectively, prepend would prepend a = module to the class' ancestor chain. Implementation-wise, it means that = all methods on a class are put into an implicit module, or an implicit = subclass is created for each new class that can have modules mixed into = it (via prepend).

We also discussed aliasing = unshift to prepend for Arrays, since shift/unshift is a source of much = confusion.

--
Yehuda Katz
Developer | = Engine Yard
(ph) 718.877.1325
=

= --Apple-Mail-12-651882621--