Project

General

Profile

Actions

Feature #7994

closed

Make iterators pass an implicit named parameter `iteration` to the executed block

Added by alexeymuranov (Alexey Muranov) about 11 years ago. Updated about 11 years ago.

Status:
Rejected
Assignee:
-
Target version:
-
[ruby-core:53072]

Description

=begin
I think it would be nice to be able to write something like this:

items.each do |item|
unless iteration.first?
# do something that is not applicable to the first iteration
end
# do whatever is to be done to all items
end
=end

Updated by alexeymuranov (Alexey Muranov) about 11 years ago

=begin
As a use case, i wanted to create a pagination navigation element on a web page in ((Haml)) template. What i ended up with looks redundant to me. With the suggested feature, i would be able to do:

%nav.pagination
- [page_ranges_before, page_ranges_after].each do |page_ranges|
- unless iteration.first?
%span.page.active
= active_page
- page_ranges.each do |range|
- unless iteration.first?
%span.ellipsis

- range.each do |page|
%button.page{ :type => :submit, :name => :page, :value => page }
= page

In other words, this would give an "imperative" solution to "Loop and a Half Problem".
=end

Updated by regularfry (Alex Young) about 11 years ago

On 01/03/13 15:21, alexeymuranov (Alexey Muranov) wrote:

Issue #7994 has been reported by alexeymuranov (Alexey Muranov).

What advantages does this have over:

items.drop(1).each do |item|

or

items[1..-1].each do |item|

or to invert it:

items.first.tap do |item|

?

--
Alex


Feature #7994: Make iterators pass an implicit named parameter iteration to the executed block
https://bugs.ruby-lang.org/issues/7994

Author: alexeymuranov (Alexey Muranov)
Status: Open
Priority: Normal
Assignee:
Category:
Target version:

=begin
I think it would be nice to be able to write something like this:

items.each do |item|
unless iteration.first?
# do something that is not applicable to the first iteration
end
# do whatever is to be done to all items
end
=end

Updated by alexeymuranov (Alexey Muranov) about 11 years ago

regularfry (Alex Young) wrote:

On 01/03/13 15:21, alexeymuranov (Alexey Muranov) wrote:

Issue #7994 has been reported by alexeymuranov (Alexey Muranov).

What advantages does this have over:

items.drop(1).each do |item|

or

items[1..-1].each do |item|

or to invert it:

items.first.tap do |item|

?

Sorry, i didn't understand, how do you plan to use this?

Updated by matz (Yukihiro Matsumoto) about 11 years ago

  • Status changed from Open to Rejected

Nice idea.

But I reject the idea for Ruby for two reasons:

  • I personally don't like implicit parameters
  • That might cause incompatibility by conflicting with existing local variable name

Maybe good for a new language without existing set of programs.

Matz.

Updated by alexeymuranov (Alexey Muranov) about 11 years ago

=begin
Ok, then i make a last try: what about adding it in the end of parameter list as an optional parameter?

items.each do |item, iteration|
unless iteration.first?
# do something that is not applicable to the first iteration
end

do whatever is to be done to all items

end
=end

Updated by marcandre (Marc-Andre Lafortune) about 11 years ago

Please think about the number of incompatibilities this would bring... not all enumerables are sequences of single items.

Just use each_with_index and index.zero? instead of iteration.first?

Updated by alexeymuranov (Alexey Muranov) about 11 years ago

Marc-Andre, thanks for the idea, i did not realize that each_with_index works with all enumerables.

However i was hoping that something like unless iteration.first? could be some day optimized away by a compiler to not check on every iteration. I also do not see right away an incompatibility introduced by my second proposal (about the original one you are right).

Update: well, maybe there is no real advantage compared to each_with_index and index.zero?, i will use it.

Updated by marcandre (Marc-Andre Lafortune) about 11 years ago

I also do not see right away an incompatibility introduced by my second proposal (about the original one you are right).

#before
[[1,2]].each{|a, b| p a, b} # => 1, then 2

after

[[1,2]].each{|a, b| p a, b} # => [1, 2], then<#your iteration object>

BTW, all hashes would be affected like this!

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0