Enumerable#find returns an enumerator?

R

Roger Pack

Hello all.
I would have expected that

[1,2,3].find(3)

just return me the element 3, not an enumerator, since it will at most
return me one item, so it doesn't seem very "enumerable" to me (at most
one item).

Thoughts?
-r
 
C

Chris Hulan

Hello all.
I would have expected that

[1,2,3].find(3)

just return me the element 3, not an enumerator, since it will at most
return me one item, so it doesn't seem very "enumerable" to me (at most
one item).

Thoughts?
-r

if there were more than 1 occurrence retuning an enumerator makes
sense,
but there is Enumerable::find_all that sounds better suited to that
behavior

Guess you use the block instead?
[1,2,3].find{|x| x == 3}

cheers
 
J

Jeremy Bopp

Hello all.
I would have expected that

[1,2,3].find(3)

just return me the element 3, not an enumerator, since it will at most
return me one item, so it doesn't seem very "enumerable" to me (at most
one item).

Take a look at the documentation:

http://rdoc.info/stdlib/core/1.9.2/Enumerable:find

Basically, you're trying to use the method incorrectly. I'm not sure if
what you're trying to do is find the third element in the array or find
all the 3's within the array. Maybe what you actually want is this:

[1,2,3][2]

That will return the third element from the array. In this case 3.

If you want to return all the 3's for some reason, keep in mind that
there may be more than 1 or even none of them in any given array.
Writing your code to account for 3 different return cases from find
would be messy and error prone, so always returning an enumerable would
make sense for most users since that is the most general case. It may
be an enumerable of 0 or 1 items, but that's still a valid enumeration.

Of course, the way you seem to be going about this won't work anyway
since the method doesn't work the way you expect. :) To find all the
3's do this as Chris suggested:

[1,2,3].find { |x| x == 3 }

-Jeremy
 
L

Lars Schirrmeister

The find method on an array takes a block and returns an enumerator if =
no block is given.
The value you pass to the find method is not the value you want to find =
but the value which is returned if no block evaluates to true.

Lars

Am 10.05.2011 um 20:48 schrieb Roger Pack:
 
7

7stud --

Roger Pack wrote in post #997818:
Hello all.
I would have expected that

[1,2,3].find(3)

just return me the element 3, not an enumerator,

Where in the world did you dream up that? Enumerable#find() returns the
first element for which the block is true. Where is your block? The
argument to find() is the default value you want find() to return if the
block is false for all elements.
 
R

Robert Klemme

The find method on an array takes a block and returns an enumerator
if no block is given. The value you pass to the find method is not
the value you want to find but the value which is returned if no
block evaluates to true.

More precisely: the value passed is something which returns the
replacement value when #called:

irb(main):007:0> (10..20).to_a.find(99) {|x| x > 150}
NoMethodError: undefined method `call' for 99:Fixnum
from (irb):7:in `find'
from (irb):7
from /usr/local/bin/irb19:12:in `<main>'
irb(main):008:0> (10..20).to_a.find(lambda {99}) {|x| x > 150}
=> 99

Which is precisely what the docs say:

$ ri19 -T Enumerable#find
-------------------------------------------------------- Enumerable#find
enum.detect(ifnone = nil) {| obj | block } => obj or nil
enum.find(ifnone = nil) {| obj | block } => obj or nil

From Ruby 1.9.1
------------------------------------------------------------------------
Passes each entry in _enum_ to _block_. Returns the first for which
_block_ is not +false+. If no object matches, calls _ifnone_ and
returns its result when it is specified, or returns +nil+

(1..10).detect {|i| i % 5 == 0 and i % 7 == 0 } #=> nil
(1..100).detect {|i| i % 5 == 0 and i % 7 == 0 } #=> 35

There are places where Ruby's documentation is bad but here
documentation is clear. Why do so many people tell different stories if
it is so easy to read this up in documentation? (And, btw, it has been
that way in all versions from 1.8.6 on.)

Cheers

robert
 
B

Brian Candler

Robert K. wrote in post #997848:
(And, btw, it has been
that way in all versions from 1.8.6 on.)

I'm pretty sure that calling Enumerable methods without a block only
returned an Enumerator from 1.8.7. In 1.8.6 you would have gotten an
error ('method called without a block' or words to that effect), which
in this case would have been much more useful to the OP.
 
R

Robert Klemme

Robert K. wrote in post #997848:

I'm pretty sure that calling Enumerable methods without a block only
returned an Enumerator from 1.8.7. In 1.8.6 you would have gotten an
error ('method called without a block' or words to that effect), which
in this case would have been much more useful to the OP.

Yes, but that was not the point. I was explicitly talking about the
semantics of the argument to #find.

http://www.ruby-doc.org/core-1.8.6/classes/Enumerable.html#M001088
http://www.ruby-doc.org/core-1.8.7/classes/Enumerable.html#M001147
http://www.ruby-doc.org/core/classes/Enumerable.html#M001484

Cheers

robert
 
B

Brian Candler

Robert K. wrote in post #997944:
Yes, but that was not the point. I was explicitly talking about the
semantics of the argument to #find.

You said: "here documentation is clear. Why do so many people tell
different stories if it is so easy to read this up in documentation?"

And my answer is: maybe because the documentation is so poor.

Your example demonstrates this, because ri doesn't mention about
Enumerable#find returning an Enumerator, which is what the original
question was.

Admittedly, the errors are usually of omission, rather than being
actually wrong. This particular one has been fixed in 1.9.2, but not
backported to 1.8.7p299 (at least)
 
R

Robert Klemme

Robert K. wrote in post #997944:

You said: "here documentation is clear. Why do so many people tell
different stories if it is so easy to read this up in documentation?"

And my answer is: maybe because the documentation is so poor.

Ah, OK *now* you said it.
Your example demonstrates this, because ri doesn't mention about
Enumerable#find returning an Enumerator, which is what the original
question was.

Admittedly, the errors are usually of omission, rather than being
actually wrong. This particular one has been fixed in 1.9.2, but not
backported to 1.8.7p299 (at least)

While we talk about omission: I really couldn't figure that from your
first posting. :)

Kind regards

robert
 
7

7stud --

Brian Candler wrote in post #997970:
Robert K. wrote in post #997944:

You said: "here documentation is clear. Why do so many people tell
different stories if it is so easy to read this up in documentation?"

And my answer is: maybe because the documentation is so poor.

Your example demonstrates this, because ri doesn't mention about
Enumerable#find returning an Enumerator, which is what the original
question was.

Which makes me wonder why the ri docs are different from the docs you
get if you google: ruby Enumerable. The first hit will be the ruby
1.9.2 docs for Enumerable, and if you click on find() it says:

===
Passes each entry in enum to block. Returns the first for which block is
not false. If no object matches, calls ifnone and returns its result
when it is specified, or returns nil otherwise.

If no block is given, an enumerator is returned instead.
===
 

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

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,119
Latest member
IrmaNorcro
Top