ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
From: keithrbennett@gmail.com
To: ruby-core@ruby-lang.org
Subject: [ruby-core:71383] [Ruby trunk - Feature #11665] Support nested functions for better code organization
Date: Sat, 07 Nov 2015 21:17:52 +0000	[thread overview]
Message-ID: <redmine.journal-54754.20151107211751.4bd9c2ff0188d368@ruby-lang.org> (raw)
In-Reply-To: redmine.issue-11665.20151107211735@ruby-lang.org

Issue #11665 has been updated by Keith Bennett.

Tracker changed from Bug to Feature

----------------------------------------
Feature #11665: Support nested functions for better code organization
https://bugs.ruby-lang.org/issues/11665#change-54754

* Author: Keith Bennett
* Status: Open
* Priority: Normal
* Assignee: 
----------------------------------------
The wisdom of using local variables has been internalized in all of us from the beginning of our software careers.  If we need a variable referring to data that is used only in a single method, we create a local variable for it.

Yet if it is logic to which we need to refer, we make it an instance method instead.

In my opinion, this is inconsistent and unfortunate. The result is a bloated set of instance methods that the reader must wade through to mentally parse the class.  The fact that some of these methods are used only by one other method is never communicated by the code; the reader has to discover that for him/herself.

The number of possible interactions among the instance methods is one of many measures of our software's complexity.  The number of possible instance method interactions is <code>(method_count * (method_count) - 1)</code>.  Using this formula, a class with 10 methods will have a complexity of 90.  If 4 of those methods are used by only 1 other method, and we could move them inside those methods, the complexity would plummet to 30 <code>(6 * (6 - 1))</code>, a third of the original amount!

While it is possible to extract subsets of these methods into new smaller classes, this is not always practical, especially in the case of methods called only by the constructor.

Fortunately, we do have lambdas in Ruby, so I will sometimes create lambdas inside methods for this purpose.  However, lambdas are not as isolated as methods, in that they can access and modify local variables previously defined outside their scope.  Furthermore, the lambdas can be passed elsewhere in the program and modify those locals from afar! So using methods would be cleaner and safer.

Another weakness of using lambdas for this purpose is that, unlike methods that are created at interpret time, lambdas are objects created at runtime -- so if a method creating 2 lambdas is called a million times in a loop, you'll need to create and garbage collect another 2 million objects. (This can be circumvented by defining the lambdas as class constants or assigning them to instance variables, but then they might as well be instance methods.)

I realize that implementing this feature would be a substantial undertaking and may not be feasible at this time. That said, I think it would be useful to discuss this now so we might benefit from its implementation someday.

* * * *

(Much of this content is communicated in my talk on Ruby lambdas; slide show is at <a href="https://speakerdeck.com/keithrbennett/ruby-lambdas-functional-conf-bangalore-oct-2014">https://speakerdeck.com/keithrbennett/ruby-lambdas-functional-conf-bangalore-oct-2014</a> and YouTube video of the presentation at FunctionalConf in Bangalore at <a href="https://www.youtube.com/watch?v=hyRgf6Qc5pw">https://www.youtube.com/watch?v=hyRgf6Qc5pw</a>.)

Also, this post is also posted as a blog article at http://www.bbs-software.com/blog/2015/11/07/the-case-for-nested-methods-in-ruby/.



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

  parent reply	other threads:[~2015-11-07 20:48 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <redmine.issue-11665.20151107211735@ruby-lang.org>
2015-11-07 21:17 ` [ruby-core:71382] [Ruby trunk - Bug #11665] [Open] Support nested functions for better code organization keithrbennett
2015-11-07 21:17 ` keithrbennett [this message]
2015-11-09  6:43 ` [ruby-core:71395] [Ruby trunk - Feature #11665] " hanmac
2015-11-09  7:37 ` [ruby-core:71400] " matz
2015-11-09  7:37 ` [ruby-core:71401] " ko1
2015-11-09 12:06 ` [ruby-core:71414] " nobu
2015-11-09 12:24 ` [ruby-core:71415] " mame
2015-11-10  6:42 ` [ruby-core:71429] " hanmac
2015-11-11 13:21 ` [ruby-core:71449] " 6ftdan
2015-11-15  1:17 ` [ruby-core:71488] " keithrbennett
2015-11-30 21:27 ` [ruby-core:71765] " mame
2016-11-16 15:06 ` [ruby-core:78175] [Ruby trunk Feature#11665] " zotherstupidguy

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-54754.20151107211751.4bd9c2ff0188d368@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).