[ruby-core:94800] [Ruby master Bug#16147] List Comprehensions in Ruby
From:
shevegen@...
Date:
2019-09-06 14:06:48 UTC
List:
ruby-core #94800
Issue #16147 has been updated by shevegen (Robert A. Heiler).
I am not sure how serious the proposal is; but I will assume, for sake of simplicity, that
the suggestion is "real". First a minor comment - it should be filed under "features"
rather than "bug", since it is a suggestion for a change, rather than a bug, in my
opinion; but this is an aside.
Next, I will briefly comment on this statement:
> Ruby has a for...in loop that is rarely used but could possibly be repurposed.
Let's for a moment briefly ignore whether people use the for loop or not (they
actually do; but let's ignore this for the moment).
Matz has said several times before that the transition from ruby 2.0 (2.x) to
3.0 will not be anywhere near as "problematic" as 1.8.x to 2.x was. So for
this reason alone, I believe that IF this were to be approved, it would have
to come way after 3.0, possibly 3.1 at earliest or even after that - so I
guess a few years from this point. (Ruby 3.0 will be released next year,
so we don't have that much time really; 15 months or so, give or take.)
You also wrote that the "for" loop is rarely used. Well, this is partially
true. I myself use almost exclusively .each and loop {}. But - I know of
other people who use "for" quite a bit, in particular when you have like
a matrix and iterate through it; in this case I can understand that a for
loop is used, even if I personally prefer .each and loop {}. So I am not
sure if your general comment is correct.
The philosophy of "more than one way to do it" also means that the "lesser
ways", that is, used more sporadically, will not necessarily be removed
merely because most ruby users may not use it. There are many other examples
here, such as @@class_variables. I don't use the latter myself, and would
rather see them go, but there are others who use class variables just fine,
even in the ruby code base (the recent rewrite of irb for example has some
class variables). So I think this is not a good metric in regards to
"adoption". But this is also not the main issue here.
The next comment to make .... hmm. List comprehensions remind me of python.
I use both ruby and python fine, but python feels a bit strange, in many
ways. Including python's OOP way (I absolutely hate explicit self by far
the most; mandatory indent is so minor compared to having to pass self
to every function/method in a class). IMO, ruby's way to filter is a
LOT more natural and easier to both understand and read than are python's
list comprehensions.
Granted, you were not confining your suggestion to python alone, so there
may be other list comprehensions that are succinct and elegant. I don't
really see them in the proposal per se, but perhaps they exist; I don't
know. I think that ruby's existing ways are very succinct, though.
Ultimately I don't think ruby needs list comprehensions, most definitely
not the pythonic list comprehensions.
You gave an example as-is in ruby:
S = [for x in 0...9 do $* << x*2 if x.even? end, $*][1] # [0, 4, 8, 12, 16]
Off the top of my mind, this would be better, in my opinion:
(0..16).select {|entry| entry % 4 == 0} => [0, 4, 8, 12, 16]
I am sure there are many other ways (Dan0042 provided more examples),
but IMO, the latter is so much more readable than the first variant,
so I don't think there is any real improvement.
You gave more examples such as:
c = -> x do $*.clear
if x['if'] && x[0] != 'f' .
I don't really know what this is. It almost looks as if there was an
attempt made to make this less readable.
Anyway you only have to convince matz, but I am not sure if the
proposal as it presently is has a good chance for implementation;
there seem to be too many trade offs associated with it in its
current form. Or perhaps there is some additional reasoning or
advantage missing; I am not quite seeing the improvement or the
stated need, to be honest.
Best luck to you nonetheless.
----------------------------------------
Bug #16147: List Comprehensions in Ruby
https://bugs.ruby-lang.org/issues/16147#change-81421
* Author: sammomichael (Samuel Michael)
* Status: Open
* Priority: Normal
* Assignee:
* Target version:
* ruby -v:
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN
----------------------------------------
## 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>