Feature #6073
closedProposal of extending syntax of for loop
Description
Hi,
I propose to extend syntax of for loop which allows us to write multiple loop with guard easily.
This extension is inspired by Scala. Here is a example
for i in 1..4 when i % 2 == 0
j in 5..8 when j % 4 == 0
puts "#{i}, #{j}"
end
Above code is same as following code.
for i in 1..4
if i % 2 == 0
for j in 5..8
if j % 4 == 0
puts "#{i}, #{j}"
end
end
end
end
I already implemented this syntax and attached a patch.
What do you think about this syntax guys?
Thank you,
Shouichi
Files
Updated by shouichi (Shouichi Kamiya) over 12 years ago
Oh and this is my fork on Github.
https://github.com/shouichi/ruby
Updated by shugo (Shugo Maeda) over 12 years ago
Hi,
Shouichi KAMIYA wrote:
I propose to extend syntax of for loop which allows us to write multiple loop with guard easily.
This extension is inspired by Scala. Here is a example
I'm interested in your idea.
Feature #6070 was preparation for the same proposal.¶
for i in 1..4 when i % 2 == 0
j in 5..8 when j % 4 == 0
puts "#{i}, #{j}"
endAbove code is same as following code.
for i in 1..4
if i % 2 == 0
for j in 5..8
if j % 4 == 0
puts "#{i}, #{j}"
end
end
end
end
Scala's for expression is more powerful.
If yield in used in a for expression, nested loop is converted to a combination of map/flatMap/withFilter.
For example, the following code:
for z in (1..Float::INFINITY).lazy
x in 1..z
y in x..z
when x2 + y2 == z**2
yield [x, y, z]
end
is equivalent to the following code:
(1..Float::INFINITY).lazy.flat_map {|z|
(1..z).flat_map {|x|
(x..z).select {|y|
x2 + y2 == z**2
}.map {|y|
[x, y, z]
}
}
}
Please note that yield is already take in Ruby, so we need different Syntax.
What do you think of that feature?
Updated by shouichi (Shouichi Kamiya) over 12 years ago
Hi,
Thank you for your quick response.
Shugo Maeda wrote:
Scala's for expression is more powerful.
If yield in used in a for expression, nested loop is converted to a combination of map/flatMap/withFilter.For example, the following code:
for z in (1..Float::INFINITY).lazy
x in 1..z
y in x..z
when x2 + y2 == z**2
yield [x, y, z]
endis equivalent to the following code:
(1..Float::INFINITY).lazy.flat_map {|z|
(1..z).flat_map {|x|
(x..z).select {|y|
x2 + y2 == z**2
}.map {|y|
[x, y, z]
}
}
}Please note that yield is already take in Ruby, so we need different Syntax.
What do you think of that feature?
Yes Scala's yield feature in for loop is powerful and it'll be good if we can use that feature in Ruby.
However, it seems like that for loop feature will be pretty different from current for loop feature right?
Do you think it's a good idea?
Updated by shugo (Shugo Maeda) over 12 years ago
Hi,
Shouichi KAMIYA wrote:
Yes Scala's yield feature in for loop is powerful and it'll be good if we can use that feature in Ruby.
However, it seems like that for loop feature will be pretty different from current for loop feature right?
Do you think it's a good idea?
I think it's good to support both each and map/flat_map.
It may be possible to use yield instead of do/;/newline when using map/flat_map.
use each¶
for i in obj
...
end
use map; yield is not a block call¶
for i in obj yield
end
use each; yield is a block call¶
for i in obj
yield i
end
for i in obj do yield i end
for i in obj; yield i end
It might be too confusing, though.
Updated by shouichi (Shouichi Kamiya) over 12 years ago
Hi,
Shugo Maeda wrote:
I think it's good to support both each and map/flat_map.
It may be possible to use yield instead of do/;/newline when using map/flat_map.use each¶
for i in obj
...
enduse map; yield is not a block call¶
for i in obj yield
enduse each; yield is a block call¶
for i in obj
yield i
end
for i in obj do yield i end
for i in obj; yield i endIt might be too confusing, though.
Though supporting both each and map/flat_map makes code simpler but,
I'm not completely sure if it's a good idea. I think we've got to
get more people involved and discuss.
About the syntax, I don't come up with better syntax right now.
Updated by mame (Yusuke Endoh) over 12 years ago
- Status changed from Open to Assigned
- Assignee set to matz (Yukihiro Matsumoto)
Updated by matz (Yukihiro Matsumoto) over 12 years ago
The current for statement does not do any map-like work. Under such behavior, extending for statement might not have enough benefit worth adding complexity. So, I have to reject this proposal for now.
Matz.
Updated by matz (Yukihiro Matsumoto) over 12 years ago
- Status changed from Assigned to Rejected