From: Avdi Grimm Date: 2015-01-11T13:56:56-05:00 Subject: [ruby-core:67513] Refinements on modules? --001a113636965eec7e050c64f5cd Content-Type: text/plain; charset=UTF-8 The other day on the Ruby Rogues forum, someone asked how to idiomatically write the following Clojure example in Ruby: (take 25 (squares-of (integers))) My answer was: 0.step.lazy.map{ |n| n**2 }.take(25).to_a ...which I'm pretty happy with, since it's reasonably concise and preserves the laziness of the Clojure version. The only part that bothered me was the squaring calculation: map{ |n| n**2 } Presumably, `squares-of` is a Clojure built-in. I don't think Ruby should add this to Enumerable; it's far too niche a use case. But I wanted a way to insert a Ruby-ish squares_of directly into the chain of operations, like this: 0.step.lazy.squares.take(25).to_a Obviously I could monkeypatch Enumerable to get this. But I thought it would be nicer to make the patch non-invasive using refinements. And here's where I ran into a snag: you can't refine modules. I wound up refining Enumerator: module Squares refine Enumerator do def squares map{ |n| n**2 } end end end using Squares 0.step.lazy.squares.take(5).to_a # => [0, 1, 4, 9, 16] This works fine. But I'm bothered by refining Enumerator instead of Enumerable. It means that the refinement isn't generic. In order to have consistency, I have to know exactly what class[es] might be involved, and refine all of them. This doesn't feel very duck-type friendly. And the more I think about uses of refinements, the more I think of wanting to refine modules that are widely included, such as Enumerable or Comparable. So my question is: is this a feature that is coming? -- Avdi Grimm http://avdi.org --001a113636965eec7e050c64f5cd Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable
The other day on the Ruby Rogues forum, someone asked= how to idiomatically write the following Clojure example in Ruby:

=C2=A0 =C2=A0=C2=A0(take 25 (squares-of (integers)))
=

My answer was:

=C2=A0=C2=A00.s= tep.lazy.map{ |n| n**2 }.take(25).to_a

...which I&= #39;m pretty happy with, since it's reasonably concise and preserves th= e laziness of the Clojure version.

The only part t= hat bothered me was the squaring calculation: map{ |n| n**2 }
Presumably, `squares-of` is a Clojure built-in. I don't thi= nk Ruby should add this to Enumerable; it's far too niche a use case. B= ut I wanted a way to insert a Ruby-ish squares_of directly into the chain o= f operations, like this:

=C2=A0 0.step.lazy.square= s.take(25).to_a

Obviously I could monkeypatch Enum= erable to get this. But I thought it would be nicer to make the patch non-i= nvasive using refinements. And here's where I ran into a snag: you can&= #39;t refine modules.

I wound up refining Enumerat= or:

=C2=A0 module Squares
=C2=A0 = =C2=A0 refine Enumerator do
=C2=A0 =C2=A0 =C2=A0 def squares
=C2=A0 =C2=A0 =C2=A0 =C2=A0 map{ |n| n**2 }
=C2=A0 =C2=A0 = =C2=A0 end
=C2=A0 =C2=A0 end
=C2=A0 end

<= /div>
=C2=A0 using Squares

=C2=A0 0.step.lazy.= squares.take(5).to_a # =3D> [0, 1, 4, 9, 16]

<= div>This works fine. But I'm bothered by refining Enumerator instead of= Enumerable. It means that the refinement isn't generic. In order to ha= ve consistency, I have to know exactly what class[es] might be involved, an= d refine all of them.=C2=A0

This doesn't feel = very duck-type friendly. And the more I think about uses of refinements, th= e more I think of wanting to refine modules that are widely included, such = as Enumerable or Comparable.

So my question is: is= this a feature that is coming?

--
Avdi Grimm
http://avdi.org

--001a113636965eec7e050c64f5cd--