ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
* [ruby-core:48639] [ruby-trunk - Bug #7248][Open] Shouldn't Enumerator::Lazy.new be private?
@ 2012-10-31  4:23 marcandre (Marc-Andre Lafortune)
  2012-11-05 14:01 ` [ruby-core:48925] [ruby-trunk - Bug #7248][Assigned] " mame (Yusuke Endoh)
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: marcandre (Marc-Andre Lafortune) @ 2012-10-31  4:23 UTC (permalink / raw
  To: ruby-core


Issue #7248 has been reported by marcandre (Marc-Andre Lafortune).

----------------------------------------
Bug #7248: Shouldn't Enumerator::Lazy.new be private?
https://bugs.ruby-lang.org/issues/7248

Author: marcandre (Marc-Andre Lafortune)
Status: Open
Priority: Normal
Assignee: 
Category: core
Target version: 2.0.0
ruby -v: ruby 2.0.0dev (2012-10-29 trunk 37380) [x86_64-darwin10.8.0]


Is there a reason why Enumerator::Lazy.new is not private?

Lazy enumerators should be created with `Enumerable#lazy`. Moreover, there is no doc, and it can give unexpected results too.


-- 
http://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [ruby-core:48925] [ruby-trunk - Bug #7248][Assigned] Shouldn't Enumerator::Lazy.new be private?
  2012-10-31  4:23 [ruby-core:48639] [ruby-trunk - Bug #7248][Open] Shouldn't Enumerator::Lazy.new be private? marcandre (Marc-Andre Lafortune)
@ 2012-11-05 14:01 ` mame (Yusuke Endoh)
  2012-12-07 16:17 ` [ruby-core:50665] [ruby-trunk - Bug #7248] " yhara (Yutaka HARA)
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: mame (Yusuke Endoh) @ 2012-11-05 14:01 UTC (permalink / raw
  To: ruby-core


Issue #7248 has been updated by mame (Yusuke Endoh).

Status changed from Open to Assigned
Assignee set to yhara (Yutaka HARA)

Yhara-san, I'd like your opinion about this ticket.

-- 
Yusuke Endoh <mame@tsg.ne.jp>
----------------------------------------
Bug #7248: Shouldn't Enumerator::Lazy.new be private?
https://bugs.ruby-lang.org/issues/7248#change-32427

Author: marcandre (Marc-Andre Lafortune)
Status: Assigned
Priority: Normal
Assignee: yhara (Yutaka HARA)
Category: core
Target version: 2.0.0
ruby -v: ruby 2.0.0dev (2012-10-29 trunk 37380) [x86_64-darwin10.8.0]


Is there a reason why Enumerator::Lazy.new is not private?

Lazy enumerators should be created with `Enumerable#lazy`. Moreover, there is no doc, and it can give unexpected results too.


-- 
http://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [ruby-core:50665] [ruby-trunk - Bug #7248] Shouldn't Enumerator::Lazy.new be private?
  2012-10-31  4:23 [ruby-core:48639] [ruby-trunk - Bug #7248][Open] Shouldn't Enumerator::Lazy.new be private? marcandre (Marc-Andre Lafortune)
  2012-11-05 14:01 ` [ruby-core:48925] [ruby-trunk - Bug #7248][Assigned] " mame (Yusuke Endoh)
@ 2012-12-07 16:17 ` yhara (Yutaka HARA)
  2012-12-09  1:44 ` [ruby-core:50702] " marcandre (Marc-Andre Lafortune)
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: yhara (Yutaka HARA) @ 2012-12-07 16:17 UTC (permalink / raw
  To: ruby-core


Issue #7248 has been updated by yhara (Yutaka HARA).


Hi,

Enumerator::Lazy.new will be needed
(1) when you want to overwrite behavior of a lazy method. eg:

---
class Enumerator::Lazy
  def zip(*args, &block)
    enums = args.map(&:lazy)
    Lazy.new(self){|yielder, val|
      ary = [val] + enums.map{|e| e.next}
      if block
        yielder << block.call(ary)  # make lazy.zip{} behave lazy (currently it doesn't because enum.zip{} is eager)
      else
        yielder << ary
      end
    }
  end
end

fizz = [nil, nil, nil, nil, "Fizz"].cycle
buzz = [nil, nil, "Buzz"].cycle
p fizz.lazy.zip(buzz){|f, b| "#{f}#{b}"}.first(20)
---

(2) when you want to add a new Enumerable method and its lazy version. eg:

---
module Enumerable
  def filter_map(&block)
    self.map(&block).compact
  end
end

class Enumerator::Lazy
  def filter_map(*args, &block)
    Lazy.new(self){|yielder, val|
      result = block.call(val)
      yielder << result if result
    }
  end
end

p [11,12,13].filter_map{|i| i*i if i.even?}  #=> [144]
p (1..Float::INFINITY).lazy.filter_map{|i| i*i if i.even?}.first(20)
---
----------------------------------------
Bug #7248: Shouldn't Enumerator::Lazy.new be private?
https://bugs.ruby-lang.org/issues/7248#change-34511

Author: marcandre (Marc-Andre Lafortune)
Status: Assigned
Priority: Normal
Assignee: yhara (Yutaka HARA)
Category: core
Target version: 2.0.0
ruby -v: ruby 2.0.0dev (2012-10-29 trunk 37380) [x86_64-darwin10.8.0]


Is there a reason why Enumerator::Lazy.new is not private?

Lazy enumerators should be created with `Enumerable#lazy`. Moreover, there is no doc, and it can give unexpected results too.


-- 
http://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [ruby-core:50702] [ruby-trunk - Bug #7248] Shouldn't Enumerator::Lazy.new be private?
  2012-10-31  4:23 [ruby-core:48639] [ruby-trunk - Bug #7248][Open] Shouldn't Enumerator::Lazy.new be private? marcandre (Marc-Andre Lafortune)
  2012-11-05 14:01 ` [ruby-core:48925] [ruby-trunk - Bug #7248][Assigned] " mame (Yusuke Endoh)
  2012-12-07 16:17 ` [ruby-core:50665] [ruby-trunk - Bug #7248] " yhara (Yutaka HARA)
@ 2012-12-09  1:44 ` marcandre (Marc-Andre Lafortune)
  2013-01-11 19:58 ` [ruby-core:51387] " yhara (Yutaka HARA)
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: marcandre (Marc-Andre Lafortune) @ 2012-12-09  1:44 UTC (permalink / raw
  To: ruby-core


Issue #7248 has been updated by marcandre (Marc-Andre Lafortune).


Oh, interesting.

I'll do my best to document it, then.

This leads to more questions, though:

1) Is there a use case for the form without a block?

It's used internally (before calling lazy_set_method), but other than that I can't see a good use.

2) Is there a use case for specifying a symbol and arguments?

Again, internally we call lazy_set_method, to the symbol and arguments are only used by inspect, right?

3) Is there a good way to improve the `inspect` of such a lazy enum?

    p [11,12,13].filter_map{|i| i*i if i.even?} # => #<Enumerator::Lazy: #<Enumerator::Lazy: [1, 2, 3]>:each>

Notice the `each` and no appearance of `filter_map`

Doing `Lazy.new(self, :filter_map)` does not work and seems redundant.

Thanks

BTW, ultimately, I'm trying to see if Lazy.new can be adapted to accept a `size` lambda argument...

----------------------------------------
Bug #7248: Shouldn't Enumerator::Lazy.new be private?
https://bugs.ruby-lang.org/issues/7248#change-34548

Author: marcandre (Marc-Andre Lafortune)
Status: Assigned
Priority: Normal
Assignee: yhara (Yutaka HARA)
Category: core
Target version: 2.0.0
ruby -v: ruby 2.0.0dev (2012-10-29 trunk 37380) [x86_64-darwin10.8.0]


Is there a reason why Enumerator::Lazy.new is not private?

Lazy enumerators should be created with `Enumerable#lazy`. Moreover, there is no doc, and it can give unexpected results too.


-- 
http://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [ruby-core:51387] [ruby-trunk - Bug #7248] Shouldn't Enumerator::Lazy.new be private?
  2012-10-31  4:23 [ruby-core:48639] [ruby-trunk - Bug #7248][Open] Shouldn't Enumerator::Lazy.new be private? marcandre (Marc-Andre Lafortune)
                   ` (2 preceding siblings ...)
  2012-12-09  1:44 ` [ruby-core:50702] " marcandre (Marc-Andre Lafortune)
@ 2013-01-11 19:58 ` yhara (Yutaka HARA)
  2013-01-14  4:59 ` [ruby-core:51418] " marcandre (Marc-Andre Lafortune)
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: yhara (Yutaka HARA) @ 2013-01-11 19:58 UTC (permalink / raw
  To: ruby-core


Issue #7248 has been updated by yhara (Yutaka HARA).

Assignee changed from yhara (Yutaka HARA) to marcandre (Marc-Andre Lafortune)

marcandre (Marc-Andre Lafortune) wrote:
> Oh, interesting.
> 
> I'll do my best to document it, then.
> 
Thanks!

> This leads to more questions, though:
> 
> 1) Is there a use case for the form without a block?
> 
> It's used internally (before calling lazy_set_method), but other than that I can't see a good use.
> 

That form is only for internal use.
You can remove the form without a block by replacing `Lazy.new(enum)'
with `Lazy.new(enum){|y, v| y<<v}'.

> 2) Is there a use case for specifying a symbol and arguments?
> 

Actually I did not know lazy_initialize can take a symbol :-p
So I'm not sure about how the symbol and arguments are used,
but it looks like for internal use.
According to svn annotate, it is introduced to implement lazy.cycle (r35028).

> Again, internally we call lazy_set_method, to the symbol and arguments are only used by inspect, right?
> 

That seems right.

> 3) Is there a good way to improve the `inspect` of such a lazy enum?
> 
>     p [11,12,13].filter_map{|i| i*i if i.even?} # => #<Enumerator::Lazy: #<Enumerator::Lazy: [1, 2, 3]>:each>
> 
> Notice the `each` and no appearance of `filter_map`
> 
> Doing `Lazy.new(self, :filter_map)` does not work and seems redundant.
> 
> 
> BTW, ultimately, I'm trying to see if Lazy.new can be adapted to accept a `size` lambda argument...

Well, I have no idea. It would be difficult to design Lazy.new which may take 
obj, block, symbol, args and size/size_fn...

BTW, I have a question. Document of to_enum says "see Enumerator#size=" but there is no such method. Is it a typo?
https://github.com/ruby/ruby/blob/e90ccd3beb0b9bf1125461ef68943578739bebbe/enumerator.c#L201

----------------------------------------
Bug #7248: Shouldn't Enumerator::Lazy.new be private?
https://bugs.ruby-lang.org/issues/7248#change-35364

Author: marcandre (Marc-Andre Lafortune)
Status: Assigned
Priority: Normal
Assignee: marcandre (Marc-Andre Lafortune)
Category: core
Target version: 2.0.0
ruby -v: ruby 2.0.0dev (2012-10-29 trunk 37380) [x86_64-darwin10.8.0]


Is there a reason why Enumerator::Lazy.new is not private?

Lazy enumerators should be created with `Enumerable#lazy`. Moreover, there is no doc, and it can give unexpected results too.


-- 
http://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [ruby-core:51418] [ruby-trunk - Bug #7248] Shouldn't Enumerator::Lazy.new be private?
  2012-10-31  4:23 [ruby-core:48639] [ruby-trunk - Bug #7248][Open] Shouldn't Enumerator::Lazy.new be private? marcandre (Marc-Andre Lafortune)
                   ` (3 preceding siblings ...)
  2013-01-11 19:58 ` [ruby-core:51387] " yhara (Yutaka HARA)
@ 2013-01-14  4:59 ` marcandre (Marc-Andre Lafortune)
  2013-01-14  4:59 ` [ruby-core:51419] " marcandre (Marc-Andre Lafortune)
  2013-01-16 15:10 ` [ruby-core:51468] " yhara (Yutaka HARA)
  6 siblings, 0 replies; 8+ messages in thread
From: marcandre (Marc-Andre Lafortune) @ 2013-01-14  4:59 UTC (permalink / raw
  To: ruby-core


Issue #7248 has been updated by marcandre (Marc-Andre Lafortune).

Priority changed from Normal to High

Thanks for the answers.

So, the public API of Lazy.new has the following issues:

* not documented
* should require a block but doesn't
* accepts a method name & arguments which aren't really usable
* has a misleading "inspect"

Moreover, the only way for the user to create a lazy enumerator with a size is to subclass Lazy.

Here's what I propose as the official Lazy.new documentation and API:

    Lazy.new(obj, size=nil) { |yielder, *values| ... }

    Creates a new Lazy enumerator. When the enumerator is actually enumerated
    (e.g. by calling #force), +obj+ will be enumerated and each value passed
    to the given block. The block can yield values back using +yielder+.
    For example, to create a method +filter_map+ in both lazy and
    non-lazy fashions:

        module Enumerable
          def filter_map(&block)
            map(&block).compact
          end
        end

        class Enumerator::Lazy
          def filter_map
            Lazy.new(self) do |yielder, *values|
              result = yield *values
              yielder << result if result
            end
          end
        end

        (1..Float::INFINITY).lazy.filter_map{|i| i*i if i.even?}.first(5)
            # => [4, 16, 36, 64, 100]

Does this seem acceptable to you?

We should also change the result of the 'inspect' method for these user created lazy enumerators to remove the 'each', i.e:

    (1..Float::INFINITY).lazy.filter_map{|i| i*i if i.even?}.inspect
    # => #<Enumerator::Lazy: #<Enumerator::Lazy: 1..Infinity>>

If we want to provide an easy way to provide more info in the inspect, we could add extra parameters, but they shouldn't be used when iterating, only for inspection...

> BTW, I have a question. Document of to_enum says "see Enumerator#size=" but there is no such method. Is it a typo?

Typo fixed, thanks.


----------------------------------------
Bug #7248: Shouldn't Enumerator::Lazy.new be private?
https://bugs.ruby-lang.org/issues/7248#change-35397

Author: marcandre (Marc-Andre Lafortune)
Status: Assigned
Priority: High
Assignee: marcandre (Marc-Andre Lafortune)
Category: core
Target version: 2.0.0
ruby -v: ruby 2.0.0dev (2012-10-29 trunk 37380) [x86_64-darwin10.8.0]


Is there a reason why Enumerator::Lazy.new is not private?

Lazy enumerators should be created with `Enumerable#lazy`. Moreover, there is no doc, and it can give unexpected results too.


-- 
http://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [ruby-core:51419] [ruby-trunk - Bug #7248] Shouldn't Enumerator::Lazy.new be private?
  2012-10-31  4:23 [ruby-core:48639] [ruby-trunk - Bug #7248][Open] Shouldn't Enumerator::Lazy.new be private? marcandre (Marc-Andre Lafortune)
                   ` (4 preceding siblings ...)
  2013-01-14  4:59 ` [ruby-core:51418] " marcandre (Marc-Andre Lafortune)
@ 2013-01-14  4:59 ` marcandre (Marc-Andre Lafortune)
  2013-01-16 15:10 ` [ruby-core:51468] " yhara (Yutaka HARA)
  6 siblings, 0 replies; 8+ messages in thread
From: marcandre (Marc-Andre Lafortune) @ 2013-01-14  4:59 UTC (permalink / raw
  To: ruby-core


Issue #7248 has been updated by marcandre (Marc-Andre Lafortune).

Assignee changed from marcandre (Marc-Andre Lafortune) to yhara (Yutaka HARA)


----------------------------------------
Bug #7248: Shouldn't Enumerator::Lazy.new be private?
https://bugs.ruby-lang.org/issues/7248#change-35398

Author: marcandre (Marc-Andre Lafortune)
Status: Assigned
Priority: High
Assignee: yhara (Yutaka HARA)
Category: core
Target version: 2.0.0
ruby -v: ruby 2.0.0dev (2012-10-29 trunk 37380) [x86_64-darwin10.8.0]


Is there a reason why Enumerator::Lazy.new is not private?

Lazy enumerators should be created with `Enumerable#lazy`. Moreover, there is no doc, and it can give unexpected results too.


-- 
http://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [ruby-core:51468] [ruby-trunk - Bug #7248] Shouldn't Enumerator::Lazy.new be private?
  2012-10-31  4:23 [ruby-core:48639] [ruby-trunk - Bug #7248][Open] Shouldn't Enumerator::Lazy.new be private? marcandre (Marc-Andre Lafortune)
                   ` (5 preceding siblings ...)
  2013-01-14  4:59 ` [ruby-core:51419] " marcandre (Marc-Andre Lafortune)
@ 2013-01-16 15:10 ` yhara (Yutaka HARA)
  6 siblings, 0 replies; 8+ messages in thread
From: yhara (Yutaka HARA) @ 2013-01-16 15:10 UTC (permalink / raw
  To: ruby-core


Issue #7248 has been updated by yhara (Yutaka HARA).

Assignee changed from yhara (Yutaka HARA) to marcandre (Marc-Andre Lafortune)

marcandre (Marc-Andre Lafortune) wrote:
> Here's what I propose as the official Lazy.new documentation and API:
> 
>     Lazy.new(obj, size=nil) { |yielder, *values| ... }
> 
>     Creates a new Lazy enumerator. When the enumerator is actually enumerated
>     (e.g. by calling #force), +obj+ will be enumerated and each value passed
>     to the given block. The block can yield values back using +yielder+.
>     For example, to create a method +filter_map+ in both lazy and
>     non-lazy fashions:
> 
>         module Enumerable
>           def filter_map(&block)
>             map(&block).compact
>           end
>         end
> 
>         class Enumerator::Lazy
>           def filter_map
>             Lazy.new(self) do |yielder, *values|
>               result = yield *values
>               yielder << result if result
>             end
>           end
>         end
> 
>         (1..Float::INFINITY).lazy.filter_map{|i| i*i if i.even?}.first(5)
>             # => [4, 16, 36, 64, 100]
> 
> Does this seem acceptable to you?
> 
Yes!
----------------------------------------
Bug #7248: Shouldn't Enumerator::Lazy.new be private?
https://bugs.ruby-lang.org/issues/7248#change-35448

Author: marcandre (Marc-Andre Lafortune)
Status: Assigned
Priority: High
Assignee: marcandre (Marc-Andre Lafortune)
Category: core
Target version: 2.0.0
ruby -v: ruby 2.0.0dev (2012-10-29 trunk 37380) [x86_64-darwin10.8.0]


Is there a reason why Enumerator::Lazy.new is not private?

Lazy enumerators should be created with `Enumerable#lazy`. Moreover, there is no doc, and it can give unexpected results too.


-- 
http://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2013-01-16 15:24 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-10-31  4:23 [ruby-core:48639] [ruby-trunk - Bug #7248][Open] Shouldn't Enumerator::Lazy.new be private? marcandre (Marc-Andre Lafortune)
2012-11-05 14:01 ` [ruby-core:48925] [ruby-trunk - Bug #7248][Assigned] " mame (Yusuke Endoh)
2012-12-07 16:17 ` [ruby-core:50665] [ruby-trunk - Bug #7248] " yhara (Yutaka HARA)
2012-12-09  1:44 ` [ruby-core:50702] " marcandre (Marc-Andre Lafortune)
2013-01-11 19:58 ` [ruby-core:51387] " yhara (Yutaka HARA)
2013-01-14  4:59 ` [ruby-core:51418] " marcandre (Marc-Andre Lafortune)
2013-01-14  4:59 ` [ruby-core:51419] " marcandre (Marc-Andre Lafortune)
2013-01-16 15:10 ` [ruby-core:51468] " yhara (Yutaka HARA)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).