From: Austin Ziegler Date: 2006-06-05T22:03:04+09:00 Subject: Re: Another Look at SELECTOR NAMESPACES On 6/5/06, transfire@gmail.com wrote: > Austin Ziegler wrote: >> Sorry, but that's an either-or proposition, and it's a false >> dichotomy. I, for one, am mostly happy with the state of Ruby as it >> is now. > Okay let me put it this way: Do you find it advantageous to be able to > change/extend core/standard libs? [...] 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. > [...] Okay so then lets take the simple scenario. I change the > behavior of an core class, say Array.each, for some particular need. > Then you come across that tool and realize you could reuse that code > in one of your progress, only to dicover it's causing some very > unexpect errors else where in you code. The simple fact this this is > readily possible, convinces me that Ruby would do well by having a > means of localizaing the effects of such core changes. 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. ;) > While I personally there are more advantages than disadvantages to > allowing such core extension. If Ruby does not plan to offer some > means of managing them, the in turn I think it woud better at least to > limit those changes, say to additions, but not redefintions. You say > it's a fasle dicotomy. But it is not. It is a very real dicotomy IF we > are to resolve the problem this scenario highlights. 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 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. >> I think you're deliberately misunderstanding. I am explicitly >> objecting to two bad ideas that you have suggested here: the dynamic >> resolution of selector namespaces and the inclusion of core syntax >> into said dynamic resolution. Allowing the override of {}, [], and "" >> literal creators (among others) would be changing certain fundamental >> behaviours that we should be able to depend on *no matter what*. I'm >> not convinced that selector namespaces are a good idea (and I've told >> Matz as much), but I *am* convinced that the use of (method-)selector >> namespaces must be explicit and *separate* from class/module >> namespace resolution. > You may well be right, but I would like to see some examples of the > issues you feel that make this so terrible. Moreover I don't exaclty > see how you plan to do any sort of namespaces without dynamic > resolution. 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.) > As for core syntax I assume you mean literal. Well if the literal > forms don't take part in namespaces than what's the point? Otherwise > my localized extension to String would have no effect. Um. I think that is kind of the point. X::String isn't a localized extension to ::String. It's a wholly new class, even if it inherits. How *would* you want to extend String locally to your class so that in "your" namespace, you know that all Strings have certain behaviours? class X class ::String # confusing and inappropriate end end There's no clean syntactic way to do this that doesn't end up affecting everything else. I mentioned it earlier, but it's my understanding that class/module namespaces and (method) selector namespaces will be independent of one another. > Perahps you just men effecting the literal constructors --i.e. their > using #new like everything else. Well, I wasn't refering to that > neccessarily in my original post. But one certainly does wonder if it > is possible. Perhaps it is not, though I suspect it's just tricky. Now > whether the ramifications merit the usage I can't say. I know it > already limits some code monitoring capabilities --for instance I > can't log the creation of evey string. But that's not a big deal. 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. >>> First of all, Selector Namespace is not my idea. Matz has talked >>> about it himself. I was just sharing an interesting proximity to it >>> that can be achieved in current code. That's it. >> Um. No, you were also complaining that literal constructors aren't >> overridable. > No. First of all I wasn't complaining. I was just pointing out the > this namespace implementation that I was *playing* with would not work > fully becuase literal constructors do not resolve to their respective > classes the same way that the named constant constructors do. I dion't > every really even take the implementation seriously. I just thought it > was interesting because it highlighted an idea: that of the core being > portable, duplicatable and reusable even within the same program. An idea, that ultimately, I don't think would work. >> No, you're not the only person who is willing to explore a loose >> idea. You are, however, one of the few people who will pick up that >> idea and run with it to your own ends and purposes no matter how >> little utility would be added and you tend to do so without thinking >> about the consequences of such a direction or if there is perhaps >> something better that can be done. > Well, you may mistake me for Nabu or someone who can see consequenses > so readily. One of the reasons I bring things up on the list is to get > help in seeing the utility or finding better alternatives. Certainly I > will argue strongly for something that I think has significant merit, > but I'll even more readily adopt a better solution if one is presented > me. 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. [...] >> your use of punctuation in filenames and pretending that it's a >> general problem (various places, including [ruby-core:05988]), > Pretending? I saw it as a general problem because requiring a file on > a Unix system worked but bombed on Windows. So yea I saw that as > pretty general. I thouhg at first it might help if Ruby esacped those > characters. I realized in discussions later that it's not really a > domain Ruby is going to help. So you see, by making that suggestion I > learned it wasn't a good one --and that's great. I might add that I > ultimately took some advice of yours (among others) and got rid of the > escaped characters. I no longer have a exact one for one method to > file scheme, but by doing some simple escaping myself, it works well > enough. 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. > BTW there is no such thing as a general *problem*. All problems are > personal and specific, but by talking about our problems they may have > general ramifications. 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. >> You're trying to solve a human engineering problem -- namely your >> problem -- with a computer engineering solution. It's the wrong >> solution. >> >> I still think that's true of most of the solutions that you end up >> proposing in your "picking up of loose ideas". I think that this is >> definitely a case of overengineering and underthinking. > Well, you can just chalk me up as being stupid then, I guess. Didn't say that. > To be honest I find your statement overengineered. Since you've never > bother to actually exlpain it (again) I take it to mean that you think > I want Ruby changed (computer solution) to solve my personal > programming whims (human problem). ie. Matz help! Please add > #solve_all_toms_problems to core. Thanks. (Damn that would be sweet ;) > If that's what you mean then it's simply not true . I may make > occasional misjudgements in that direction. But that's a far cry from > seeking it out. 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. >> Consider it that I don't feel like digging unnecessarily. You, at >> least, should know what you've proposed and what I've opposed. Let's >> just see one: >> >> require 'nano:classes/string' >> require 'nano:classes/string/empty?' >> >> In what way is either of those not a trainwreck? (I really don't >> want to get into the discussion on that, though; they aren't >> problems that most people would ever encounter because they wouldn't >> paint themselves into a corner that required it.) > A trainwreck? Meaningless hyperbole. 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). >> Time doesn't have a literal constructor. String does. Unless I've >> misread completely, in which case I apologise, you've said >> specifically that dynamic resolution of selector namespaces including >> literal constructors would be desirable. > Yes and no. It would be neccessary for namespaces implemented > according to my example. You have to understand, this implementation > was not meant to be a suggestion for how Ruby should do it > neccessarily, I was just showing the idea I had that got pretty close > to implementing namespaces. I though it was interesting for that > reason and shared it, then pointed out hwy it didn;t work becasue of > how RUby worked. You somehow turned that around as me saying Ruby > should work differently to accomidate my implmentation. But that's not > true -- that's the way you're interpreting things. A la your > "enginering problems" Fair enough. [...] -austin [1] def Object.const_missing(name); name.to_s; end -- Austin Ziegler * halostatue@gmail.com * Alternate: austin@halostatue.ca