ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
From: Recursive Madman <recursive.madman@gmx.de>
To: Ruby developers <ruby-core@ruby-lang.org>
Subject: [ruby-core:73928] Re: [Ruby trunk Feature#11262] Make more objects behave like "Functions"
Date: Mon, 22 Feb 2016 17:53:40 +0100	[thread overview]
Message-ID: <56CB3D14.5010006@gmx.de> (raw)
In-Reply-To: <CAE3kKutTLEMxJDwUa10rfLM7fqdJPumhbg_6vsYPx+hyx_9EVQ@mail.gmail.com>


[-- Attachment #1.1: Type: text/plain, Size: 7453 bytes --]

@hanlyu: it's not widely known, but instead of `something.call()` you 
can also write just `something.()` which feels a lot less verbose.


On 02/22/2016 05:50 PM, Hanlyu Sarang wrote:
> This is one of the few cases where JavaScript is superior to ruby. You 
> can have just about anything and append parentheses to it and presto, 
> an invocation will be attempted "just_about_anything(...)". 
> JavaScript's approach is both powerful and clean. Ruby's approach is 
> also powerful, but it is complicated. I usually choose between 
> "->myarg{...}" or "myobj.method :mymethod". I also have to use 
> ".call(...), a complaint which is really nitpicking. [If I love 
> JavaScript so much, why don't I just use JavaScript instead of Ruby?]
>
> But I'm also comparing Apples and Oranges, which isn't fair. 
> JavaScript doesn't have Blocks, nor does it have a compact poetry 
> mode. I don't think there is much that is practical which can be done 
> to clean up Ruby function calling syntax. I appreciate stabby, which 
> is really very nice.
>
>
> On Mon, Feb 22, 2016 at 9:27 AM, <Ruby-Lang@joergwmittag.de 
> <mailto:Ruby-Lang@joergwmittag.de>> wrote:
>
>     Issue #11262 has been updated by Jörg W Mittag.
>
>     Project changed from CommonRuby to Ruby trunk
>     Description updated
>
>     ----------------------------------------
>     Feature #11262: Make more objects behave like "Functions"
>     https://bugs.ruby-lang.org/issues/11262#change-57075
>
>     * Author: Jörg W Mittag
>     * Status: Open
>     * Priority: Normal
>     * Assignee:
>     ----------------------------------------
>     # What is a Function?
>
>     In Ruby, we have the [`Proc`](http://ruby-doc.org/core/Proc.html)
>     class to represent objects which are "function-like". But, in true
>     object-oriented / duck-typing fashion, an object doesn't actually
>     have to be an instance of `Proc` in order to be treated as a
>     function, it only needs to respond to
>     [`call`](http://ruby-doc.org/core/Proc.html#method-i-call). For
>     cases, where a `Proc` instance is absolutely required (mostly, the
>     `&` unary prefix ampersand "make-me-a-block" operator), there is
>     the
>     [`to_proc`](http://ruby-doc.org/core/Proc.html#method-i-to_proc)
>     conversion.
>
>     So, in short: if an object wants to be a function, it **MUST**
>     respond to `call`, and **SHOULD** also respond to `to_proc`.
>
>     There are some objects in Ruby that *could* be seen as functions,
>     but currently don't respond to `call` or `to_proc`:
>
>     # [`Array`](http://ruby-doc.org/core/Array.html) as mapping
>
>     An array is a mapping from indices to elements. "Mapping" is just
>     a different word for (partial) function, though! I propose, that
>     `Array` should implement `call` and `to_proc` in the following manner:
>
>     ~~~ruby
>     class Array
>       alias_method :call, :[]
>
>       def to_proc
>         method(:call).to_proc
>       end
>     end
>     ~~~
>
>     # [`Hash`](http://ruby-doc.org/core/Hash.html) as mapping
>
>     A hash is a mapping from keys to values. I propose, that `Hash`
>     should implement `call` and `to_proc` in the following manner:
>
>     ~~~ruby
>     class Hash
>       alias_method :call, :[]
>
>       def to_proc
>         method(:call).to_proc
>       end
>     end
>     ~~~
>
>     # `Set` as predicate
>
>     A set is a mapping from values to booleans, i.e. a set is the same
>     as its `include?` predicate. This would mean, for example, that I
>     can pass a `Set` as a predicate to methods like
>     [`Enumerable#select`](http://ruby-doc.org/core/Enumerable.html#method-i-select).
>     I propose, that `Set` should implement `call` and `to_proc` in the
>     following manner:
>
>     ~~~ruby
>     require 'set'
>
>     class Set
>       alias_method :call, :include?
>
>       def to_proc
>         method(:call).to_proc
>       end
>     end
>     ~~~
>
>     I believe that these three additions are worthwhile and fairly
>     uncontroversial. They match with the way arrays, maps and
>     especially sets are treated in mathematics and in other
>     programming languages. E.g. in both
>     [Clojure](http://clojure.org/data_structures#Data%20Structures-Maps%20(IPersistentMap)
>     <http://clojure.org/data_structures#Data%20Structures-Maps%20%28IPersistentMap%29>)
>     and
>     [Scala](http://scala-lang.org/api/current/#scala.collection.Seq),
>     arrays, sets and maps are functions and use function application
>     syntax for accessing values. Scala doesn't even have indexing syntax.
>
>     Here are some potential use cases:
>
>     ~~~ruby
>     numbers_to_words = %w[zero one two three four five six seven eight
>     nine ten eleven twelve]
>
>     [4, 7, 1, 0, 8].map(&numbers_to_words)
>     # => ['four', 'seven', 'one', 'zero', 'eight']
>
>
>     allowed_languages = Set[:ruby, :python, :scala, :scheme]
>
>     %i[ruby c cplusplus scala java perl].select(&allowed_languages)
>     # => [:ruby, :scala]
>     ~~~
>
>     Here is a more "wild" proposal that is much more controversial. I
>     don't actually propose adding this to Ruby, but I will mention it
>     here as food for thought:
>
>     # [`Class`](http://ruby-doc.org/core/Class.html) as factory
>
>     If you squint your eyes, tilt your head sideways and look at it
>     juuuuuuust right, a class is a factory for objects. In other
>     words, it is a function from constructor arguments to instances:
>
>     ~~~ruby
>     class Class
>       alias_method :call, :new
>
>       def to_proc
>         method(:call).to_proc
>       end
>     end
>     ~~~
>
>     Example:
>
>     ~~~ruby
>     class Person
>       def initialize(name)
>         @name = name
>       end
>     end
>
>     %w[matz ko1 charlie].map(&Person)
>     # => [#<Person:0xdeadbeef481523 @name="matz">,
>     #<Person:0xdeadbeef815234 @name="ko1">, #<Person:0xdeadbeef152342
>     @name="charlie">]
>     ~~~
>
>     # Incompatibilities
>
>     This proposal conflicts with #10829, which proposes to use
>     `Array#to_proc` for a completely different purpose.
>
>     I believe that having `Array`s behave as functions from indices to
>     elements is natural, unsurprising, and well in line with both
>     mathematics and other languages.
>
>     ---
>
>     # Related
>
>     The code duplication encountered here suggests refactoring to
>     extract two new mixins in the Ruby core library:
>
>     ~~~ruby
>     module Callable
>       def to_proc
>         method(:call).to_proc
>       end
>     end
>
>     module Indexable
>       alias_method :call, :[]
>     end
>     ~~~
>
>     However, this is out of scope of this discussion and *not* part of
>     this particular feature proposal.
>
>     ---
>
>     [NOTE: I originally posted this in project:common-ruby, which
>     according to [[common-ruby:|its wiki]] is "The official place to
>     submit feature proposal for Ruby" but from my observation, almost
>     all Ruby feature requests actually get filed at project:ruby-trunk.]
>
>
>
>     --
>     https://bugs.ruby-lang.org/
>
>     Unsubscribe: <mailto:ruby-core-request@ruby-lang.org
>     <mailto:ruby-core-request@ruby-lang.org>?subject=unsubscribe>
>     <http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>
>
>
>
>
> Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
> <http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>


[-- Attachment #1.2: Type: text/html, Size: 12962 bytes --]

[-- Attachment #2: Type: text/plain, Size: 138 bytes --]


Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>

  reply	other threads:[~2016-02-22 16:18 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <redmine.issue-11262.20150615115504@ruby-lang.org>
2015-06-15 11:55 ` [ruby-core:69590] [CommonRuby - Feature #11262] [Open] Make more objects behave like "Functions" JoergWMittag+Ruby-Lang
2015-07-09  5:10 ` [ruby-core:69906] [CommonRuby - Feature #11262] " 2851820660
2016-02-22 15:27 ` [ruby-core:73919] [Ruby trunk Feature#11262] " Ruby-Lang
2016-02-22 16:50   ` [ruby-core:73927] " Hanlyu Sarang
2016-02-22 16:53     ` Recursive Madman [this message]
2016-02-22 15:46 ` [ruby-core:73922] " zverok.offline
2016-02-23  0:55 ` [ruby-core:73939] " Ruby-Lang
2016-02-23  0:58 ` [ruby-core:73940] " Ruby-Lang
2016-06-24  8:40 ` [ruby-core:76136] " Ruby-Lang
2016-06-24  8:43 ` [ruby-core:76137] " Ruby-Lang

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=56CB3D14.5010006@gmx.de \
    --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).