ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
From: sammomichael@gmail.com
To: ruby-core@ruby-lang.org
Subject: [ruby-core:94807] [Ruby master Feature#16147] List Comprehensions in Ruby
Date: Fri, 06 Sep 2019 17:28:49 +0000 (UTC)	[thread overview]
Message-ID: <redmine.journal-81428.20190906172849.29a928842aee00d5@ruby-lang.org> (raw)
In-Reply-To: redmine.issue-16147.20190906103822@ruby-lang.org

Issue #16147 has been updated by sammomichael (Samuel Michael).


sammomichael (Samuel Michael) wrote:
> shevegen (Robert A. Heiler) wrote:
> > 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.

Yes it is real, and yes, I should have changed it to be a feature and not a bug

> > 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).

I use it too, that is why I said "rarely" rather than never or fully deprecated. It has to be admitted it is less common in Ruby vernacular than in other languages. Also I never said intended that it break compatibility with earlier versions or that we wouldn't still be able to use for loop, rather to extend those keywords for an additional use of generating a list comprehension to give an alternate option to filter_map. Obviously filter_mapping was considered important enough to add a enumerable specifically for that, I am suggesting we offering an additional and alternate notation using [for..in] inside of brackets, obviously the final syntax would depend on the parser and how it would be easiest to modify without breaking compatibility with previous versions. 

> > 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.

A few years is fine by me, IF it were to be approved, that is a reasonable trajectory...

> > I assume that one reason why a for loop exists, and also other aliases,
> > such as .map <- -> .collect, and as to why ruby is multi-paradigm, was
> > that matz wanted to make ruby convenient to use for people with different
> > background. Ruby itself has incorporated useful ideas and paradigms from
> > other languages too. (My personal opinion is that, by far, the strongest
> > point of ruby, in regards to philosophies, is its OOP-centric nature, but
> > you may disagree. People use ruby in different ways, though. Some of the
> > ruby code looks quite alien; and matz has said sometimes, in the past,
> > that he was sometimes surprised to see how people use ruby.)
> > 
> > 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.

This is the lambda used to evaluate a list comprehension string and return an array in the examples below it.
> > 
> > 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.
> 

> 
> [[https://en.wikipedia.org/wiki/Comparison_of_programming_languages_(list_comprehension)]]
> 
> Dan0042 (Daniel DeLorme) wrote:
> > What's wrong with existing well-established object-oriented ruby idioms?
> > 
> > ```ruby
> > (1..10).to_a
> > (1..10).select(&:even?)
> > (1..10).select(&:even?).map{ |x| x**2 }
> > (1..10).map{ |x| x**2 }
> > ```
> > 
> > or in ruby 2.7:
> > 
> > ```ruby
> > (1..10).to_a
> > (1..10).select(&:even?)
> > (1..10).select(&:even?).map{ _0**2 }
> > (1..10).map{ _0**2 }
> > ```
> > 
> > or if #16120 was accepted ;-D
> > 
> > ```ruby
> > (1..10).to_a
> > (1..10).select{.even?}
> > (1..10).select{.even?}.map{.**2}
> > (1..10).map{.**2}
> > ```



----------------------------------------
Feature #16147: List Comprehensions in Ruby
https://bugs.ruby-lang.org/issues/16147#change-81428

* 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/

  parent reply	other threads:[~2019-09-06 17:28 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <redmine.issue-16147.20190906103822@ruby-lang.org>
2019-09-06 10:38 ` [ruby-core:94796] [Ruby master Bug#16147] List Comprehensions in Ruby sammomichael
2019-09-06 13:18 ` [ruby-core:94799] " daniel
2019-09-06 14:06 ` [ruby-core:94800] " shevegen
2019-09-06 16:41 ` [ruby-core:94804] [Ruby master Feature#16147] " sammomichael
2019-09-06 16:44 ` [ruby-core:94805] " sammomichael
2019-09-06 17:28 ` sammomichael [this message]
2019-09-21 21:46 ` [ruby-core:95026] " sammomichael
2019-09-22 10:09 ` [ruby-core:95031] " nobu
2019-09-22 16:47 ` [ruby-core:95035] " eregontp
2019-09-23 21:16 ` [ruby-core:95047] " sammomichael
2019-09-23 22:06 ` [ruby-core:95049] " sammomichael
2019-09-29  2:26 ` [ruby-core:95144] " sammomichael
2019-10-03 17:57 ` [ruby-core:95200] " sammomichael
2019-10-04  0:41 ` [ruby-core:95213] " sammomichael
2019-10-07 13:01 ` [ruby-core:95259] " sammomichael
2019-10-07 18:35 ` [ruby-core:95262] " sammomichael

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.ruby-lang.org/en/community/mailing-lists/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=redmine.journal-81428.20190906172849.29a928842aee00d5@ruby-lang.org \
    --to=ruby-core@ruby-lang.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).