Project

General

Profile

Feature #6073

Proposal of extending syntax of for loop

Added by shouichi (Shouichi KAMIYA) over 7 years ago. Updated over 7 years ago.

Status:
Rejected
Priority:
Normal
Target version:
-
[ruby-core:42851]

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

0001-extend-for-loop-syntax.patch (6.45 KB) 0001-extend-for-loop-syntax.patch shouichi (Shouichi KAMIYA), 02/24/2012 02:19 PM

History

Updated by shugo (Shugo Maeda) over 7 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}"
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

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 x*2 + 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|
x*2 + 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 7 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 x*2 + 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|
x*2 + 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 7 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 7 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
...
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.

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 7 years ago

  • Status changed from Open to Assigned
  • Assignee set to matz (Yukihiro Matsumoto)

Updated by matz (Yukihiro Matsumoto) over 7 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 7 years ago

  • Status changed from Assigned to Rejected

Also available in: Atom PDF