Array#index block and rdetect

Tiny RCR suggestion:

Array#index optionally take a block like Enumerable#detect does.

    ['a','b','c'].index{|e| e == 'b'} # => 1
    ['a','b','c'].index{|e| e == 'c'} # => 2
    ['a','a','a'].index{|e| e == 'a'} # => 0
    ['a','a','a'].index{|e| e == 'b'} # => nil

Question: why isn't #index a method of Enumerable, considering
#each_with_index is? (FYI: 'alias find detect'.)

Lastly, what about an rdetect?

···

--
( o _ カラチ (Pakistan)
// trans.
/ \ transami@runbox.com

I don't give a damn for a man that can only spell a word one way.
-Mark Twain

"trans. (T. Onoma)" <transami@runbox.com> schrieb im Newsbeitrag news:200409190606.22327.transami@runbox.com...

Tiny RCR suggestion:

Array#index optionally take a block like Enumerable#detect does.

   ['a','b','c'].index{|e| e == 'b'} # => 1
   ['a','b','c'].index{|e| e == 'c'} # => 2
   ['a','a','a'].index{|e| e == 'a'} # => 0
   ['a','a','a'].index{|e| e == 'b'} # => nil

Question: why isn't #index a method of Enumerable, considering
#each_with_index is? (FYI: 'alias find detect'.)

Because not all collections keep a definite order as Array does. For example, hashes do not keep any certain order of elements hence indexing does not make any sense.

Lastly, what about an rdetect?

Not in Enumerable because each only iterates in one direction. (Ok, you could go through it an output the last but that would not work for Enumerables that return infinite elements.)

Regards

    robert

Hi --

···

On Sun, 19 Sep 2004, trans. (T. Onoma) wrote:

Tiny RCR suggestion:

Array#index optionally take a block like Enumerable#detect does.

    ['a','b','c'].index{|e| e == 'b'} # => 1
    ['a','b','c'].index{|e| e == 'c'} # => 2
    ['a','a','a'].index{|e| e == 'a'} # => 0
    ['a','a','a'].index{|e| e == 'b'} # => nil

See the thread at
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/105314
for a recent discussion of this. I basically like the idea, with a
couple of caveats which are discussed in that thread.

David

--
David A. Black
dblack@wobblini.net

"trans. (T. Onoma)" <transami@runbox.com> schrieb im Newsbeitrag
news:200409190606.22327.transami@runbox.com...

> Tiny RCR suggestion:
>
> Array#index optionally take a block like Enumerable#detect does.
>
> ['a','b','c'].index{|e| e == 'b'} # => 1
> ['a','b','c'].index{|e| e == 'c'} # => 2
> ['a','a','a'].index{|e| e == 'a'} # => 0
> ['a','a','a'].index{|e| e == 'b'} # => nil

But this Array#index {block) is acceptable, yes?

> Question: why isn't #index a method of Enumerable, considering
> #each_with_index is? (FYI: 'alias find detect'.)

Because not all collections keep a definite order as Array does. For
example, hashes do not keep any certain order of elements hence indexing
does not make any sense.

Couldn't the index of a hash be considered the key? So the block of #index
when applied is the value. i.e.

    {:a=>'a',:b=>'b',:c=>'b'}.index{|e| e == 'b'} # => :b
  
But then, of course, there would be no telling which key you might get.
Suppose that could be considered a problem.

> Lastly, what about an rdetect?

Not in Enumerable because each only iterates in one direction. (Ok, you
could go through it an output the last but that would not work for
Enumerables that return infinite elements.)

I see.

Hmm... sometimes it seems like these are quite categorized as finely as they
might be.

T.

···

On Sunday 19 September 2004 07:59 am, Robert Klemme wrote:

--
( o _ カラチ
// trans.
/ \ transami@runbox.com

I don't give a damn for a man that can only spell a word one way.
-Mark Twain

Hi,

···

In message "Re: Array#index block and rdetect" on Sun, 19 Sep 2004 23:20:08 +0900, "trans. (T. Onoma)" <transami@runbox.com> writes:

> Array#index optionally take a block like Enumerable#detect does.
>
> ['a','b','c'].index{|e| e == 'b'} # => 1
> ['a','b','c'].index{|e| e == 'c'} # => 2
> ['a','a','a'].index{|e| e == 'a'} # => 0
> ['a','a','a'].index{|e| e == 'b'} # => nil

But this Array#index {block) is acceptable, yes?

Along with assoc and rassoc. I will consider this idea.

              matz.

"trans. (T. Onoma)" <transami@runbox.com> schrieb im Newsbeitrag news:200409191019.59425.transami@runbox.com...

"trans. (T. Onoma)" <transami@runbox.com> schrieb im Newsbeitrag
news:200409190606.22327.transami@runbox.com...

> Tiny RCR suggestion:
>
> Array#index optionally take a block like Enumerable#detect does.
>
> ['a','b','c'].index{|e| e == 'b'} # => 1
> ['a','b','c'].index{|e| e == 'c'} # => 2
> ['a','a','a'].index{|e| e == 'a'} # => 0
> ['a','a','a'].index{|e| e == 'b'} # => nil

But this Array#index {block) is acceptable, yes?

Yes, I think that could be useful.

> Question: why isn't #index a method of Enumerable, considering
> #each_with_index is? (FYI: 'alias find detect'.)

Because not all collections keep a definite order as Array does. For
example, hashes do not keep any certain order of elements hence indexing
does not make any sense.

Couldn't the index of a hash be considered the key? So the block of #index
when applied is the value. i.e.

Good idea! That way Hash and Array are partly interchangable. You could view an array as a special case of an associative storage with the restriction that keys are ints.

   {:a=>'a',:b=>'b',:c=>'b'}.index{|e| e == 'b'} # => :b

But then, of course, there would be no telling which key you might get.
Suppose that could be considered a problem.

The same holds for #index so I think this is not a problem. You only get one key, presumably the first that is found. Same story for Array#index:

%w{a a a a}.index "a"

=> 0

class Hash
def index(val)
  each {|k,v| return k if val == v}
  nil
end

=> nil

{1=>"a", 2=>"a"}.index "a"

=> 1

{1=>"a", 2=>"a"}.index "ad"

=> nil

> Lastly, what about an rdetect?

Not in Enumerable because each only iterates in one direction. (Ok, you
could go through it an output the last but that would not work for
Enumerables that return infinite elements.)

I see.

Hmm... sometimes it seems like these are quite categorized as finely as they
might be.

Yes, definitely! That's what I discovered, too, when I suggested Enumerable#size and Enumerable#empty? They just need more preconditions than Enumerable. Matz did really a great job here!

Kind regards

    robert

···

On Sunday 19 September 2004 07:59 am, Robert Klemme wrote:

Hi --

Couldn't the index of a hash be considered the key? So the block of #index
when applied is the value. i.e.

That's how I tend to see it, though Ruby has two interpretations of
"index" for hashes:

  irb(main):007:0> h = Hash[*%w{a b c d}]
  => {"a"=>"b", "c"=>"d"}
  irb(main):008:0> h.index("d")
  => "c"
  irb(main):009:0> h.each_with_index {|e,i| p i if e[0] == "c"}
  1

This is one of the reasons I've always felt that Hash#each_with_index
should be eliminated. The "index" in h.each_with_index is not the
same as the "index" of h.index. h.each_with_index is effectively
equivalent to h.to_a.each_with_index, but with the to_a being hidden.

David

···

On Sun, 19 Sep 2004, trans. (T. Onoma) wrote:

--
David A. Black
dblack@wobblini.net

trans. (T. Onoma) wrote:

Couldn't the index of a hash be considered the key? So the block of #index when applied is the value. i.e.

I agree heavily with this. It would greatly simplify Hashes. If we then could also make them yield(value, key) and merge Enumerable#each and Enumerable#each_with_index (and propagate that to the other methods like #map and so on) Enumerables would really only need to provide #each instead of overwriting all the Hash methods. It would contribute to consistency and simplicity IMHO, but it is a big change.

Regards,
Florian Gross

Right! Index in this second sense has no significance with regards to Hash
proper.

To be honest I have always felt a bit odd about Hash being "Enumerable" for
this very reason. Hash elements cannot be "numbered" --unless converted
(whether by key or by value) into an array first. Perhaps part of the oddness
is just that the word "Enumerable" cannotes more then it should. "Indexable"
seems more exact.

T.

···

On Sunday 19 September 2004 12:34 pm, David A. Black wrote:

On Sun, 19 Sep 2004, trans. (T. Onoma) wrote:
> Couldn't the index of a hash be considered the key? So the block of
> #index when applied is the value. i.e.

That's how I tend to see it, though Ruby has two interpretations of
"index" for hashes:

  irb(main):007:0> h = Hash[*%w{a b c d}]
  => {"a"=>"b", "c"=>"d"}
  irb(main):008:0> h.index("d")
  => "c"
  irb(main):009:0> h.each_with_index {|e,i| p i if e[0] == "c"}
  1

This is one of the reasons I've always felt that Hash#each_with_index
should be eliminated. The "index" in h.each_with_index is not the
same as the "index" of h.index. h.each_with_index is effectively
equivalent to h.to_a.each_with_index, but with the to_a being hidden.

--
( o _ カラチ
// trans.
/ \ transami@runbox.com

I don't give a damn for a man that can only spell a word one way.
-Mark Twain

Hi,

···

In message "Re: Array#index block and rdetect" on Mon, 20 Sep 2004 00:39:42 +0900, "Robert Klemme" <bob.news@gmx.net> writes:

Couldn't the index of a hash be considered the key? So the block of #index
when applied is the value. i.e.

Good idea! That way Hash and Array are partly interchangable. You could
view an array as a special case of an associative storage with the
restriction that keys are ints.

In that case, Hash#each and Enumerable#each_with_index should be
redefined for consistency.

              matz.

Hi --

···

On Mon, 20 Sep 2004, Yukihiro Matsumoto wrote:

Hi,

In message "Re: Array#index block and rdetect" > on Mon, 20 Sep 2004 00:39:42 +0900, "Robert Klemme" <bob.news@gmx.net> writes:

>> Couldn't the index of a hash be considered the key? So the block of #index
>> when applied is the value. i.e.
>
>Good idea! That way Hash and Array are partly interchangable. You could
>view an array as a special case of an associative storage with the
>restriction that keys are ints.

In that case, Hash#each and Enumerable#each_with_index should be
redefined for consistency.

Could #each_with_index be left to individual classes, as #each_index
is?

David

--
David A. Black
dblack@wobblini.net

Hi,

···

In message "Re: Array#index block and rdetect" on Mon, 20 Sep 2004 10:19:46 +0900, "David A. Black" <dblack@wobblini.net> writes:

In that case, Hash#each and Enumerable#each_with_index should be
redefined for consistency.

Could #each_with_index be left to individual classes, as #each_index
is?

Can you express your idea in detail?

  * Enumerable#each_index should be removed (yes/no)
  * Array#each_with_index should be added (yes/no)
  * Hash#each_with_index should be added with key as index (yes/no)
  * How about other enumerable classes?

              matz.

Hi --

Hi,

>> In that case, Hash#each and Enumerable#each_with_index should be
>> redefined for consistency.
>
>Could #each_with_index be left to individual classes, as #each_index
>is?

Can you express your idea in detail?

  * Enumerable#each_index should be removed (yes/no)

There is no Enumerable#each_index -- nothing to remove.

  * Array#each_with_index should be added (yes/no)

Yes. (Florian's ideas about merging #each and #each_with_index is
also interesting, though I'm not sure it would be good to always have
an "extra" parameter passed to the block.)

  * Hash#each_with_index should be added with key as index (yes/no)

No. The key is already available to block, with #each. (But you said
Hash#each would be redefined -- I'm not sure what that would involve.)

  * How about other enumerable classes?

I think the idea of every enumerable class having an "index", defined
as part of that class, is possibly useful. For hashes it could be the
keys; for arrays, the integer index; for files, the line number. In
some cases (like index/key for hashes), it might be redundant. But it
might open up some good possibilities.

That would mean an enumerable class would have to be able to say:
"This is how I define 'index'." I'm not sure how that would work.

David

···

On Mon, 20 Sep 2004, Yukihiro Matsumoto wrote:

In message "Re: Array#index block and rdetect" > on Mon, 20 Sep 2004 10:19:46 +0900, "David A. Black" <dblack@wobblini.net> writes:

--
David A. Black
dblack@wobblini.net

Hi,

  * Enumerable#each_index should be removed (yes/no)

There is no Enumerable#each_index -- nothing to remove.

I meant each_with_index.

  * How about other enumerable classes?

I think the idea of every enumerable class having an "index", defined
as part of that class, is possibly useful. For hashes it could be the
keys; for arrays, the integer index; for files, the line number. In
some cases (like index/key for hashes), it might be redundant. But it
might open up some good possibilities.

The most consistent (but incompatible) change would be:

  * leave Enumerable#each_with_index unchanged.
  * make Hash#each as alias of Hash#each_value
  * redefine Hash#each_with_index as alias of Hash#each_pair

But this change may break many programs.
              matz.

···

In message "Re: Array#index block and rdetect" on Mon, 20 Sep 2004 11:12:12 +0900, "David A. Black" <dblack@wobblini.net> writes:

David A. Black wrote:

Hi --

* How about other enumerable classes?

I think the idea of every enumerable class having an "index", defined
as part of that class, is possibly useful. For hashes it could be the
keys; for arrays, the integer index; for files, the line number. In
some cases (like index/key for hashes), it might be redundant. But it
might open up some good possibilities.

That would mean an enumerable class would have to be able to say:
"This is how I define 'index'." I'm not sure how that would work.

All enumerable objects don't neccessarilly have a meaningful concept of an index. Eg. sets, multisets. Enumerable and Indexable are two different things, though Indexable extends Enumerable.

···

On Mon, 20 Sep 2004, Yukihiro Matsumoto wrote:

"Yukihiro Matsumoto" <matz@ruby-lang.org> schrieb im Newsbeitrag
news:1095650370.096071.21408.nullmailer@x31.priv.netlab.jp...

Hi,

>> * Enumerable#each_index should be removed (yes/no)
>
>There is no Enumerable#each_index -- nothing to remove.

I meant each_with_index.

>> * How about other enumerable classes?
>
>I think the idea of every enumerable class having an "index", defined
>as part of that class, is possibly useful.

Sorry, David, I stongly disagree: IMHO an index does only make sense in a
class that maintains a certain order (such as Array). A Hash does not
have a particular order and thus Enumerable#each_with_index is the
appropriate thing; here the index is valid just for the current iteration
and can be used for printing or whatever. But I would not want to add an
index to a Hash.

Or did you mean to use the hash key as index? That would be a different
story... While that would make sense for Array and Hash I think there are
a lot Enumerables out there that do not correspond easily to associative
storage, for example a Enumerable that emits arbitrary many random numbers
in its #each method.

For hashes it could be the
>keys; for arrays, the integer index; for files, the line number. In
>some cases (like index/key for hashes), it might be redundant. But it
>might open up some good possibilities.

The most consistent (but incompatible) change would be:

  * leave Enumerable#each_with_index unchanged.
  * make Hash#each as alias of Hash#each_value
  * redefine Hash#each_with_index as alias of Hash#each_pair

But this change may break many programs.

Yeah, that's true. What about a method in Hash that changes method
behavior to the array compatible style? That way no old code is broken
and you can purposely change a Hash's look if you need to make sure that
this Hash can be interchangeably used with an Array.

Kind regards

    robert

···

In message "Re: Array#index block and rdetect" > on Mon, 20 Sep 2004 11:12:12 +0900, "David A. Black" <dblack@wobblini.net> writes:

Hi --

Hi,

>> * Enumerable#each_index should be removed (yes/no)
>
>There is no Enumerable#each_index -- nothing to remove.

I meant each_with_index.

In that case, yes.

>> * How about other enumerable classes?
>
>I think the idea of every enumerable class having an "index", defined
>as part of that class, is possibly useful. For hashes it could be the
>keys; for arrays, the integer index; for files, the line number. In
>some cases (like index/key for hashes), it might be redundant. But it
>might open up some good possibilities.

The most consistent (but incompatible) change would be:

  * leave Enumerable#each_with_index unchanged.

Question: if "index" is a basic Enumerable thing, why is there no
Enumerable#each_index? (My preference would be to push
#each_with_index down to the individual classes too; but in any case,
I'm curious about it.)

  * make Hash#each as alias of Hash#each_value
  * redefine Hash#each_with_index as alias of Hash#each_pair

Actually it might be better to have Hash#each_with_index yield (value,
key) (like Florian's idea), since the value is the element and the key
is the index. However, calling it "index" instead of "key" then just
becomes arbitrary, and has a "legacy" feel to it.

But this change may break many programs.

The #each change might, but I don't think I've ever seen anyone use
Hash#each_with_index so that probably wouldn't matter.

David

···

On Mon, 20 Sep 2004, Yukihiro Matsumoto wrote:

In message "Re: Array#index block and rdetect" > on Mon, 20 Sep 2004 11:12:12 +0900, "David A. Black" <dblack@wobblini.net> writes:

--
David A. Black
dblack@wobblini.net

Main Entry: enu·mer·a·ble
  Pronunciation: i-'n(y)üm-r&-b&l, -'n(y)ü-m&-
  Function: adjective
  : DENUMERABLE

  Main Entry: de·nu·mer·a·ble
  Pronunciation: di-'n(y)ü-m&-r&-b&l
  Function: adjective
  : capable of being put into one-to-one correspondence
    with the positive integers

So "index" must mean this corresponding integer. I would argue that sets and
hashes are not technically enumerable, because they're elements can not be
accessed as a _function_ of the index, i.e. one-to-one correspondence.

Perhaps separate Collectable and Indexable modules would be preferable.

T.

···

On Monday 20 September 2004 09:52 am, Randy W. Sims wrote:

All enumerable objects don't neccessarilly have a meaningful concept of
an index. Eg. sets, multisets. Enumerable and Indexable are two
different things, though Indexable extends Enumerable.

--
( o _ カラチ (a place in Paki)
// trans.
/ \ transami@runbox.com

I don't give a damn for a man that can only spell a word one way.
-Mark Twain

Hi --

···

On Mon, 20 Sep 2004, Randy W. Sims wrote:

David A. Black wrote:
> Hi --
>
> On Mon, 20 Sep 2004, Yukihiro Matsumoto wrote:
>
>> * How about other enumerable classes?
>
>
> I think the idea of every enumerable class having an "index", defined
> as part of that class, is possibly useful. For hashes it could be the
> keys; for arrays, the integer index; for files, the line number. In
> some cases (like index/key for hashes), it might be redundant. But it
> might open up some good possibilities.
>
> That would mean an enumerable class would have to be able to say:
> "This is how I define 'index'." I'm not sure how that would work.

All enumerable objects don't neccessarilly have a meaningful concept of
an index.

I know. That's why I've been advocating the removal of
Hash#each_with_index for four years :slight_smile:

David

--
David A. Black
dblack@wobblini.net

Hi --

"Yukihiro Matsumoto" <matz@ruby-lang.org> schrieb im Newsbeitrag
news:1095650370.096071.21408.nullmailer@x31.priv.netlab.jp...
> Hi,
>
>
> >> * Enumerable#each_index should be removed (yes/no)
> >
> >There is no Enumerable#each_index -- nothing to remove.
>
> I meant each_with_index.
>
> >> * How about other enumerable classes?
> >
> >I think the idea of every enumerable class having an "index", defined
> >as part of that class, is possibly useful.

Sorry, David, I stongly disagree: IMHO an index does only make sense in a
class that maintains a certain order (such as Array). A Hash does not
have a particular order and thus Enumerable#each_with_index is the
appropriate thing; here the index is valid just for the current iteration
and can be used for printing or whatever. But I would not want to add an
index to a Hash.

Or did you mean to use the hash key as index?

Yes. I certainly didn't mean numerical indexes for hashes; that's the
whole problem (well, part of the problem) with Hash#each_with_index in
the first place. Also, by "defined as part of that class", I meant
defined according to the needs of that class, so that for arrays it
would be integers, for hashes the keys, etc.

That would be a different
story... While that would make sense for Array and Hash I think there are
a lot Enumerables out there that do not correspond easily to associative
storage, for example a Enumerable that emits arbitrary many random numbers
in its #each method.

That problem is already there, in the sense that such an object
already has an #each_with_index method. I'm trying to make sense of
the notion of "index" as part of Enumerable, though it's quite
possible that *not* having it be part of Enumerable would be better --
and then classes could either define index-related methods or not.
(That's what I meant originally about leaving #each_with_index up to
the individual classes, like #each_index.)

> For hashes it could be the
> >keys; for arrays, the integer index; for files, the line number. In
> >some cases (like index/key for hashes), it might be redundant. But it
> >might open up some good possibilities.
>
> The most consistent (but incompatible) change would be:
>
> * leave Enumerable#each_with_index unchanged.
> * make Hash#each as alias of Hash#each_value
> * redefine Hash#each_with_index as alias of Hash#each_pair
>
> But this change may break many programs.

Yeah, that's true. What about a method in Hash that changes method
behavior to the array compatible style? That way no old code is broken
and you can purposely change a Hash's look if you need to make sure that
this Hash can be interchangeably used with an Array.

It's called #to_a :slight_smile: I think that's better than having a switch that
changes behavior. We're going to start hearing a lot of "for
historical reasons..." and "glued on as an afterthought..." otherwise
:slight_smile:

David

···

On Mon, 20 Sep 2004, Robert Klemme wrote:

> In message "Re: Array#index block and rdetect" > > on Mon, 20 Sep 2004 11:12:12 +0900, "David A. Black" > <dblack@wobblini.net> writes:

--
David A. Black
dblack@wobblini.net