From: Artem Voroztsov Date: 2011-10-31T20:14:12+09:00 Subject: [ruby-core:40554] Re: [ruby-trunk - Feature #4890] Enumerable#lazy I prefer to_lazy and to_a instead of delay and force PS: Here some student's code from http://rails.vsevteme.ru/2009/04/20/samorazvitie/10-metaprogramming-patterns-15-kyu-lenivye-konteynery: Emumerator.module_eval do ��def to_lazy ����LazyContainer.new(this) ��end end container.map{|i| f(i)}.select{|i| g(i)}.uniq.each {|i| puts i} module LazyEnumerable include Enumerable ZERO_PIPE_LAMBDA = lambda {|i| [i,true]} ZERO_RESET_LAMBDA = lambda {} def self.included(klass) klass.class_eval < < -EOE alias each_orig each def each(&block) @pipe_lambda ||= ZERO_PIPE_LAMBDA each_orig do |elem| value,take = @pipe_lambda[elem] block[value] if take end @reset_lambda ||= ZERO_RESET_LAMBDA @reset_lambda.call end EOE end def map!(&block) old_pipe = @pipe_lambda ||= ZERO_PIPE_LAMBDA @pipe_lambda = lambda do |i| value,take = old_pipe[i] take ? [block[value], take] : [nil, false] end self end def select!(&block) old_pipe = @pipe_lambda ||= ZERO_PIPE_LAMBDA @pipe_lambda = lambda do |i| value,take = old_pipe[i] take ? [value, block[value]] : [nil, false] end self end def uniq!(&block) old_pipe = @pipe_lambda ||= ZERO_PIPE_LAMBDA old_reset = @reset_lambda ||= ZERO_RESET_LAMBDA filter = Hash.new{|h,k| h[k]={}} @reset_lambda = lambda do old_reset.call filter[self].clear end @pipe_lambda = lambda do |i| value,take = old_pipe[i] take ? ( if filter[self][value] [nil, false] else filter[self][value] = true [value, true] end ) : [nil, false] end self end make_nobang :uniq, :map, :select end class LazyContainer def initialize(enum) @enum = enum end def each(&block) @enum.each(&block) end include LazyEnumerable end 2011/10/31 Shugo Maeda > > Issue #4890 has been updated by Shugo Maeda. > > > Shugo Maeda wrote: > > FYI, Scala has a similar method called view. �I don't know whether > > the name view is better than lazy because I'm not a native English speaker. > (snip) > > In Ruby, results are always arrays, so we can use to_a instead of force. > > But the name force looks better than to_a for me. > > If the method force is added, delay sounds more natural than lazy or view for me. > > �p (1..10).delay.map{|i| i+1}.map{|i| i+2}.force > > That's just off the top of my head, and it may be confusing. > > ---------------------------------------- > Feature #4890: Enumerable#lazy > http://redmine.ruby-lang.org/issues/4890 > > Author: Yutaka HARA > Status: Open > Priority: Normal > Assignee: Yukihiro Matsumoto > Category: core > Target version: 2.0 > > > =begin > = Example > Print first 100 primes which are in form of n^2+1 > > � require 'prime' > � INFINITY = 1.0 / 0 > � p (1..INFINITY).lazy.map{|n| n**2+1}.select{|m| m.prime?}.take(100) > > (Example taken from enumerable_lz; thanks @antimon2) > > = Description > > Enumerable#lazy returns an instance of Enumerable::Lazy. > This is the only method added to the existing bulit-in classes. > > Lazy is a subclass of Enumerator, which includes Enumerable. > So you can call any methods of Enumerable on Lazy, except methods like > map, select, etc. are redefined as 'lazy' versions. > > = Sample implementation > > (()) > (also attached to this ticket) > > =end > > > > -- > http://redmine.ruby-lang.org > -- �����! ����� ��������