[ruby-core:95031] [Ruby master Feature#16147] List Comprehensions in Ruby
From:
nobu@...
Date:
2019-09-22 10:09:06 UTC
List:
ruby-core #95031
Issue #16147 has been updated by nobu (Nobuyoshi Nakada).
sammomichael (Samuel Michael) wrote:
> ```ruby
> [for x in 1..10 do x**2 if x.even? end] #=> 1..10 (normal Ruby)
> ```
It is an `Array` from 0 to 10 now.
> below we propose a syntax in which we splat the for loop to return the stored result not the caller
>
> ```ruby
> [*for x in 1..10 do x**2 if x.even? end] #=> [4, 16, 36, 64, 100]
> ```
Obviously the latter result conflicts with the former.
Which result do you expect from the following code?
```ruby
a = for x in 1..10 do x**2 if x.even? end
[*a] #=> ????
[*(for x in 1..10 do x**2 if x.even? end)] #=> ????
```
----------------------------------------
Feature #16147: List Comprehensions in Ruby
https://bugs.ruby-lang.org/issues/16147#change-81661
* Author: sammomichael (Samuel Michael)
* Status: Open
* Priority: Normal
* Assignee:
* Target version:
----------------------------------------
## List comprehensions are present in many languages and programmers are quite fond of their simplicity and power. Add to that the fact that Ruby has a for...in loop that is rarely used but could possibly be repurposed.
### Currently we can already do a hack like this to make Ruby support list comprehension syntax:
``` ruby
S = [for x in 0...9 do $* << x*2 if x.even? end, $*][1]
# [0, 4, 8, 12, 16]
```
Still, it would be far nicer if the for...in loop would return the desired array automatically, this is one way to approach that taking advantage of lambda bracket invocation syntax:
``` ruby
c = -> x do $*.clear
if x['if'] && x[0] != 'f' .
y = x[0...x.index('for')]
x = x[x.index('for')..-1]
(x.insert(x.index(x.split[3]) + x.split[3].length, " do $* << #{y}")
x.insert(x.length, "end; $*")
eval(x)
$*)
elsif x['if'] && x[0] == 'f'
(x.insert(x.index(x.split[3]) + x.split[3].length, " do $* << x")
x.insert(x.length, "end; $*")
eval(x)
$*)
elsif !x['if'] && x[0] != 'f'
y = x[0...x.index('for')]
x = x[x.index('for')..-1]
(x.insert(x.index(x.split[3]) + x.split[3].length, " do $* << #{y}")
x.insert(x.length, "end; $*")
eval(x)
$*)
else
eval(x.split[3]).to_a
end
end
```
so basically we are converting a string to proper ruby syntax for loop then we can use python syntax in a string to do:
``` ruby
c['for x in 1..10']
c['for x in 1..10 if x.even?']
c['x**2 for x in 1..10 if x.even?']
c['x**2 for x in 1..10']
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# [2, 4, 6, 8, 10]
# [4, 16, 36, 64, 100]
# [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
```
--
https://bugs.ruby-lang.org/
Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>