From: transfire@... Date: 2006-06-07T01:25:13+09:00 Subject: Re: Another Look at SELECTOR NAMESPACES Austin Ziegler wrote: > You're right. It's "mostly". I am very ... cautious about changing the > behaviour in core libraries and I almost never do so in anything that I > release. In a DSL that I have done for work, though, I have made a > *very* dangerous change (one that I have found necessary to document) > that makes the DSL itself much easier to use[1]. If I were doing this in > anything that would be combined with anything else, I wouldn't make this > change. Period. I agree that changing core behavior should not be done lightly, becasue they reduce code readability. But DSLs can be even better for that, and as you point out a core change may enhance that. I think you should be able to share your code without having to worry so about it. > I would question the need to change Array#each rather than introducing a > new method. That's the thing that I've found in my years of Ruby: the > need I have for modifying the core language's operations are few and far > between. More likely, I need *extra* behaviour which suggests adding a > _new_ method to the core class (in private code), but I think I can > count the number of times I've needed to override a core functionality > on three fingers and not use them all. ;) I've done a lot of "framework" coding --ways to enhance the overall system, such as AOP and Annotations, plus I maintain a whole library of extensions. So I'm completely on the other side of the spectrum. Of course I too almost entirely avoid overriding core behavior, and stick to additions, for obvious reasons. Yet I think there is more potential here. The way I see it is like Kernel. We can override any Kernel method we wish in our subclasses, right? So what if the entire system came in via Kernel instead of being split into two separate hierarchies: Kernel and Constant Lookup. You may think that would lead to a train wrek, but I am not so sure of that. People generally avoid the Kernel methods in their subclasses unless they have a good reason for not doing so --I think the same would hold true, and even more cautiously, when it comes to more essential aspects of the core. > It *is* a false dichotomy. One does not have the choice between allowing > core extensions or not. Taking your example, what would the difference > be between: > > %w(a b c).trans:each { ... } > %w(a b c).trans_each { ... } > > Seriously? The former is the proposed selector namespace format for an > individual call. I agree. That notation has very limited usefulness. BTW I though it was? %w(a b c).each:trans { ... } > I think that the only real difference would be: > > with_namespace :trans do > %w(a b c).each { ... } # is trans:each > end > > That's what I mean about being explicit. Your statements *so far* have > been focussed around implicit resolution of (selector) namespaces. And > *that* is the part that I oppose as much as possible. Implicit > behaviours tend to confuse people unnecessarily. Well, I'm certainly not against explict namespaces. And in part I was thinking of my example notation as more akin to private, protected and public (even if it didn't fully implement that way). So in that case there's still an explicit "area" in which the namespace applies. You may be right about implicit namespaces, though I won't discredit them quite so readily --they would be akin to what one does when they include a module in a class. I mean you have to know what the module brings to the table to use work in that class, a namespace is the the same idea, juut more extensive. Again I go back to the idea of the whol system coming though the Kernel. > See above for the explicit selector namespace resolution. Selector > namespaces is about method namespacing, not class namespacing. There are > already well-defined rules for the resolution of class (and module) > namespacing, and they're going to become less confusing in Ruby2. With > regard to examples of what could go wrong? > > class X > class String > def initialize(*args, &block) > @value = 0 > end > > def to_s > @value.to_s > end > > def to_str > to_s > end > end > > puts "Here's some debug information." > puts String.new("More debug information.") > end > > If you have dynamic resolution of the class and constructor based on > literals, you *will* break the behaviour of String (and very badly) for > everything else (that is, the first example would do the same as the > second example). As I said when I first responded, this is *just* like > the ability in C++ to define: > > T operator+(const T& o); > T operator+=(const T& o); > > The moment that I can define away what looks like it should be core > standard behaviour (that is, that the result of "x = x + b" and "x += b" > would be the same), I have not just given the user power, I have given > the user *inappropriate* power. The potential for misbehaviour and > everything else is *significantly* higher than the value afforded by > such redefinition. (I know why they allow it. It allows your += > operation to be implemented efficiently on complex objects, but I > consider that to be premature optimisation most of the time.) [snip] > I think that you wouldn't want to know when literals are created, mostly > because literals are generally very small and multiply in your code like > rabbits. Sure. I such things are far from any common use case. But I'm not sure it should neccessarily be illegal? There may be very good reasons that it is, but if it's reasonably possible then having that avenue could be very useful in some cases. Code inspection tools for instance would probably be all over such abilities. > I think that what you may need to do with some of your proposals is step > back from them and think them through. You say you can't see > consequenses so readily. The reality is that this is a skill that can be > trained just like any other. Sometimes, the better solution is no change > at all. Well, sometimes I do and sometimes I don't. Sometimes I think others would have better insight so I ask. I'm not one of those guys whose dead set against asking for directions --if you take my meaning. You think maybe I should spend more time considering before asking. In some cases you're right. And I'll try to do that more (and actually I have already been doing so). > Okay; I may have been unfair in my characterisation of how you viewed > this. However, there are cases where it would have bombed on Unix, too > (usually from the command-line since the *shell* does meta character > expansion). But Windows isn't the only system to limit punctuation, > although it's probably the strictest at this point. Yep. More goog reasons I was deads wrong about that. > Um. I would disagree with you philosophically. However, I will modify my > statement to suggest that you adopt positions and treat them as > something that a language change should fix when it's usually far easier > and cleaner for the programmer to change what they do. [snip] > Trans, I may be your most vocal critic, but I know I'm not the only one. > I also know you have people who admire the work that you've done, and I > would be the last to suggest that you've done nothing for Ruby. You have > done things for Ruby, but I think it's a little more than "occasional > misjudgements" (your word, not mine). I think what I'm *really* trying > to say is that you often appear far more willing to tinker with Ruby, > the language, rather than trying to look at the problem from a different > perspective. > > There are things that I would fix with Ruby. There are choices that Matz > has made that I strongly disagree with (->() {}, anyone?). I'm not at > all suggesting that there aren't things about Ruby that don't need > fixing, but I will look at changing Ruby *last*. You may not look at > changing Ruby *first*, but your public persona here on ruby-talk and on > ruby-core is ... one of the first voices when this comes up. Well, I think you misunderstand me. I enjoy toying with ideas realated to the language itself. Just because I present such an idea doesn't mean that I am proposing it a la RCR. I'm just interested in exploring the possibilities. It's sort of a hobby. So I think your misjudging my modus operandi here. > No, not meaningless hyperbole. Meaningful hyperbole. IIRC, you wanted to > be able to do "require 'nano:classes/string" because you didn't want to > reorganise your source repository or use a Rake task to reorganise it on > packaging. But simply changing Ruby for that isn't the right answer, and > visually your desired change don't provide useful meaning (IMO). No. That's not it at all. Think you mixed up two issues into one that I was having about the same time --which can be interrelate, so i understand why you may have thought that. But the colon notion is specifically for a way to do versioning *efficiently* and independently of a packaing system. That's all. While it's functionality relates to the organization ones distributed files, the organization of the source repository is not the causal issue. > [1] def Object.const_missing(name); name.to_s; end Hmm... too bad you can't capture cont_missing relative a module or class. T.