Project

General

Profile

Feature #15752

A dedicated module for experimental features

Added by Eregon (Benoit Daloze) 7 months ago. Updated 7 months ago.

Status:
Open
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:92175]

Description

I believe we should introduce a module for experimental features portable across Ruby implementations.

An example of such a portable experimental feature is RubyVM.resolve_feature_path.
This feature has nothing MRI specific in it, it is a part of basic require functionality.
In the future, I would think more experimental features will be introduced, and I think RubyVM is not a good place for it.

Currently, RubyVM is sometimes used for experimental features, but I believe RubyVM should be defined only on MRI and contain only MRI-specific features.
This means it is impossible for other implementations such as JRuby and TruffleRuby to define resolve_feature_path (even though it's trivial and might be useful for some users),
and keeping RubyVM not defined for clearly marking MRI specific features are not available.

This is a problem that will only gets worse as portable experimental features are added to RubyVM.
Here is one example of adding an experimental feature but unfortunately there is no common place between Ruby implementations to add it:
https://github.com/jruby/jruby/issues/5206

If other implementations defined RubyVM, then only parts of it would be portable and other parts would be MRI specific,
which would be very confusing to both users and Ruby implementers.

Also, RubyVM doesn't really indicate by its name that it contains experimental features.

So I propose the obvious name ExperimentalFeatures.

I think such a long name is unlikely to clash with existing Object constants, is very clear,
and marks that any usage of it is by definition using not stable APIs that might be removed or changed.

In combination with #15743, this would mean we can very clearly see what kind of feature it is due to explicit naming:

  • ExperimentalFeatures.resolve_feature_path is a portable experimental feature, which can be supported on other Ruby implementations too.
  • CRuby::InstructionSequence is a CRuby/MRI-specific feature, which will only be supported on MRI.

OTOH, the RubyVM name doesn't indicate this important difference, and doesn't even indicate the features under it might experimental or not portable.

My main motivation here, is allowing other Ruby implementations to support some of these portable experimental features.
There is no reason for only MRI to be able to support code using portable experimental features.

cc mame (Yusuke Endoh) headius (Charles Nutter)


Related issues

Related to Ruby master - Feature #15743: RubyVM should be renamed to CRubyClosedActions
Related to Ruby master - Feature #15903: Move RubyVM.resolve_feature_path to Kernel.resolve_feature_pathClosedActions
Related to Ruby master - Feature #15966: Introducing experimental features behind a flag, disabled by defaultRejectedActions

History

#1

Updated by Eregon (Benoit Daloze) 7 months ago

#2

Updated by Eregon (Benoit Daloze) 7 months ago

  • Description updated (diff)

Updated by ioquatix (Samuel Williams) 7 months ago

I think it's a good idea. Might I suggest two potential ideas?

Firstly, maybe have a shared Ruby module for common but interpreter specific functionality.

Then, interpreter specific modules e.g. CRuby, MRuby, JRuby, TruffleRuby for interpreter specific functionality.

For experimental stuff, you could choose either CRuby::Experimental or Ruby::Experimental. The path for loading such features would be require 'ruby/experimental/thing'.

Maybe also worthwhile considering how Python's __future__ works, e.g. https://stackoverflow.com/questions/7075082/what-is-future-in-python-used-for-and-how-when-to-use-it-and-how-it-works is a quick overview if anyone is unfamiliar.

+1

Updated by Eregon (Benoit Daloze) 7 months ago

ioquatix (Samuel Williams) wrote:

I think it's a good idea. Might I suggest two potential ideas?

Go ahead :)

Firstly, maybe have a shared Ruby module for common but interpreter specific functionality.

This is equivalent to my proposition of ExperimentalFeatures with a different name, right?

I don't understand how it can be "common" and also "interpreter specific". They are opposite to me. Did you mean "but not"?

Then, interpreter specific modules e.g. CRuby, MRuby, JRuby, TruffleRuby for interpreter specific functionality.

For experimental stuff, you could choose either CRuby::Experimental or Ruby::Experimental.

I was thinking both the common namespace and the interpreter-specific namespaces are experimental.
But indeed, maybe we need to be more fine-grained.

For instance, TruffleRuby defines a few methods and classes under TruffleRuby and those are fairly stable and documented.
https://github.com/oracle/truffleruby/blob/master/doc/user/truffleruby-additions.md#truffleruby-methods-and-classes
BTW, a few of those would probably make sense under ExperimentalFeatures (most of these are needed by ConcurrentRuby).

I think anything under ExperimentalFeatures is experimental.
Common stable (non-experimental) features should just be under another namespace (e.g., Kernel or whatever feels appropriate, including possibly a new class/module for the feature).

For interpreter-specific namespaces, I think it's OK to delegate to the documentation of the implementation to say what's experimental and what's stable,
although the distinction should be simple such as TruffleRuby would be stable and TruffleRuby::Experimental would be experimental.

I think CRuby::Experimental would be good (as a replacement for RubyVM), because it clearly marks such API are MRI specific and have not matured to a stable API yet.
Just as an example, RubyVM::AbstractSyntaxTree will probably break usages of it whenever a node field is added, removed or reordered,
so being clearly marked as experimental in the usages seems good (#14844 is an example that this is not clear at all for users currently with RubyVM).

The path for loading such features would be require 'ruby/experimental/thing'.

Typically the require is not needed, such functionality is just declared from startup.
That's the case for JRuby, TruffleRuby and Rubinius.
I'm not against it, but I don't see what it solves.
For feature checking, defined?(ExperimentalFeatures.foo) (or respond_to?) seems good enough.

Maybe also worthwhile considering how Python's __future__ works, e.g. https://stackoverflow.com/questions/7075082/what-is-future-in-python-used-for-and-how-when-to-use-it-and-how-it-works is a quick overview if anyone is unfamiliar.

How would that work in Ruby?
It seems more targeted at trying to make code more compatible with more recent versions, which I think we simply do by deprecation in Ruby and not breaking syntax.

Updated by naruse (Yui NARUSE) 7 months ago

Web browsers showed us that it cannot achieve at once both experimental and portable.

Updated by shevegen (Robert A. Heiler) 7 months ago

One worry that I have here is that this change may add bureaucratic overhead to MRI in
particular. I have nothing against alternative ruby implementations at all, quite the
opposite - the easier it is to implement ruby/rubies the better. The core team also
tried to help here, e. g. ISO spec of ruby; and alternative implementations also
helped likewise the other way around, such as rubinius + ruby spec early on (and still
maintained, also by ruby contributors; I think Benoit extended the spec too, and this
may be a partial reason for the suggestion perhaps). But having a situation where changes
to MRI could possibly be delayed due to difficulties of alternative implementations would
be a bad thing too, in my opinion. I think most people use MRI and any change to MRI in
this regard should also be kept in mind.

Updated by Eregon (Benoit Daloze) 7 months ago

naruse (Yui NARUSE) wrote:

Web browsers showed us that it cannot achieve at once both experimental and portable.

I will dare to challenge that.
Why would ExperimentalFeatures.resolve_feature_path not be portable?
Portable here just means it can be implemented by other Ruby implementations,
and it is designed to not be specific to a given implementation (i.e., it can be implemented on other Ruby implementations).

Re browsers, I think the main problem is every browser used their own prefixes.
If we use a common namespace, and discuss all additions in this tracker, I don't think we'll have that problem.

Updated by Eregon (Benoit Daloze) 7 months ago

shevegen (Robert A. Heiler) wrote:

But having a situation where changes to MRI could possibly be delayed due to difficulties
of alternative implementations would be a bad thing too, in my opinion.

I am not proposing anything like that.
Practically, whenever MRI decides to add an experimental feature,
the only change is if it could potentially be implemented on other Ruby implementations ("portable" as I just defined above),
add it under ExperimentalFeatures instead of under RubyVM. That's all.

#9

Updated by Eregon (Benoit Daloze) 7 months ago

  • Subject changed from A dedicated module for portable experimental features to A dedicated module for experimental features

Updated by knu (Akinori MUSHA) 7 months ago

Using a plural constant name sounds like a good idea because it wouldn't likely conflict with existing model names. 😄

Updated by knu (Akinori MUSHA) 7 months ago

I think it's a good idea to reserve a namespace globally shared among Ruby implementations, even if it's up to each implementation whether to follow individual features proposed by other implementations.

#12

Updated by Eregon (Benoit Daloze) 5 months ago

  • Related to Feature #15903: Move RubyVM.resolve_feature_path to Kernel.resolve_feature_path added
#13

Updated by Eregon (Benoit Daloze) 5 months ago

  • Related to Feature #15966: Introducing experimental features behind a flag, disabled by default added

Also available in: Atom PDF