Refinements.

# Jonathan Barronville (12 years ago)

I have a proposal for ES6. I don't know if it's been discussed before, so if it has, I don't mean to waste your time … hopefully, I'll be directed to the right place.

One of the most debated JavaScript topics (at least in my experience) is whether or not one should modify objects that don't belong to them ... some say it's okay if you "know what you're doing" and others see it as a crime.

I propose we solve this problem by adding "refinements" to ES6. Ruby v2.0.0 introduced a nice little feature dubbed "refinements". Refinements allow you to extend other objects for specific modules of code. I know this isn't a Ruby mailing list, but because the inspiration comes from the Ruby implementation, an example is in order (feel free to ignore it).

Say you want to modify the to_str() method in the built-in String class in Ruby, the common way to do this is as follows.

class String
  def to_str()
    "Blah, blah, blah ... this is an example."
  end
end

Very simple ... just re-open the class and create a method with the same name. However, there's a problem with this, which happens to be the same problem we have in JavaScript, and that's the fact that we've now just modified this method permanently for the rest of the execution.

Well, with refinements, the better way of accomplishing the same thing is as follows.

module MyLibrary
  refine(String) do
    def to_str()
      "Blah, blah, blah ... this is an example."
    end
  end
end

Now, if you try to send to_str() to, say, a string object "hello" ("hello".to_str()), you'll get the original "hello" as a return value. In order to use the refinements made to the class, you have to do the following.

using MyLibrary

puts("hello".to_str())

Running the code above properly outputs the string Blah, blah, blah ... this is an example..

Refinements can only be used after a using statement and only within that file.

Given that we're already getting modules in ES6, I believe something similar to this would be a great addition to the language.

I can definitely work on a more in-depth and detailed proposal, with specific JavaScript examples, if needed, but I just would like to hear thoughts around the idea.

# Jonathan Barronville (12 years ago)

(duplicate post)

# Jonathan Barronville (12 years ago)

(duplicate post)

# Rick Waldron (12 years ago)

I think this idea is certainly worth writing a strawman for, but it's too late in the ES6 cycle and this couldn't even be considered until ES7. Would you be willing to write up a "Refinements" strawman with some proposed ES-centric syntax and some preliminary semantics sketched?

# Jonathan Barronville (12 years ago)

Sure thing Rick, I will definitely do that.

I'd love to hear any current thoughts and feedback around the idea though.

# Erik Arvidsson (12 years ago)

There is another thread covering this exact topic at the moment. See "Scooped binding of a method to an object".

# Rick Waldron (12 years ago)

Can you clarify the overlap?

# Tab Atkins Jr. (12 years ago)

The overlap appears to be 100% - they're the exact same concept. It's just different words for "add something to this object within this context, but not outside".

# Erik Arvidsson (12 years ago)

When we proposed scoped object extensions we looked at Ruby's refinements.

# Brendan Eich (12 years ago)

Which were inspired by the classbox work that built on Smalltalk classes.

# Rick Waldron (12 years ago)

On Mon, Oct 21, 2013 at 11:25 AM, Tab Atkins Jr. <jackalmage at gmail.com>wrote:

The overlap appears to be 100% - they're the exact same concept. It's just different words for "add something to this object within this context, but not outside".

Indeed. I had forgotten about this: strawman:scoped_object_extensions and was mistakenly thinking of the "scoped binding of a method to an object" discussion—which does have overlap, but certainly not aligned 1-to-1 as refinements and scoped object extensions. Sorry for the noise.