Object#each ?

A

Andrew Wagner

[Note: parts of this message were removed to make it a legal post.]

A weird idea just popped into my head:

class Object
def each
yield self
end
end

Lets you enumerate without having to worry about whether or not you have a
collection. Thoughts? Hidden ramifications?
 
A

Andrew Wagner

[Note: parts of this message were removed to make it a legal post.]

A weird idea just popped into my head:

class Object
def each
yield self
end
end

Lets you enumerate without having to worry about whether or not you have a
collection. Thoughts? Hidden ramifications?

Ugh, did I just say collection? I thought my .Net days were behind me....I
meant, of course, an enumerable...
 
R

Robert Klemme

First of all if you implement #each then you should also include
Enumerable because the expectation would be that you also have all the
nice methods like #select, #map etc. This makes all objects Enumerable
which does not seem a good idea. One drawback of this approach is that
you won't notice if you accidentally pass something to a method which
should be Enumerable (I mean a real collection) - or at least the issue
might take some time to be detected.
Ugh, did I just say collection? I thought my .Net days were behind me....I
meant, of course, an enumerable...

:)

Cheers

robert
 
A

Andrew Wagner

[Note: parts of this message were removed to make it a legal post.]

First of all if you implement #each then you should also include Enumerable
because the expectation would be that you also have all the nice methods
like #select, #map etc. This makes all objects Enumerable which does not
seem a good idea.


An interesting point. I think I agree that cluttering Object with all the
Enumerable methods seems like a bad idea. I guess my thinking was that this
would be useful just for the purposes of having #each available, without
including Enumerable. This avoids the [*items] garbage.

One drawback of this approach is that you won't notice if you accidentally
pass something to a method which should be Enumerable (I mean a real
collection) - or at least the issue might take some time to be detected.


This is an interesting argument, because it sounds an awful lot like the
arguments I usually hear against duck-typing and dynamic typing in general.
Don't those also allow issues which "might take some time to be detected"
too? It seems like the answer is, as always, that's what specs/tests are
for.

One other thing that I thought of after my original email is that it might
be preferable to change it to "yield self unless nil?", because it could be
odd to have NilClass#each.

Thanks for the thoughts!
 
R

Robert Klemme

First of all if you implement #each then you should also include Enumera= ble
because the expectation would be that you also have all the nice methods
like #select, #map etc. =A0This makes all objects Enumerable which does = not
seem a good idea.

An interesting point. I think I agree that cluttering Object with all the
Enumerable methods seems like a bad idea. I guess my thinking was that th= is
would be useful just for the purposes of having #each available, without
including Enumerable. This avoids the [*items] garbage.

I usually opt for making things explicit - at least if they are so
clutterless as "[*items]". :)
=A0This is an interesting argument, because it sounds an awful lot like t= he
arguments I usually hear against duck-typing and dynamic typing in genera= l.
Don't those also allow issues which "might take some time to be detected"
too? It seems like the answer is, as always, that's what specs/tests are
for.

Hm, not sure I agree. With duck typing you will immediately know if
an object does not implement a required method. Granted, you can pass
in all objects that satisfy the used contract without "noticing". But
then again that's the whole point of duck typing. :) Maybe my
argument is not too important though. The main point would be anyway
the first argument against, that then everything is Enumerable and the
module Enumerable basically becomes meaningless.
One other thing that I thought of after my original email is that it migh= t
be preferable to change it to "yield self unless nil?", because it could = be
odd to have NilClass#each.

No. You would simply use inheritance and implement a special version
in class NilClass which throws, e.g.

class NilClass
def each
raise NoMethodError, "undefined method `each` for %p" % self
end
end
Thanks for the thoughts!

You're welcome! It's an interesting exchange.

Kind regards

robert

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 
A

Andrew Wagner

[Note: parts of this message were removed to make it a legal post.]

On Wed, Dec 1, 2010 at 8:52 AM, niklas | brueckenschlaeger <
Consider code like this:

def do_sth_on(this)
if this.kind_of?(Enumerable)
this.map {|item| do_sth_on(item) }
else
# whatever
end
end

This is a method that either works on a collection or on single item. As
soon as a you make Object behave like Enumerable, this breaks and leads
to recursion.

Well, sure. The whole point is to write, instead of the above:

def do_sth_on(this)
this.each do
#whatever
end
end
 
J

Josh Cheek

[Note: parts of this message were removed to make it a legal post.]

Well, sure. The whole point is to write, instead of the above:

def do_sth_on(this)
this.each do
#whatever
end
end

I think he means that you remove the base case that recursive functions may
be relying on. Here is an example:


# a function, maybe in a lib you are using,
# silently doing its job, you don't even know its there
# to do its job it must recursively traverse enumerable objects
# in this example, it just prints them out
def print_nested(iteratable)
iteratable.each do |*objects|
if objects.size > 1
print_nested(objects)
next
end
object = objects.first
if object.respond_to? :each
print_nested object
else
puts object
end
end
end


# prints 1 through 16
print_nested [
1,2,[3,4,[5]],
{ 6 => 7,
8 => [ 9 , 10 , { 11 => 12..14 } ]
},
"15\n16",
]


# make everything respond to each
class Object
def each
yield self
end
end


# stack overflow
print_nested [
1,2,[3,4,[5]],
{ 6 => 7,
8 => [ 9 , 10 , { 11 => 12..14 } ]
},
"15\n16",
]
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,143
Latest member
DewittMill
Top