<ppdoc>
<copyright>
    Copyright (c) 2001 by Addison Wesley Longman.  This
    material may be distributed only subject to the terms and
    conditions set forth in the Open Publication License, v1.0 or
    later (the latest version is presently available at
    http://www.opencontent.org/openpub/).
</copyright>
<class name="Enumerable" type="module" ref="xref-000001">
  <relieson>each, &lt;=&gt;</relieson>
<p/>
  The <modulename>Enumerable</modulename> mixin provides collection classes with several
  traversal and searching methods, and with the ability to sort.    
  The class must provide a method <meth>each</meth>, which yields
  successive members of the collection. If <mim><file>enumerable</file><front>Enumerable</front><back>max</back><mref>max</mref></mim>,
  <meth>#min</meth>, or <meth>#sort</meth> is used, the objects in the
  collection must also implement a meaningful <tt>&lt;=&gt;</tt> operator, as
  these methods rely on an ordering between members of the collection.
<p/>
  <methods type="instance">
        <method name="collect" ref="collect">
      <callseq>
        <obj>enumObj</obj>.collect <block>{| obj | <blockbody>block</blockbody> }</block>
<p/>
        <returns><obj>anArray</obj></returns>
      </callseq>
      <desc>
<p/>
      Returns a new array with the results of running <em>block</em> once for every
      element in <obj>enumObj</obj>.
<p/>
<codefragment>
<fullcode><![CDATA[         (1..4).collect {|i| i*i }
         (1..4).collect { "cat"  }
]]></fullcode><rubycode>
<tr>
  <td><tt>(1..4).collect<nbsp/>{|i|<nbsp/>i*i<nbsp/>}</tt></td>
  <td>&#187;</td>
  <td><tt>[1,<nbsp/>4,<nbsp/>9,<nbsp/>16]</tt></td>
</tr>
<tr>
  <td><tt>(1..4).collect<nbsp/>{<nbsp/>"cat"<nbsp/><nbsp/>}</tt></td>
  <td>&#187;</td>
  <td><tt>["cat",<nbsp/>"cat",<nbsp/>"cat",<nbsp/>"cat"]</tt></td>
</tr>
</rubycode>
<p/>
</codefragment>
<p/>
      </desc>
    </method>
<p/>
        <method name="detect" ref="detect">
      <callseq>
        <obj>enumObj</obj>.detect <block>{| obj | <blockbody>block</blockbody> }</block>
<p/>
        <returns><obj>anObject</obj> or <tt>nil</tt></returns>
      </callseq>
      <desc>
<p/>
      Passes each entry in <obj>enumObj</obj> to <em>block</em>. Returns the first for 
      which <em>block</em> is not <const>false</const>. Returns <const>nil</const> 
      if no object matches.
<p/>
<codefragment>
<fullcode><![CDATA[         (1..10).detect  {|i| i % 5 == 0 and i % 7 == 0 }
         (1..100).detect {|i| i % 5 == 0 and i % 7 == 0 }
]]></fullcode><rubycode>
<tr>
  <td><tt>(1..10).detect<nbsp/><nbsp/>{|i|<nbsp/>i<nbsp/>%<nbsp/>5<nbsp/>==<nbsp/>0<nbsp/>and<nbsp/>i<nbsp/>%<nbsp/>7<nbsp/>==<nbsp/>0<nbsp/>}</tt></td>
  <td>&#187;</td>
  <td><tt>nil</tt></td>
</tr>
<tr>
  <td><tt>(1..100).detect<nbsp/>{|i|<nbsp/>i<nbsp/>%<nbsp/>5<nbsp/>==<nbsp/>0<nbsp/>and<nbsp/>i<nbsp/>%<nbsp/>7<nbsp/>==<nbsp/>0<nbsp/>}</tt></td>
  <td>&#187;</td>
  <td><tt>35</tt></td>
</tr>
</rubycode>
<p/>
</codefragment>
<p/>
      </desc>
    </method>
<p/>
        <method name="each_with_index" ref="each_with_index">
      <callseq>
        <obj>enumObj</obj>.each_with_index
        <block>{| obj, i | <blockbody>block</blockbody> }</block>
<p/>
        <returns><tt>nil</tt></returns>
      </callseq>
      <desc>
<p/>
      Calls <em>block</em> with two arguments, the item and its index,
      for each item in <obj>enumObj</obj>.
<p/>
<codefragment>
<fullcode><![CDATA[         hash = Hash.new
         %w(cat dog wombat).each_with_index {|item, index|
           hash[item] = index
         }
         hash
]]></fullcode><rubycode>
<tr>
<td colspan="3"><tt>hash<nbsp/>=<nbsp/>Hash.new</tt></td>
</tr>
<tr>
<td colspan="3"><tt>%w(cat<nbsp/>dog<nbsp/>wombat).each_with_index<nbsp/>{|item,<nbsp/>index|</tt></td>
</tr>
<tr>
<td colspan="3"><tt><nbsp/><nbsp/>hash[item]<nbsp/>=<nbsp/>index</tt></td>
</tr>
<tr>
<td colspan="3"><tt>}</tt></td>
</tr>
<tr>
  <td><tt>hash</tt></td>
  <td>&#187;</td>
  <td><tt>{"dog"=&gt;1,<nbsp/>"cat"=&gt;0,<nbsp/>"wombat"=&gt;2}</tt></td>
</tr>
</rubycode>
<p/>
</codefragment>
<p/>
      </desc>
    </method>
<p/>
        <method name="entries" ref="entries">
      <callseq>
        <obj>enumObj</obj>.entries <returns><obj>anArray</obj></returns>
      </callseq>
      <desc>
<p/>
      Synonym for <mim><file>enumerable</file><front>Enumerable</front><back>to_a</back><mref>to_a</mref></mim>.
<p/>
      </desc>
    </method>
<p/>
        <method name="find" ref="find">
      <callseq>
        <obj>enumObj</obj>.find <block>{| obj | <blockbody>block</blockbody> }</block>
<p/>
        <returns><obj>anObject</obj> or <tt>nil</tt></returns>
      </callseq>
      <desc>
<p/>
      Synonym for <mim><file>enumerable</file><front>Enumerable</front><back>detect</back><mref>detect</mref></mim>.
<p/>
      </desc>
    </method>
<p/>
        <method name="find_all" ref="find_all">
      <callseq>
        <obj>enumObj</obj>.find_all <block>{| obj | <blockbody>block</blockbody> }</block>
<p/>
        <returns><obj>anArray</obj></returns>
      </callseq>
      <desc>
<p/>
      Returns an array containing all elements of <obj>enumObj</obj> for which
      <em>block</em> is not <const>false</const> (see also <mim><file>enumerable</file><front>Enumerable</front><back>reject</back><mref>reject</mref></mim>).
<p/>
<codefragment>
<fullcode><![CDATA[         (1..10).find_all {|i|  i % 3 == 0 }
]]></fullcode><rubycode>
<tr>
  <td><tt>(1..10).find_all<nbsp/>{|i|<nbsp/><nbsp/>i<nbsp/>%<nbsp/>3<nbsp/>==<nbsp/>0<nbsp/>}</tt></td>
  <td>&#187;</td>
  <td><tt>[3,<nbsp/>6,<nbsp/>9]</tt></td>
</tr>
</rubycode>
<p/>
</codefragment>
<p/>
      </desc>
    </method>
<p/>
        <method name="grep" ref="grep">
      <callseq>
                    <obj>enumObj</obj>.grep( <obj>pattern</obj> ) <returns><obj>anArray</obj></returns><br/><obj>enumObj</obj>.grep( <obj>pattern</obj> ) <block>{| obj | <blockbody>block</blockbody> }</block>
 <returns><obj>anArray</obj></returns>
      </callseq>
      <desc>
<p/>
      Returns an array of every element in <obj>enumObj</obj> for which
      <tt>Pattern === element</tt>. If the optional <em>block</em> is
      supplied, each matching element is passed to it, and the block's
      result is stored in the output array.
<p/>
<codefragment>
<fullcode><![CDATA[        (1..100).grep 38..44
        c = IO.constants
        c.grep(/SEEK/)
        res = c.grep(/SEEK/) {|v| IO.const_get(v) } 
        res
]]></fullcode><rubycode>
<tr>
  <td><tt>(1..100).grep<nbsp/>38..44</tt></td>
  <td>&#187;</td>
  <td><tt>[38,<nbsp/>39,<nbsp/>40,<nbsp/>41,<nbsp/>42,<nbsp/>43,<nbsp/>44]</tt></td>
</tr>
<tr>
<td colspan="3"><tt>c<nbsp/>=<nbsp/>IO.constants</tt></td>
</tr>
<tr>
  <td><tt>c.grep(/SEEK/)</tt></td>
  <td>&#187;</td>
  <td><tt>["SEEK_END",<nbsp/>"SEEK_CUR",<nbsp/>"SEEK_SET"]</tt></td>
</tr>
<tr>
<td colspan="3"><tt>res<nbsp/>=<nbsp/>c.grep(/SEEK/)<nbsp/>{|v|<nbsp/>IO.const_get(v)<nbsp/>}</tt></td>
</tr>
<tr>
  <td><tt>res</tt></td>
  <td>&#187;</td>
  <td><tt>[2,<nbsp/>1,<nbsp/>0]</tt></td>
</tr>
</rubycode>
<p/>
</codefragment>
<p/>
      </desc>
    </method>
<p/>
        <method name="include?" ref="include_qm">
      <callseq>
        <obj>enumObj</obj>.include?( <obj>anObject</obj> )
      <returns><const>true</const> or <const>false</const></returns>
      </callseq>
      <desc>
<p/>
      Returns <const>true</const> if any member of <obj>enumObj</obj> equals
      <obj>anObject</obj>. Equality is tested using <meth>==</meth>.
<p/>
<codefragment>
<fullcode><![CDATA[        IO.constants.include? "SEEK_SET"
        IO.constants.include? "SEEK_NO_FURTHER"
]]></fullcode><rubycode>
<tr>
  <td><tt>IO.constants.include?<nbsp/>"SEEK_SET"</tt></td>
  <td>&#187;</td>
  <td><tt>true</tt></td>
</tr>
<tr>
  <td><tt>IO.constants.include?<nbsp/>"SEEK_NO_FURTHER"</tt></td>
  <td>&#187;</td>
  <td><tt>false</tt></td>
</tr>
</rubycode>
<p/>
</codefragment>
<p/>
      </desc>
    </method>
<p/>
        <method name="map" ref="map">
      <callseq>
        <obj>enumObj</obj>.map <block>{| obj | <blockbody>block</blockbody> }</block>
<p/>
        <returns><obj>anArray</obj></returns>
      </callseq>
      <desc>
<p/>
      Synonym for <mim><file>enumerable</file><front>Enumerable</front><back>collect</back><mref>collect</mref></mim>.
<p/>
      </desc>
    </method>
<p/>
        <method name="max" ref="max">
      <callseq>
                  <obj>enumObj</obj>.max <returns><obj>anObject</obj></returns><br/><obj>enumObj</obj>.max <block>{| a,b | <blockbody>block</blockbody> }</block>
 <returns><obj>anObject</obj></returns>
      </callseq>
      <desc>
<p/>
      Returns the object in <obj>enumObj</obj> with the maximum value. The first
      form assumes all objects implement <modulename>Comparable</modulename>; the second
      uses the block to return <em>a<nbsp/>&lt;=&gt;<nbsp/>b</em>.
<p/>
<codefragment>
<fullcode><![CDATA[         a = %w(albatross dog horse)
         a.max
         a.max {|a,b| a.length <=> b.length }
]]></fullcode><rubycode>
<tr>
<td colspan="3"><tt>a<nbsp/>=<nbsp/>%w(albatross<nbsp/>dog<nbsp/>horse)</tt></td>
</tr>
<tr>
  <td><tt>a.max</tt></td>
  <td>&#187;</td>
  <td><tt>"horse"</tt></td>
</tr>
<tr>
  <td><tt>a.max<nbsp/>{|a,b|<nbsp/>a.length<nbsp/>&lt;=&gt;<nbsp/>b.length<nbsp/>}</tt></td>
  <td>&#187;</td>
  <td><tt>"albatross"</tt></td>
</tr>
</rubycode>
<p/>
</codefragment>
<p/>
      </desc>
    </method>
<p/>
        <method name="member?" ref="member_qm">
      <callseq>
        <obj>enumObj</obj>.member?( <obj>anObject</obj> ) <returns><const>true</const> or <const>false</const></returns>
      </callseq>
      <desc>
<p/>
      Synonym for <mim><file>enumerable</file><front>Enumerable</front><back>include?</back><mref>include_qm</mref></mim>.
<p/>
      </desc>
    </method>
<p/>
        <method name="min" ref="min">
      <callseq>
                  <obj>enumObj</obj>.min <returns><obj>anObject</obj></returns><br/><obj>enumObj</obj>.min <block>{| a,b | <blockbody>block</blockbody> }</block>
 <returns><obj>anObject</obj></returns>
      </callseq>
      <desc>
<p/>
      Returns the object in <obj>enumObj</obj> with the minimum value. The first
      form assumes all objects implement <modulename>Comparable</modulename>; the second
      uses the block to return <em>a<nbsp/>&lt;=&gt;<nbsp/>b</em>.
<p/>
<codefragment>
<fullcode><![CDATA[         a = %w(albatross dog horse)
         a.min
         a.min {|a,b| a.length <=> b.length }
]]></fullcode><rubycode>
<tr>
<td colspan="3"><tt>a<nbsp/>=<nbsp/>%w(albatross<nbsp/>dog<nbsp/>horse)</tt></td>
</tr>
<tr>
  <td><tt>a.min</tt></td>
  <td>&#187;</td>
  <td><tt>"albatross"</tt></td>
</tr>
<tr>
  <td><tt>a.min<nbsp/>{|a,b|<nbsp/>a.length<nbsp/>&lt;=&gt;<nbsp/>b.length<nbsp/>}</tt></td>
  <td>&#187;</td>
  <td><tt>"dog"</tt></td>
</tr>
</rubycode>
<p/>
</codefragment>
<p/>
      </desc>
    </method>
<p/>
        <method name="reject" ref="reject">
      <callseq>
        <obj>enumObj</obj>.reject <block>{| obj | <blockbody>block</blockbody> }</block>
<p/>
        <returns><obj>anArray</obj></returns>
      </callseq>
      <desc>
<p/>
      Returns an array for all elements of <obj>enumObj</obj> for which
      <em>block</em> is <const>false</const> (see also <mim><file>enumerable</file><front>Enumerable</front><back>find_all</back><mref>find_all</mref></mim>).
<p/>
<codefragment>
<fullcode><![CDATA[         (1..10).reject {|i|  i % 3 == 0 }
]]></fullcode><rubycode>
<tr>
  <td><tt>(1..10).reject<nbsp/>{|i|<nbsp/><nbsp/>i<nbsp/>%<nbsp/>3<nbsp/>==<nbsp/>0<nbsp/>}</tt></td>
  <td>&#187;</td>
  <td><tt>[1,<nbsp/>2,<nbsp/>4,<nbsp/>5,<nbsp/>7,<nbsp/>8,<nbsp/>10]</tt></td>
</tr>
</rubycode>
<p/>
</codefragment>
<p/>
      </desc>
    </method>
<p/>
        <method name="select" ref="select">
      <callseq>
        <obj>enumObj</obj>.select <block>{| obj | <blockbody>block</blockbody> }</block>
<p/>
        <returns><obj>anArray</obj></returns>
      </callseq>
      <desc>
<p/>
      Synonym for <mim><file>enumerable</file><front>Enumerable</front><back>find_all</back><mref>find_all</mref></mim>.
<p/>
      </desc>
    </method>
<p/>
        <method name="sort" ref="sort">
      <callseq>
                  <obj>enumObj</obj>.sort <returns><obj>anArray</obj></returns><br/><obj>enumObj</obj>.sort <block>{| a, b | <blockbody>block</blockbody> }</block>
 <returns><obj>anArray</obj></returns>
      </callseq>
      <desc>
<p/>
      Returns an array containing the items in <obj>enumObj</obj> sorted, either
      according to their own <meth>&lt;=&gt;</meth> method, or by using the
      results of the supplied block. The block should return -1, 0, or 
      +1 depending on the comparison between <obj>a</obj> and <obj>b</obj>.
<p/>
<codefragment>
<fullcode><![CDATA[        %w(rhea kea flea).sort
        (1..10).sort {|a,b| b <=> a}
]]></fullcode><rubycode>
<tr>
  <td><tt>%w(rhea<nbsp/>kea<nbsp/>flea).sort</tt></td>
  <td>&#187;</td>
  <td><tt>["flea",<nbsp/>"kea",<nbsp/>"rhea"]</tt></td>
</tr>
<tr>
  <td><tt>(1..10).sort<nbsp/>{|a,b|<nbsp/>b<nbsp/>&lt;=&gt;<nbsp/>a}</tt></td>
  <td>&#187;</td>
  <td><tt>[10,<nbsp/>9,<nbsp/>8,<nbsp/>7,<nbsp/>6,<nbsp/>5,<nbsp/>4,<nbsp/>3,<nbsp/>2,<nbsp/>1]</tt></td>
</tr>
</rubycode>
<p/>
</codefragment>
<p/>
      The following code sorts some files on modification time.
<p/>
<codefragment>
<fullcode><![CDATA[!-        Dir.mkdir("sorteg")
!-        Dir.chdir("sorteg")
!-        system("touch -t 08071200 mon")
!-        system("touch -t 08081200 tues")
!-        system("touch -t 08091200 wed")
!-        system("touch -t 08101200 thurs")
        files = Dir["*"]
        sorted = files.sort {|a,b| File.new(a).mtime <=> File.new(b).mtime}
        sorted
!-        system("rm mon tues wed thurs")
!-        Dir.chdir("..")
!-        Dir.rmdir("sorteg")
]]></fullcode><rubycode>
<tr>
<td colspan="3"><tt>files<nbsp/>=<nbsp/>Dir["*"]</tt></td>
</tr>
<tr>
<td colspan="3"><tt>sorted<nbsp/>=<nbsp/>files.sort<nbsp/>{|a,b|<nbsp/>File.new(a).mtime<nbsp/>&lt;=&gt;<nbsp/>File.new(b).mtime}</tt></td>
</tr>
<tr>
  <td><tt>sorted</tt></td>
  <td>&#187;</td>
  <td><tt>["mon",<nbsp/>"tues",<nbsp/>"wed",<nbsp/>"thurs"]</tt></td>
</tr>
</rubycode>
<p/>
</codefragment>
<p/>
      This sort is inefficient: it generates two new <classname>File</classname> objects
      during every comparison. A slightly better technique is to use
      the <cim><file>kernel</file><front>Kernel</front><back>test</back><mref>test</mref></cim> method to generate the modification times
      directly.
<p/>
<codefragment>
<fullcode><![CDATA[!-        Dir.mkdir("sorteg")
!-        Dir.chdir("sorteg")
!-        system("touch -t 08071200 mon")
!-        system("touch -t 08081200 tues")
!-        system("touch -t 08091200 wed")
!-        system("touch -t 08101200 thurs")
        files = Dir["*"]
        sorted = files.sort { |a,b|
          test(?M, a) <=> test(?M, b)
        }
        sorted
!-        system("rm mon tues wed thurs")
!-        Dir.chdir("..")
!-        Dir.rmdir("sorteg")
]]></fullcode><rubycode>
<tr>
<td colspan="3"><tt>files<nbsp/>=<nbsp/>Dir["*"]</tt></td>
</tr>
<tr>
<td colspan="3"><tt>sorted<nbsp/>=<nbsp/>files.sort<nbsp/>{<nbsp/>|a,b|</tt></td>
</tr>
<tr>
<td colspan="3"><tt><nbsp/><nbsp/>test(?M,<nbsp/>a)<nbsp/>&lt;=&gt;<nbsp/>test(?M,<nbsp/>b)</tt></td>
</tr>
<tr>
<td colspan="3"><tt>}</tt></td>
</tr>
<tr>
  <td><tt>sorted</tt></td>
  <td>&#187;</td>
  <td><tt>["mon",<nbsp/>"tues",<nbsp/>"wed",<nbsp/>"thurs"]</tt></td>
</tr>
</rubycode>
<p/>
</codefragment>
<p/>
      This still generates many unnecessary <classname>Time</classname> objects.
      A more efficient technique is to cache
      the sort keys (modification times in this case) before the sort.
      Perl users often call this approach a Schwartzian Transform,                  
      after Randal Schwartz. We construct a temporary array,
      where each element is an array containing our sort key along
      with the filename. We sort this array, and then extract the
      filename from the result.
<p/>
<codefragment>
<fullcode><![CDATA[!-        Dir.mkdir("sorteg")
!-        Dir.chdir("sorteg")
!-        system("touch -t 08071200 mon")
!-        system("touch -t 08081200 tues")
!-        system("touch -t 08091200 wed")
!-        system("touch -t 08101200 thurs")
        sorted = Dir["*"].collect { |f|
           [test(?M, f), f]
        }.sort.collect { |f| f[1] }
        sorted
!-        system("rm mon tues wed thurs")
!-        Dir.chdir("..")
!-        Dir.rmdir("sorteg")
]]></fullcode><rubycode>
<tr>
<td colspan="3"><tt>sorted<nbsp/>=<nbsp/>Dir["*"].collect<nbsp/>{<nbsp/>|f|</tt></td>
</tr>
<tr>
<td colspan="3"><tt><nbsp/><nbsp/><nbsp/>[test(?M,<nbsp/>f),<nbsp/>f]</tt></td>
</tr>
<tr>
<td colspan="3"><tt>}.sort.collect<nbsp/>{<nbsp/>|f|<nbsp/>f[1]<nbsp/>}</tt></td>
</tr>
<tr>
  <td><tt>sorted</tt></td>
  <td>&#187;</td>
  <td><tt>["mon",<nbsp/>"tues",<nbsp/>"wed",<nbsp/>"thurs"]</tt></td>
</tr>
</rubycode>
<p/>
</codefragment>
<p/>
      </desc>
    </method>
<p/>
        <method name="to_a" ref="to_a">
      <callseq>
        <obj>enumObj</obj>.to_a <returns><obj>anArray</obj></returns>
      </callseq>
      <desc>
<p/>
      Returns an array containing the items in <obj>enumObj</obj>.
<p/>
<codefragment>
<fullcode><![CDATA[        (1..7).to_a
        { 'a'=>1, 'b'=>2, 'c'=>3 }.to_a
]]></fullcode><rubycode>
<tr>
  <td><tt>(1..7).to_a</tt></td>
  <td>&#187;</td>
  <td><tt>[1,<nbsp/>2,<nbsp/>3,<nbsp/>4,<nbsp/>5,<nbsp/>6,<nbsp/>7]</tt></td>
</tr>
<tr>
  <td><tt>{<nbsp/>'a'=&gt;1,<nbsp/>'b'=&gt;2,<nbsp/>'c'=&gt;3<nbsp/>}.to_a</tt></td>
  <td>&#187;</td>
  <td><tt>[["a",<nbsp/>1],<nbsp/>["b",<nbsp/>2],<nbsp/>["c",<nbsp/>3]]</tt></td>
</tr>
</rubycode>
<p/>
</codefragment>
<p/>
      </desc>
    </method>
<p/>
  </methods>
<p/>
</class>
</ppdoc>
