While Ruby's require system is nice for it simplicity, it is seriously lacking for encapsulation. It would be nice to see a system that supported this.
To clarify what I am talking about, instead of loading code at the top level, one would assign the required code and then access it via a variable or constant. To differentiate this from require, lets call it "acquire". e.g.
MyFoo = acquire('foo')
MyFoo::Foo.new
This is like the require systems used by Lua and Node.js and such.
I admit that it would be really sweet, but it definitely doesn't feel very ruby-esque due to monkey patching etc.
I need that feature once a year at most, while it adds some ugliness to code (node's exports I'm looking at you). In ruby world such problem is close to non-existent, and various attempts (refinements) to fix non-existent problem are just waste of time.
I definitely prefer nodejs modules to globals.
What @Nami-Doc says is the main reason Ruby doesn't implement this: monkey-patching. In any file you can reopen any other class. What would a file that reopen a class return?
Ruby is very comfortable to program. Yes, you have to be careful not to have name conflicts. But people come up with very strange (sometimes funny) names for gems (i.e.: decent_exposure, thor, etc.) so that conflict is very rare.
This doesn't necessarily eliminate monkey patching. It just means it would have to be done through a different means than require. e.g. maybe
MyFoo = acquire('foo')
apply_patch MyFoo
Also, there's a possibility that Ruby itself might change in the future to utilize refinements for monkey patching. See https://bugs.ruby-lang.org/issues/9704.
I second something like this, please don't copy the Ruby way of requiring everything in the global namespace. I have had multiple conflicts because of this, like several gems trying to use the 'Search' namespace. Also, the ruby way makes it very hard to load multiple version of the same library, Node has no issue with this.
Even if I have to type some more, I far prefer the system of requiring what I need in each file (an keeping this local). The benefits overweight the drawbacks.
-1
I think it just doesn't fit the semantics of the language as #767 and similar show, disambiguating which monkey patch should affect what, how which constant should be looked up after namespacing etc while not damaging the open class system is just too hard, for both the compiler but also the user of the language.
I therefore vote to reject this, drop the existing namespacing behaviour that require has and to disallow require anywhere outside the toplevel.
-1 for me too.
I stand with @jhass. I vote for require to always be global, to avoid confusion and inconsistencies. When I open a file, I want to see the actual namespaces and classes when I'll require it, either directly or throught another require. Non global requires may only make sense within ifdef or maybe inside macros.
BTW: refinements in Ruby have been there for 2 years. I feel that nobody uses them, and everybody forgot about them...
+1 I second this as I am coming here from Lua background, which had this system for globals from requires before, but now it is deprecated. What about syntax like this:
require(`foo`) as Bar
So it will require it as alias but it will still have Ruby-styled principe for globals from requires.
Side note: Refinements do change the global view but localize that change to a single file, that's vastly different from changing the namespace of things and something I wouldn't oppose.
I'm closing this, we won't change the require system. We might introduce a concept similar to refinements if we later find the need for it.
:disappointed:
(I guess the proposal here is to do what python does, which is everything is defined in a "file local" namespace, except vars declared global, +1 here):
Hmm it seems to me like monkey patching can still work
require "a/b", "B"
def B.my_new_method
end
ref: https://groups.google.com/d/msg/crystal-lang/Yid3gQnlKyI/oS4eLDh2AAAJ
This is a very good thing (TM) - but it should _allow_ flexibility.
Some propositions
include/extend - _local to file_ to avoid prefixing.using ("with") clause which I've proposed before, it also very useful: "opening" modules in an explicit lexical using scope.Motivations
--hints, --warnings or such)Problems
I see only pros to _extending Crystal_ with this stabilizing feature.
Almost all of the comments here (including, confusingly, later comments by the OP) are (negative) responses to a proposal to change the semantics of require, which are understandable, but not what this issue initially proposed:
To differentiate this from require, lets call it "acquire".
Since this discussion has wandered away from this topic, I've opened a new one here to discuss implementing a new method which complements require rather than replacing it.
Most helpful comment
This is a very good thing (TM) - but it should _allow_ flexibility.
Some propositions
include/extend- _local to file_ to avoid prefixing.using("with") clause which I've proposed before, it also very useful: "opening" modules in an explicit lexicalusingscope.Motivations
--hints,--warningsor such)Problems
I see only pros to _extending Crystal_ with this stabilizing feature.