https://redmine.ruby-lang.org/https://redmine.ruby-lang.org/favicon.ico?17113305112012-07-01T05:26:47ZRuby Issue Tracking SystemRuby master - Feature #6636: Enumerable#sizehttps://redmine.ruby-lang.org/issues/6636?journal_id=276182012-07-01T05:26:47Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<ul><li><strong>File</strong> <a href="/attachments/2844">enumsize.pdf</a> <a class="icon-only icon-download" title="Download" href="/attachments/download/2844/enumsize.pdf">enumsize.pdf</a> added</li></ul><p>Attaching one-minute slide</p> Ruby master - Feature #6636: Enumerable#sizehttps://redmine.ruby-lang.org/issues/6636?journal_id=276742012-07-02T02:09:38Zmame (Yusuke Endoh)mame@ruby-lang.org
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Assigned</i></li></ul><p>Received. Thank you!</p>
<p>--<br>
Yusuke Endoh <a href="mailto:mame@tsg.ne.jp" class="email">mame@tsg.ne.jp</a></p> Ruby master - Feature #6636: Enumerable#sizehttps://redmine.ruby-lang.org/issues/6636?journal_id=282472012-07-21T15:43:51Znaruse (Yui NARUSE)naruse@airemix.jp
<ul></ul><p>How about adding Enumerator#receiver and define yourself with it.</p>
<p>diff --git a/enumerator.c b/enumerator.c<br>
index f01ddd5..8e3ae9a 100644<br>
--- a/enumerator.c<br>
+++ b/enumerator.c<br>
@@ -942,6 +942,32 @@ enumerator_inspect(VALUE obj)<br>
}</p>
<p>/*</p>
<ul>
<li>
<ul>
<li>call-seq:</li>
</ul>
</li>
<li>
<ul>
<li>e.receiver -> object</li>
</ul>
</li>
<li>
<ul>
<li>
</ul>
</li>
<li>
<ul>
<li>Returns the receiver of this enumerator.</li>
</ul>
</li>
<li>*/</li>
<li>
</ul>
<p>+static VALUE<br>
+enumerator_receiver(VALUE obj)<br>
+{</p>
<ul>
<li>struct enumerator *e;</li>
<li>VALUE eobj;</li>
<li>
<li>TypedData_Get_Struct(obj, struct enumerator, &enumerator_data_type, e);</li>
<li>if (!e || e->obj == Qundef) {</li>
<li>
<pre><code> return Qnil;
</code></pre>
</li>
<li>}</li>
<li>
<li>eobj = rb_attr_get(obj, id_receiver);</li>
<li>if (NIL_P(eobj)) {</li>
<li>
<pre><code> eobj = e->obj;
</code></pre>
</li>
<li>}</li>
<li>
<li>return eobj;<br>
+}</li>
<li>
</ul>
<p>+/*</p>
<ul>
<li>Yielder<br>
*/<br>
static void<br>
@@ -1748,6 +1774,7 @@ InitVM_Enumerator(void)<br>
rb_define_method(rb_cEnumerator, "feed", enumerator_feed, 1);<br>
rb_define_method(rb_cEnumerator, "rewind", enumerator_rewind, 0);<br>
rb_define_method(rb_cEnumerator, "inspect", enumerator_inspect, 0);</li>
</ul>
<ul>
<li>
<p>rb_define_method(rb_cEnumerator, "receiver", enumerator_receiver, 0);</p>
<p>/* Lazy */<br>
rb_cLazy = rb_define_class_under(rb_cEnumerator, "Lazy", rb_cEnumerator);</p>
</li>
</ul>
<p>irb(main):007:0> e="abcde".enum_for(:each_byte)<br>
=> #<Enumerator: "abcde":each_byte><br>
irb(main):009:0> def e.size; receiver.bytesize; end<br>
=> nil<br>
irb(main):010:0> e.size<br>
=> 5</p> Ruby master - Feature #6636: Enumerable#sizehttps://redmine.ruby-lang.org/issues/6636?journal_id=282632012-07-22T06:38:10Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<ul></ul><p>Hi,</p>
<p>On Sat, Jul 21, 2012 at 2:43 AM, naruse (Yui NARUSE) <a href="mailto:naruse@airemix.jp" class="email">naruse@airemix.jp</a> wrote:</p>
<blockquote>
<p>How about adding Enumerator#receiver and define yourself with it.</p>
</blockquote>
<p>I agree <code>receiver</code> could be helpful. One would also need the <code>method</code> and the <code>arguments</code>, as in my request <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: Add getters for Enumerator (Closed)" href="https://redmine.ruby-lang.org/issues/3714">#3714</a>.</p>
<p>Still, it doesn't really address the issue.</p>
<p>If someone wants to write a library to output the progression, for example, it is still not possible for a general enumerable/enumerator.</p>
<p>The proposal is so that:</p>
<ul>
<li>it is standard so anyone can depend on it and also create their own enumerables/enumerators</li>
<li>it can help in some calculations</li>
<li>it can help to have generic progression reports</li>
<li>etc.</li>
</ul>
<p>Thanks</p> Ruby master - Feature #6636: Enumerable#sizehttps://redmine.ruby-lang.org/issues/6636?journal_id=283312012-07-23T23:55:36Zmame (Yusuke Endoh)mame@ruby-lang.org
<ul><li><strong>Status</strong> changed from <i>Assigned</i> to <i>Feedback</i></li></ul><p>Marc-Andre Lafortune,</p>
<p>We discussed your slide at the developer meeting (7/21).</p>
<p>Matz was positive to the spec of return value: Integer, Float::<br>
INFINITY, and nil.<br>
However, we couldn't understand what API is proposed for creating<br>
an Enumeartor with size.</p>
<p>So, please revise and elaborate your API according to these two<br>
points:</p>
<ul>
<li>
<p>Enumerator.new(size) is not acceptable because of compatibility:</p>
<p>p Enumerator.new([1,2,3]).take(2) #=> [1, 2]</p>
</li>
<li>
<p>We cannot determine the size of enumerator when creating it:</p>
<p>a = [1]<br>
e = a.permutation<br>
a << 2<br>
p e.to_a #=> [[1, 2], [2, 1]]</p>
<p>So, the API may need to receive a code fragment that calculates<br>
size, such as a Proc.</p>
</li>
</ul>
<p>--<br>
Yusuke Endoh <a href="mailto:mame@tsg.ne.jp" class="email">mame@tsg.ne.jp</a></p> Ruby master - Feature #6636: Enumerable#sizehttps://redmine.ruby-lang.org/issues/6636?journal_id=283362012-07-24T00:13:37Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<ul><li><strong>Status</strong> changed from <i>Feedback</i> to <i>Open</i></li></ul><p>Hi,</p>
<p>mame (Yusuke Endoh) wrote:</p>
<blockquote>
<p>Matz was positive to the spec of return value: Integer, Float::<br>
INFINITY, and nil.</p>
</blockquote>
<p>:-)</p>
<blockquote>
<p>However, we couldn't understand what API is proposed for creating<br>
an Enumeartor with size.</p>
<p>So, please revise and elaborate your API according to these two<br>
points:</p>
<ul>
<li>
<p>Enumerator.new(size) is not acceptable because of compatibility:</p>
<p>p Enumerator.new([1,2,3]).take(2) #=> [1, 2]</p>
</li>
</ul>
</blockquote>
<p>Agreed.<br>
I am proposing <code>Enumerator.new(size_lambda){ block }</code>, i.e. only if a block is given, then the first argument can be a lambda/proc that can lazily compute the size.</p>
<p>The old syntax of <code>Enumerator.new</code> without a block does not change meaning.</p>
<blockquote>
<ul>
<li>
<p>We cannot determine the size of enumerator when creating it:</p>
<p>a = [1]<br>
e = a.permutation<br>
a << 2<br>
p e.to_a #=> [[1, 2], [2, 1]]</p>
<p>So, the API may need to receive a code fragment that calculates<br>
size, such as a Proc.</p>
</li>
</ul>
</blockquote>
<p>Agreed.<br>
This is why I propose that <code>to_enum</code> accepts a block that can calculate the size, and Enumerator.new with a block can accept a lambda/proc for the same.</p>
<p>Does this address the concerns?</p>
<a name="I-will-be-glad-to-propose-a-set-of-patches-so-we-can-experiment-with-this"></a>
<h2 >I will be glad to propose a set of patches so we can experiment with this.<a href="#I-will-be-glad-to-propose-a-set-of-patches-so-we-can-experiment-with-this" class="wiki-anchor">¶</a></h2>
<p>Marc-André</p> Ruby master - Feature #6636: Enumerable#sizehttps://redmine.ruby-lang.org/issues/6636?journal_id=283972012-07-24T23:29:41Zmame (Yusuke Endoh)mame@ruby-lang.org
<ul></ul><p>Hello Marc-Andre</p>
<p>2012/7/24, marcandre (Marc-Andre Lafortune) <a href="mailto:ruby-core@marc-andre.ca" class="email">ruby-core@marc-andre.ca</a>:</p>
<blockquote>
<blockquote>
<ul>
<li>
<p>Enumerator.new(size) is not acceptable because of compatibility:</p>
<p>p Enumerator.new([1,2,3]).take(2) #=> [1, 2]</p>
</li>
</ul>
</blockquote>
<p>Agreed.<br>
I am proposing <code>Enumerator.new(size_lambda){ block }</code>, i.e. only if a block<br>
is given, then the first argument can be a lambda/proc that can lazily<br>
compute the size.</p>
</blockquote>
<p>This is just my guess, but matz will not like such a method whose<br>
meaning of its argument varies depending on whether block is given<br>
or not.</p>
<blockquote>
<p>The old syntax of <code>Enumerator.new</code> without a block does not change meaning.</p>
</blockquote>
<p>Is it okay that there is no way to specify size in this case?</p>
<blockquote>
<blockquote>
<ul>
<li>
<p>We cannot determine the size of enumerator when creating it:</p>
<p>a = [1]<br>
e = a.permutation<br>
a << 2<br>
p e.to_a #=> [[1, 2], [2, 1]]</p>
<p>So, the API may need to receive a code fragment that calculates<br>
size, such as a Proc.</p>
</li>
</ul>
</blockquote>
<p>Agreed.<br>
This is why I propose that <code>to_enum</code> accepts a block that can calculate the<br>
size, and Enumerator.new with a block can accept a lambda/proc for the<br>
same.</p>
</blockquote>
<p>What argument(s) will the lambda/proc receive?</p>
<p>--<br>
Yusuke Endoh <a href="mailto:mame@tsg.ne.jp" class="email">mame@tsg.ne.jp</a></p> Ruby master - Feature #6636: Enumerable#sizehttps://redmine.ruby-lang.org/issues/6636?journal_id=284002012-07-25T00:26:43Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<ul></ul><p>Hi,</p>
<p>mame (Yusuke Endoh) wrote:</p>
<blockquote>
<blockquote>
<p>I am proposing <code>Enumerator.new(size_lambda){ block }</code>, i.e. only if a block<br>
is given, then the first argument can be a lambda/proc that can lazily<br>
compute the size.</p>
</blockquote>
<p>This is just my guess, but matz will not like such a method whose<br>
meaning of its argument varies depending on whether block is given<br>
or not.</p>
</blockquote>
<p>I understand the concern.</p>
<p>It could still be acceptable here because the other form is already documented as 'discouraged'. Maybe we should deprecate it?</p>
<p>Other possibility would be to add a different creator, e.g. <code>Enumerator.sized(size_lambda){|yielder| ... }</code>.</p>
<blockquote>
<blockquote>
<p>The old syntax of <code>Enumerator.new</code> without a block does not change meaning.</p>
</blockquote>
<p>Is it okay that there is no way to specify size in this case?</p>
</blockquote>
<p>This old syntax is already discouraged and <code>to_enum</code>/<code>enum_for</code> should be used instead.</p>
<blockquote>
<blockquote>
<p>This is why I propose that <code>to_enum</code> accepts a block that can calculate the<br>
size, and Enumerator.new with a block can accept a lambda/proc for the<br>
same.</p>
</blockquote>
<p>What argument(s) will the lambda/proc receive?</p>
</blockquote>
<p>We could consider passing the receiver and/or any arguments passed to <code>to_enum</code>, but I would propose to keep it simple and pass no arguments.</p>
<a name="This-is-because-enumerators-are-immutable-and-all-information-held-in-Enumerators-should-be-accessible-from-the-blocklambda-anyways"></a>
<h2 >This is because enumerators are immutable and all information held in Enumerators should be accessible from the block/lambda anyways.<a href="#This-is-because-enumerators-are-immutable-and-all-information-held-in-Enumerators-should-be-accessible-from-the-blocklambda-anyways" class="wiki-anchor">¶</a></h2>
<p>Marc-André</p> Ruby master - Feature #6636: Enumerable#sizehttps://redmine.ruby-lang.org/issues/6636?journal_id=316912012-10-27T07:11:54Zko1 (Koichi Sasada)
<ul><li><strong>Assignee</strong> changed from <i>matz (Yukihiro Matsumoto)</i> to <i>mame (Yusuke Endoh)</i></li></ul> Ruby master - Feature #6636: Enumerable#sizehttps://redmine.ruby-lang.org/issues/6636?journal_id=317632012-10-27T11:51:11Zmame (Yusuke Endoh)mame@ruby-lang.org
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Assigned</i></li><li><strong>Assignee</strong> changed from <i>mame (Yusuke Endoh)</i> to <i>matz (Yukihiro Matsumoto)</i></li><li><strong>Target version</strong> changed from <i>2.0.0</i> to <i>2.6</i></li></ul> Ruby master - Feature #6636: Enumerable#sizehttps://redmine.ruby-lang.org/issues/6636?journal_id=319082012-10-29T14:48:43Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<ul></ul><p>Hi.</p>
<p>My understanding was this new feature would make it into Ruby 2.0. Did I misunderstand?</p>
<p>The implementation can be seen here: <a href="https://github.com/marcandre/ruby/compare/marcandre:trunk...marcandre:enum_size" class="external">https://github.com/marcandre/ruby/compare/marcandre:trunk...marcandre:enum_size</a></p>
<p>Although the combined diff (<a href="https://github.com/marcandre/ruby/compare/marcandre:trunk...marcandre:enum_size.diff" class="external">https://github.com/marcandre/ruby/compare/marcandre:trunk...marcandre:enum_size.diff</a> ) is pretty big, there are really just two interesting commits. The second adds #size and extends constructor. The third extends <code>to_enum</code> to accept a block. See <a href="https://github.com/marcandre/ruby/commit/add_enumerator_size" class="external">https://github.com/marcandre/ruby/commit/add_enumerator_size</a> and <a href="https://github.com/marcandre/ruby/commit/sized_to_enum" class="external">https://github.com/marcandre/ruby/commit/sized_to_enum</a></p>
<p>The first commit only warns on using the deprecated form with no block <code>Enumerator.new(obj, *args)</code>, but compatibility is maintained.</p>
<p>The remaining commits add support for the different ways of creating enumerators that can evaluate lazily their size. A few remain to be implemented, in particular the lazy ones.</p> Ruby master - Feature #6636: Enumerable#sizehttps://redmine.ruby-lang.org/issues/6636?journal_id=320522012-10-31T13:20:10Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<ul></ul><p>I added support for lazy enumerators.</p>
<p>Yusuke, Matz, did I address your questions/concerns?</p> Ruby master - Feature #6636: Enumerable#sizehttps://redmine.ruby-lang.org/issues/6636?journal_id=323642012-11-05T13:30:44Zmatz (Yukihiro Matsumoto)matz@ruby.or.jp
<ul></ul><p>After skimming your modifies, I feel they are decent.<br>
Sorry for being late to check.</p>
<p>Matz.</p> Ruby master - Feature #6636: Enumerable#sizehttps://redmine.ruby-lang.org/issues/6636?journal_id=324492012-11-06T02:16:25Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<ul><li><strong>Assignee</strong> changed from <i>matz (Yukihiro Matsumoto)</i> to <i>marcandre (Marc-Andre Lafortune)</i></li><li><strong>Target version</strong> changed from <i>2.6</i> to <i>2.0.0</i></li></ul><p>Hi,</p>
<p>matz (Yukihiro Matsumoto) wrote:</p>
<blockquote>
<p>After skimming your modifies, I feel they are decent.</p>
</blockquote>
<p>Thanks for looking at them. Very happy to read this :-)</p>
<a name="Ill-then-commit-these-and-finish-implementing-size-for-ranges-of-strings"></a>
<h2 >I'll then commit these and finish implementing size for ranges of strings.<a href="#Ill-then-commit-these-and-finish-implementing-size-for-ranges-of-strings" class="wiki-anchor">¶</a></h2>
<p>Marc-André</p> Ruby master - Feature #6636: Enumerable#sizehttps://redmine.ruby-lang.org/issues/6636?journal_id=325072012-11-07T02:09:47Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<ul><li><strong>Status</strong> changed from <i>Assigned</i> to <i>Closed</i></li><li><strong>% Done</strong> changed from <i>0</i> to <i>100</i></li></ul><p>This issue was solved with changeset r37495.<br>
Marc-Andre, thank you for reporting this issue.<br>
Your contribution to Ruby is greatly appreciated.<br>
May Ruby be with you.</p>
<hr>
<ul>
<li>enumerator.c (enumerator_initialize): Warn when using deprecated form<br>
[Feature <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: Enumerable#size (Closed)" href="https://redmine.ruby-lang.org/issues/6636">#6636</a>]</li>
</ul>