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:95026] [Ruby master Feature#16147] List Comprehensions in Ruby
Date: Sat, 21 Sep 2019 21:46:11 +0000 (UTC)	[thread overview]
Message-ID: <redmine.journal-81654.20190921214610.51bfcbc00803942a@ruby-lang.org> (raw)
In-Reply-To: redmine.issue-16147.20190906103822@ruby-lang.org

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


In reiteration of my main points, Ruby is a dynamic multi-paradigm language which should when possible embrace a variety of modes to achieve the same result.    

SO what would be the benefits of list comprehension in Ruby and what would it look like? 

1. Creating an array with only [] square brackets is fun and makes intuitive sense for beginners
2. "For .. in .." syntax is succinct, flexible, and has a good spoken rhythm/easy to verbalize
3. Easier for users of other languages to assimilate into Ruby as they don't need to know all our enumerable library right away.

Ruby already has functioning list comprehension syntax but it could be optimized:

[for x in 1..10 do x**2 if x%2==0 end] # this is Ruby but we can't capture the value 
[for x in 1..10; x**2 if x.even? end] # since 2.7 Ruby it would also be better if it called Filter_Map under the hood instead of each

# proposal to use some syntax to use a splat or additional indicator to allow a smoother shorthand for list comprehensions

[for x in 1..10 do x**2 if x.even? end] #=> 1..10  (normal Ruby)

# below we propose a syntax in which we splat the for loop to return the stored result not the caller

[*for x in 1..10 do x**2 if x.even? end] #=> [4, 16, 36, 64, 100] 

# under the hood this could be syntactic sugar for 

(1..10).filter_map{@1**2 if @1.even?}  #=> [4, 16, 36, 64, 100] 

# the key differences to notice. although there are less keystrokes with filter_map, you had to know the method name, and the exact arrangement of parentheses and curly braces, and whether to use a block or numbered parameter. If you decided to use pre-2.7 ruby you would have said:

(1..10).filter_map{|x|x**2 if x.even?}

vs with proposed list syntax:

[*for x in 1..10; x**2 if x.even? end] 

# I think both could and should be standard ruby syntax of achieving the same result of quickly generating a filter mapped array of the given elements.







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

* 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-21 21:46 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 ` [ruby-core:94807] " sammomichael
2019-09-21 21:46 ` sammomichael [this message]
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-81654.20190921214610.51bfcbc00803942a@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).