ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
From: shevegen@gmail.com
To: ruby-core@ruby-lang.org
Subject: [ruby-core:94433] [Ruby master Feature#16113] Partial application
Date: Mon, 19 Aug 2019 11:11:42 +0000 (UTC)	[thread overview]
Message-ID: <redmine.journal-80858.20190819111141.5347346398a52f2f@ruby-lang.org> (raw)
In-Reply-To: redmine.issue-16113.20190819100716@ruby-lang.org

Issue #16113 has been updated by shevegen (Robert A. Heiler).


Personally I dislike this proposal primarily due to the name alone. I don't think
a method named .m is good in this context.

We do have short named methods here and there, of course, such as "p" or "pp",
but I feel that these cases are simpler, and relate mostly to "output-related
tasks".

To me it is not clear why a method called "m" should signify "partial application".

There are a few other aspects intermingled in the proposal, or comments that 
I think are a bit strange.

For example:

    foo(&some.method(:name)) (as of 2.7, foo(&some.:name))
    Currently disputed "nameless block args": foo { something(@1) } or foo { something(@) } or foo { something(it) }

First, I don't think the second is "disputed", but let's ignore this for
the moment. To me, foo(&some.method(:name)) has little to do with e. g.
foo { method(@1) }. Both syntax-wise and from the functionality; but 
syntax-wise, I actually think that ALL the syntax examples are not hugely
elegant. Neither is the oldschool foo(&:symbol). I use the latter myself,
mostly because it leads to shorter code, but I think it is visually not
as elegant as the longer block variant:

    .each {|foo|
    }

In my opinion, this style is the clearest. Not as short as & but clearer
and cleaner, in my opinion. But I digress.

Another part of the proposal mentioned the "staying true to language's
spirit". I think this is a bit problematic, though. Ruby was always 
multi-paradigm and had influences from different languages. My own opinion
is that ruby's biggest strength is the focus on OOP, but I think this may
depend a lot on how someone may use ruby. My use cases will be different
from what other people use. There is also a lot of ruby code out in the 
wild I would never write, use or want to maintain. :)

Some of these coding styles are, IMO, somewhat orthogonal or opposing to
one another if applied at the same time. But this is admittedly also a
LOT due to the individual preference of the ruby user at hand.

Another aspect that I dislike is that suggestions like this, but also
similar ones, increase the complexity of ruby by a LOT.

Consider this:

    fetch(urls).map(&JSON.:parse.w(symbolize_names: true))

Honestly, I don't even want to have to get my brain to want to 
decipher this. Again, this is up to a personal opinion and preference,
just as people may appreciate a shorter syntax to block parameters
or dislike it - but if possible, I think it would be better to strive
for simplicity rather than build up more and more complexity into
ruby in general.

This is of course only my own personal opinion on that matter.

Note that using a slightly different name other than e. g. w,
may partially alleviate the above problem, but the syntax complexity
and overall complexity may still remain.

IMO I think this is simply for matz to decide how much complexity 
ruby should strive to in general.

This is also, as stated, up to an individual's preference - zverok
loves deeply nested, chained blocks. I prefer them to be much 
much simpler, including syntax. Difficult to unite two somewhat
opposing views on the same topic. :D

----------------------------------------
Feature #16113: Partial application
https://bugs.ruby-lang.org/issues/16113#change-80858

* Author: zverok (Victor Shepelev)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
**Preface:** One of the main "microstructures" of the code we use is chaining methods-with-blocks; and we really love to keep those blocks DRY when they are simple. Currently, for DRY-ing up simple blocks, we have:

* `foo(&:symbol)`
* `foo(&some.method(:name))` (as of 2.7, `foo(&some.:name)`)
* Currently disputed "nameless block args": `foo { something(@1) }` or `foo { something(@) }` or `foo { something(it) }`

**Proposal:** I argue that short and easy-to-remember partial application of blocks and methods can make methods-with-blocks much more pleasant and consistent to write, and continue softly shifting Ruby towards "functional" (while staying true to language's spirit). 

In order to achieve this, I propose method `{Symbol,Method,Proc}#w` (from `with`), which will produce `Proc` with _last_ arguments bound.

Example of usability:

```ruby
# No-shortcuts: fetch something and parse as JSON:
fetch(urls).map { |body| JSON.parse(body) }
# Could be already (2.7+) shortened to:
fetch(urls).map(&JSON.:parse)

# But if you have this:
fetch(urls).map { |body| JSON.parse(body, symbolize_names: true) }
# How to shorten it, to don't repeat body?
# "Nameless block args" answer:
fetch(urls).map { JSON.parse(@1, symbolize_names: true) }
# Partial application answer:
fetch(urls).map(&JSON.:parse.w(symbolize_names: true))
```

I believe that the latter (while can be easily met with usual "hard to understand for a complete novice") provides the added value of producing proper "functional object", that can be stored in variables and constants, and generally lead to new approaches to writing Ruby code. 

Another example:
```ruby
(6..11).map(&:**.w(2)).map(&:clamp.w(20, 50))
# => [36, 49, 50, 50, 50, 50]
```

Reference implementation:
```ruby
class Symbol
  def w(*args)
    proc { |receiver, *rest| receiver.send(self, *rest, *args) }
  end
end

class Method
  def w(*args)
    proc { |receiver, *rest| self.call(receiver, *rest, *args) }
  end
end

class Proc
  def w(*args)
    prc = self
    proc { |*rest| prc.call(*rest, *args) }
  end
end
```



-- 
https://bugs.ruby-lang.org/

  parent reply	other threads:[~2019-08-19 11:11 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <redmine.issue-16113.20190819100716@ruby-lang.org>
2019-08-19 10:07 ` [ruby-core:94432] [Ruby master Feature#16113] Partial application zverok.offline
2019-08-19 11:11 ` shevegen [this message]
2019-08-19 12:23 ` [ruby-core:94434] " hanmac
2019-08-20  1:28 ` [ruby-core:94440] " shannonskipper
2019-08-23 23:51 ` [ruby-core:94517] " shannonskipper
2019-08-24 10:57 ` [ruby-core:94529] " zverok.offline

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-80858.20190819111141.5347346398a52f2f@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).