Stefan Rusterholz wrote:
> Charles Oliver Nutter wrote:
>>> Is there a good example of where and why per-thread namespaces would 
>>> make it that much more useful you imply, so I can follow your argument 
>>> of thread unaware namespaces being worthless?
>> They wouldn't "have to be" but that would probably be the most useful.
>> If I have a namespace that changes String#to_s and I call a library that
>> calls String#to_s, don't I want that library to see my change?
> 
> Hm, my knowledge about AOP is very limited, but this sounds more like 
> AOP to me than namespacing.
> I'd expect (and want) a namespace only to be effective for libs that 
> know about the changes and request them (by importing the namespace 
> where the change is made e.g.)

AOP is largely method-bounded (or cutpoint-bounded) and not applicable 
to things outside that method or cutpoint. It doesn't really apply here.

What about this example, based on your code:

require 'namespaces'
namespace :foo, %{
   class Array
     def each
       # do something new
     end
   end
   p Array.new.collect
}

The default implementation of Enumerable#collect calls each. Would you 
expect collect to see the original each method or the one you've 
provided in the namespace?

>> Your version and Trans's example would work fine for very localized
>> namespacing, which would have much lower implementation impact (and may
>> also be useful).
> 
> I see the use of namespaces mostly in safe monkey patching. I.e. that I 
> can change the behaviour of default .each for a namespace without 
> breaking a library that depends on the default way .each works.

See the above example; if you only want namespaces so that within a 
given block of code method calls to where you want them to, that's 
simpler to implement. But it breaks some amount of consistency you might 
expect. It seems like if selector namespacing is useful (which I'm 
unsure of) it would only be generally useful if it could also affect 
calls further down the chain. Maybe I'm wrong?

>> Your code gets around that by essentially delaying the parse until a
>> namespace is already installed. While this works, and allows namespacing
>> within that subcontext, you lose all the benefits of having code only
>> get parsed once. eval is *very* expensive, even more expensive than
>> installing per-call namespace checks throughout the system.
> 
> Does that apply to block-eval too? That I currently have to resort to 
> string-eval is only due to constant lookup rules, which with access to 
> the interpreter could be changed. Or as somebody on irc mentioned, 
> ruby2ruby could also be used to search constant lookup nodes and "bend" 
> them.

No, it doesn't apply to block eval (as much), but you don't get to delay 
the parse in that case.

At some point you have to be able to say "this code is being 
namespaced". If you want to do that at runtime, then either you need to 
modify already-parsed code (which won't work across libraries or calls) 
or you need every invocation to check for namespaces. If you want to do 
that at parse/compile time you need a pragma or keyword, and you still 
can't do it across libraries or calls without installing a namespace 
check for every invocation.

> Also isn't a required file essentially evaled too? Or are there 
> differences I'm unaware of?

There's not much difference, except that require does a one-time eval of 
an entire file, parsing all code, classes, methods, blocks in one go and 
saving the results. eval calls parse every time you hit them.

- Charlie