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 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...
On Tue, Nov 30, 2010 at 12:44 PM, Andrew Wagner <wagner.andrew@gmail.com>wrote:
A weird idea just popped into my head:
class Object
def each
yield self
end
endLets you enumerate without having to worry about whether or not you have a
collection. Thoughts? Hidden ramifications?
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.
Always very dangerous to modify core classes and in this case it seems
suicidal
-- niklas
On Wed, 2010-12-01 at 02:44 +0900, Andrew Wagner wrote:
A weird idea just popped into my head:
class Object
def each
yield self
end
endLets you enumerate without having to worry about whether or not you have a
collection. Thoughts? Hidden ramifications?
A weird idea just popped into my head:
class Object
def each
yield self
end
endLets you enumerate without having to worry about whether or not you have a
collection. Thoughts? Hidden ramifications?
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
On 11/30/2010 06:45 PM, Andrew Wagner wrote:
On Tue, Nov 30, 2010 at 12:44 PM, Andrew Wagner<wagner.andrew@gmail.com>wrote:
Well, sure. The whole point is to write, instead of the above:
def do_sth_on(this)
this.each do
#whatever
end
end
On Wed, Dec 1, 2010 at 8:52 AM, niklas | brueckenschlaeger < niklas@brueckenschlaeger.de> wrote:
Consider code like this:
def do_sth_on(this)
if this.kind_of?(Enumerable)
this.map {|item| do_sth_on(item) }
else
# whatever
end
endThis 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.
A weird idea just popped into my head:
class Object
def each
yield self
end
endLets you enumerate without having to worry about whether or not you have
a
collection. Thoughts? Hidden ramifications?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!
On Tue, Nov 30, 2010 at 4:40 PM, Robert Klemme <shortcutter@googlemail.com>wrote:
On 11/30/2010 06:45 PM, Andrew Wagner wrote:
On Tue, Nov 30, 2010 at 12:44 PM, Andrew Wagner<wagner.andrew@gmail.com >> >wrote:
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",
]
On Wed, Dec 1, 2010 at 8:30 AM, Andrew Wagner <wagner.andrew@gmail.com>wrote:
> 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
A weird idea just popped into my head:
class Object
def each
yield self
end
endLets you enumerate without having to worry about whether or not you have
a
collection. Thoughts? Hidden ramifications?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.
I usually opt for making things explicit - at least if they are so
clutterless as "[*items]".
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.
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 might
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
On Wed, Dec 1, 2010 at 12:00 AM, Andrew Wagner <wagner.andrew@gmail.com> wrote:
On Tue, Nov 30, 2010 at 4:40 PM, Robert Klemme > <shortcutter@googlemail.com>wrote:
On 11/30/2010 06:45 PM, Andrew Wagner wrote:
On Tue, Nov 30, 2010 at 12:44 PM, Andrew Wagner<wagner.andrew@gmail.com >>> >wrote:
--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/