Implementing Lazy map

Let’s implement method chaining on methods such as map and take. Enumerable::Lax returns a Lax instance, which means we need to define Lax versions of map and take. Each invocation of map and take will in turn return yet another Lax instance. Recall how the original implementation “wraps” each method call with a “lazy layer.” You’ll do exactly the same thing here.

How would the map method in Lax look? Here’s a start:

 def​ map(&block)
 end

You also know that you would need to return a new Lax instance. Also, since map is going to be chained, you should expect that self is going to be another Lax instance:

 def​ map(&block)
» Lax.new(self)
 end

For the method’s logic, you’ll want to populate the yielder object with elements that are going to be modified by the map method. That means that you must somehow pass two things into the Lax instance in map: the yielder object, and the element to be mapped on. You can pass these via a block argument like so:

 def​ map(&block)
» Lax.new(self) ​do​ |yielder, val|
» yielder << block.call(val)
»end
 end

What does this do? It looks like block is invoked with val, and that element is then passed into the yielder. That’s not completely accurate, though. Instead, it’s more like the instructions of how to treat a mapped value being stored inside the yielder object.

Since the Lax initializer accepts a block, the constructor needs to be modified:

 def​ initialize(receiver)
 super​() ​do​ |yielder|
  receiver.each ​do​ |val|
»if​ block_given?
»yield​(yielder, val)
»else
» yielder << val
»end
 end
 end
 end

Let’s trace through what happens when a block is supplied, using the Lax version of the map method.

When we supply a block, as in the case of the Lax#map method, it is yielded, where both the yielder object and the element val are given to the yield method.

Does it work? Let’s find out:

 >>​ 1.upto(Float::INFINITY).lax.map { |x| x*x }.map { |x| x+1 }.first(5)
 =>​ [2, 5, 10, 17, 26]

Enumerable#first(5) returns the first five elements of the enumerable, which gives you [2, 5, 10, 17, 26]. It is this method that “forces” the Lax enumerable to produce values.

That takes care of map. Let’s implement take.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset