[ruby-core:22246] YASNP (Yet Another Selector Namespace Proposal)

9 views
Skip to first unread message

Yehuda Katz

unread,
Feb 19, 2009, 1:22:59 AM2/19/09
to ruby-core
The idea is to make selectors like optional versions of Python imports. Example:

# merb/core_ext/string.rb

namespace Merb
  class String
    def to_s
      super + "Awesome"
    end
  end
end

# merb/application.rb

use Merb::String

class Foo
  def bar(str)
    str.to_s
  end
end


The basic implementation idea is that there be a new node named call_with_namespace that would hold any namespaces registered for the file in question. This would be a parse-time transform (based on a new use keyword). You would also be able to cache the method lookup, based on the selector AND the namespaces. So it shouldn't be a huge performance hit.

Thoughts?

--
Yehuda Katz
Developer | Engine Yard
(ph) 718.877.1325

Tom Link

unread,
Feb 19, 2009, 1:44:04 AM2/19/09
to ruby...@ruby-lang.org
> use Merb::String
>
> class Foo
>   def bar(str)
>     str.to_s
>   end
> end

Just out of curiosity: Wouldn't the problem with your examples be that
the String class is hard-wired in the ruby parser -- see eg
http://groups.google.com/group/comp.lang.ruby/browse_frm/thread/2a0ad2d4a78f499d/

I'm not sure though if this is still true for ruby 1.9.

Yehuda Katz

unread,
Feb 19, 2009, 1:51:24 AM2/19/09
to ruby-core
Actually it's completely unrelated.

str.to_s would become:

s(:call_with_namespace, nil, :str, s(:arglist)), :to_s, s(:arglist), s(:namespaces, :Merb))

-- Yehuda

2009/2/18 Tom Link <mica...@gmail.com>

Charles Oliver Nutter

unread,
Feb 19, 2009, 2:10:31 AM2/19/09
to ruby...@ruby-lang.org
Yehuda Katz wrote:
> The basic implementation idea is that there be a new node named
> call_with_namespace that would hold any namespaces registered for the
> file in question. This would be a parse-time transform (based on a new
> use keyword). You would also be able to cache the method lookup, based
> on the selector AND the namespaces. So it shouldn't be a huge
> performance hit.

Here's a hacked-together implementation for JRuby:

http://pastie.org/393746

The idea is that at parse time it saves off the node associated with
whatever you're "use"ing and attaches it to future parsed calls. Then
there's a modification to calls to use that namespace first if it's present.

Caveats:

* HACKHACKHACK
* Only works for single-arg "call" in this case, but easy to generalize
to all other calls
* The namespace never gets turned off in this example. It wouldn't be
hard to add with parser help, but there's no trigger I can use in this
simple version.
* Interpreter-only. Compilation would be a bit trickier, but not much.

If I were going to implement this for real I'd probably have a special
"namespaced call site" that does the magic for all calls.

A fortunate side effect of this impl is that the "to_s" inside the
namespaced Merb::String actually goes to the real String, since "self"
is the 'crazy time' object below. This may or may not be desirable, but
it was easier than trying to make super work.

- Charlie

Charles Oliver Nutter

unread,
Feb 19, 2009, 2:15:20 AM2/19/09
to ruby...@ruby-lang.org
Charles Oliver Nutter wrote:
> Caveats:
>
> * HACKHACKHACK
> * Only works for single-arg "call" in this case, but easy to generalize
> to all other calls
> * The namespace never gets turned off in this example. It wouldn't be
> hard to add with parser help, but there's no trigger I can use in this
> simple version.
> * Interpreter-only. Compilation would be a bit trickier, but not much.

Another important one:

* This version searches the namespace for the method *unconditionally*.
It would probably be desirable to identify whether it applies to the
receiver or not:

use String => Merb::String

And then the namespace association only applies when the receiver is_a?
String.

- Charlie

Florian Gilcher

unread,
Feb 19, 2009, 12:11:32 PM2/19/09
to ruby...@ruby-lang.org


That sounds a lot like the Objective-C method poseAs, discarding some
of it's limitations.

But what is the scope of use? AFAIK, there is no construct in Ruby
that has a file-only scope (except the ones that need to be closed
because of syntactical reasons). Granted, those are details.

But what about this example in Yehudas gist:

===
# require "my_app3", :use => Merb::String

"hello_goodbye".camel_case #=> "HelloGoodbye"
"hello_goodbye".camel_case(true) #=> ArgumentError
===

Making it externally controllable which class a file uses is at least
discussable. I don't like it, especially because it is not really
fitting in Rubys way of not seeing files as program units. Also, only
one parametrization can be in place at once, which smells like a
source of conflicts.

Regards,
Florian Gilcher

--
Florian Gilcher

smtp: f...@andersground.net
jabber: Sk...@jabber.ccc.de
gpg: 533148E2


Charles Oliver Nutter

unread,
Feb 19, 2009, 2:03:10 PM2/19/09
to ruby...@ruby-lang.org
Florian Gilcher wrote:
> ===
> # require "my_app3", :use => Merb::String
>
> "hello_goodbye".camel_case #=> "HelloGoodbye"
> "hello_goodbye".camel_case(true) #=> ArgumentError
> ===
>
> Making it externally controllable which class a file uses is at least
> discussable. I don't like it, especially because it is not really
> fitting in Rubys way of not seeing files as program units. Also, only
> one parametrization can be in place at once, which smells like a source
> of conflicts.

I see the namespacing more like adding an extra layer of indirection to
calls so you can hook them without globally overriding them. So within
the context of a file you're saying "I want to have a go at all methods
called against String" and you can optionally then provide your own impls.

If it's the file scoping that seems odd, I don't see any reason why it
couldn't be explicitly scoped. Something like:

use String => Merb::String do
... and in here all calls to String methods can be replaced by Merb
end

It could be argued that the file scope logic is a little too unbounded,
certainly.

- Charlie

Yehuda Katz

unread,
Feb 19, 2009, 2:46:29 PM2/19/09
to ruby-core


2009/2/19 Florian Gilcher <f...@andersground.net>


On Feb 19, 2009, at 8:15 AM, Charles Oliver Nutter wrote:

Charles Oliver Nutter wrote:
Caveats:
* HACKHACKHACK
* Only works for single-arg "call" in this case, but easy to generalize to all other calls
* The namespace never gets turned off in this example. It wouldn't be hard to add with parser help, but there's no trigger I can use in this simple version.
* Interpreter-only. Compilation would be a bit trickier, but not much.

Another important one:

* This version searches the namespace for the method *unconditionally*. It would probably be desirable to identify whether it applies to the receiver or not:

use String => Merb::String

And then the namespace association only applies when the receiver is_a? String.

- Charlie



That sounds a lot like the Objective-C method poseAs, discarding some of it's limitations.

But what is the scope of use? AFAIK, there is no construct in Ruby that has a file-only scope (except the ones that need to be closed because of syntactical reasons). Granted, those are details.

I would be open to making it take a block, but I'm not aware of any use-case where that would be helpful, so I left it out at the beginning to reduce the need for extra ceremony.
 


But what about this example in Yehudas gist:

===
# require "my_app3", :use => Merb::String


"hello_goodbye".camel_case #=> "HelloGoodbye"
"hello_goodbye".camel_case(true) #=> ArgumentError
===

Making it externally controllable which class a file uses is at least discussable. I don't like it, especially because it is not really fitting in Rubys way of not seeing files as program units.

Again, I'm open to doing it a different way. I chose this initially because it makes it easier to implement at parse-time (which is required for performance) and because I can't think of any use-case where more granular application of namespaces would actually be useful, but I'd be fine with "use" taking a block if it moved the proposal forward.
 
Also, only one parametrization can be in place at once, which smells like a source of conflicts.

"only one parametrization can be in place at once" -- I don't understand what you mean by this.
 


Regards,
Florian Gilcher

--
Florian Gilcher

smtp:   f...@andersground.net
jabber: Sk...@jabber.ccc.de
gpg:    533148E2


Charles Oliver Nutter

unread,
Feb 19, 2009, 4:45:28 PM2/19/09
to ruby...@ruby-lang.org
Yehuda Katz wrote:
> I would be open to making it take a block, but I'm not aware of any
> use-case where that would be helpful, so I left it out at the beginning
> to reduce the need for extra ceremony.
...

> Again, I'm open to doing it a different way. I chose this initially
> because it makes it easier to implement at parse-time (which is required
> for performance) and because I can't think of any use-case where more
> granular application of namespaces would actually be useful, but I'd be
> fine with "use" taking a block if it moved the proposal forward.

I suppose there's another argument in favor of an explicit bounding of
the "use" area: where do you *start*? If this is parse time, having it
start at the first "use" call seems a little odd; you'd almost want it
to be a whole-file pragma. But starting it at the beginning of the file
seems just as odd, since a use anywhere in the body changes all method
dispatches.

- Charlie

Yehuda Katz

unread,
Feb 19, 2009, 5:49:11 PM2/19/09
to ruby-core
I'd be perfectly happy to have it take a block.

-- Yehuda

2009/2/19 Charles Oliver Nutter <charles...@sun.com>

Florian Gilcher

unread,
Feb 20, 2009, 4:02:07 AM2/20/09
to ruby...@ruby-lang.org
On Feb 19, 2009, at 8:46 PM, Yehuda Katz wrote:

Also, only one parametrization can be in place at once, which smells like a source of conflicts.

"only one parametrization can be in place at once" -- I don't understand what you mean by this.
 

I don't know whether I picked the right vocabulary. I wanted to say that by suddently making require passing in parameters into the code loading process, you open the door for problems such as this:

Lib A loads some file with:

require 'foolib', use String => LibA::String

Another one does:

require 'foolib', use String => LibB::String

Which String class does foolib use now? The first, the last, undefined? Based on the behaviour of require: the first one, which would make LibB fail. Granted, you could find ways around this, but not that simple ones.[2]
Granted, we already have that problem with redefining methods, but making it so easy to produce a clash seems a bit careless.

Just for the record: I would really like to see some kind of namespacing/posing in Ruby. But the topic is a dangerous one, a careless approach could break the language[1].
I believe it would also require to fundamentally rethink the way ruby packages code. 

But then again, I may be a hardcore programmer, but not a language designer.

Regards,
Florian

[1]: in memory of the "\" operator ;).
[2]: that could be an interesting thesis topic.

Yehuda Katz

unread,
Feb 20, 2009, 11:39:53 AM2/20/09
to ruby-core
Ok, based on a bunch of comments I got from Aaron Patterson and John Barnette, a somewhat modified proposal:

https://gist.github.com/83d390aea81a12f1667c

Main changes:
  • "use" is scoped
  • no special namespace keyword; any module can be a namespace
  • use Merb::String for String
  • use Merb::* (equivalent to Merb.constants.each {|k| use k for k.split("::", 2).last.constantize })
Take a look at the gist for more details. I think this is a significantly refined proposal than the one I submitted a few days ago.

-- Yehuda

2009/2/20 Florian Gilcher <f...@andersground.net>

Charles Oliver Nutter

unread,
Feb 20, 2009, 12:10:47 PM2/20/09
to ruby...@ruby-lang.org
Yehuda Katz wrote:
> Ok, based on a bunch of comments I got from Aaron Patterson and John
> Barnette, a somewhat modified proposal:
>
> https://gist.github.com/83d390aea81a12f1667c

I'm trying to work out the details in my head. The main complication I
have is what gets done at parse time and what gets done at runtime.

Parse Time:

It seems like at least the "use" would have to set a global or
per-thread flag during parsing so that calls made under that scope would
be generated with extra logic for namespace checking.

Runtime:

The runtime bit is trickier. I think the node passed to use would have
to be saved off in the parsed calls so they could do that lookup.

But then there's the question of whether they should look it up each
time. That's a constant lookup hit for ever namespaced call. Looking it
up every time could also lead to some oddities if the method itself had
conflicting constants in its lookup hierarchy.

If instead the use itself were captured and used as the reference point
for the the lookup, it would be executed once in the script, immediately
cached, and all calls would then use the same value. Yes, I think that's
probably better.

So a NamespacedCallNode would aggregate a UseNode, with the UseNode
aggregating some other node structure for the argument and a body of
code; basically all calls would have a backreference to the 'use', and
the 'use' itself would represent the cache key and lookup reference point.

Threading:

I lean more toward having the parse of a "use" set a flag in the
executing parser instance on a single thread; there are possible
complications here though.

If one thread requires a file while in a "use", and at the same time
another thread requires the same file without a "use", we have a race.

If one thread requires a file and another file loads it, we have issues
as well (though not substantially different from issues in normal Ruby.

Of course the threading concerns are entirely parse-time; once parsed
every thread would see the namespacing, eh?

Mock-up:

As this settles we could probably mock it up pretty easily in JRuby. My
early attempt was without parser support; I could continue hacking it
that way, but having real parser help would make it easier. We shall
see...I'm curious what others think of the proposal.

- Charlie

Jim Weirich

unread,
Feb 21, 2009, 2:34:18 PM2/21/09
to ruby...@ruby-lang.org
On Feb 20, 2009, at 8:39 AM, Yehuda Katz wrote:
> - no special namespace keyword; any module can be a namespace

+1

I like this much better than giving the use command its own block.

--
-- Jim Weirich
-- jim.w...@gmail.com


Aaron Patterson

unread,
Feb 21, 2009, 9:35:41 PM2/21/09
to ruby...@ruby-lang.org
On Sun, Feb 22, 2009 at 04:34:18AM +0900, Jim Weirich wrote:
> On Feb 20, 2009, at 8:39 AM, Yehuda Katz wrote:
>> - no special namespace keyword; any module can be a namespace
>
> +1
>
> I like this much better than giving the use command its own block.

+1 as well, but I like the block. For me, it seems to be more clear as
to what is going on.

use Merb::String => String do
"bla blah".some_special_merb_only_method
end

"bla blah".some_special_merb_only_method # => doh! doesn't exist

--
Aaron Patterson
http://tenderlovemaking.com/

Yehuda Katz

unread,
Feb 21, 2009, 11:30:48 PM2/21/09
to ruby...@ruby-lang.org
The thing is that it's not a *real* block, but that might not matter
since you can't capture it anyway.

I'd hate for people to think it had closure semantics... Without a
block, it's analogous to the class, module or def keyword, which are
perfectly clear. I'm fine either way though.

Sent from my iPhone

On Feb 21, 2009, at 9:35 PM, Aaron Patterson

Eero Saynatkari

unread,
Feb 22, 2009, 9:55:54 AM2/22/09
to ruby...@ruby-lang.org
Excerpts from Aaron Patterson's message of Sun Feb 22 04:35:41 +0200 2009:

> On Sun, Feb 22, 2009 at 04:34:18AM +0900, Jim Weirich wrote:
> > On Feb 20, 2009, at 8:39 AM, Yehuda Katz wrote:
> >> - no special namespace keyword; any module can be a namespace
> >
> > +1
> >
> > I like this much better than giving the use command its own block.
>
> +1 as well, but I like the block. For me, it seems to be more clear as
> to what is going on.
>
> use Merb::String => String do
> "bla blah".some_special_merb_only_method
> end


I am not sure I like this plan at all, really: it would be better
to implement through (or at least concurrently with) methodwise
selectors, but since this version is not dealing with an actual
block, it should follow the while/until pattern instead:

using Merb::String => String
whatever
end


--
Magic is insufficiently advanced technology.

Berger, Daniel

unread,
Feb 23, 2009, 10:15:36 AM2/23/09
to ruby...@ruby-lang.org

> -----Original Message-----
> From: Eero Saynatkari [mailto:rub...@kittensoft.org]
> Sent: Sunday, February 22, 2009 7:56 AM
> To: ruby...@ruby-lang.org
> Subject: [ruby-core:22330] Re: YASNP (Yet Another Selector
> Namespace Proposal)
>
> Excerpts from Aaron Patterson's message of Sun Feb 22
> 04:35:41 +0200 2009:
> > On Sun, Feb 22, 2009 at 04:34:18AM +0900, Jim Weirich wrote:
> > > On Feb 20, 2009, at 8:39 AM, Yehuda Katz wrote:
> > >> - no special namespace keyword; any module can be a namespace
> > >
> > > +1
> > >
> > > I like this much better than giving the use command its own block.
> >
> > +1 as well, but I like the block. For me, it seems to be
> more clear

> > +as


> > to what is going on.
> >
> > use Merb::String => String do
> > "bla blah".some_special_merb_only_method
> > end
>
>
> I am not sure I like this plan at all, really: it would be
> better to implement through (or at least concurrently with)
> methodwise selectors, but since this version is not dealing
> with an actual block, it should follow the while/until
> pattern instead:
>
> using Merb::String => String
> whatever
> end

Put me in the "don't like" category as well.

Regards,

Dan

Yehuda Katz

unread,
Feb 23, 2009, 11:08:29 AM2/23/09
to ruby-core
Can you explain *why* you don't like it?

Keep in mind that most people would never use this feature... it's mostly for frameworks to be able to make core extensions for their own use without polluting the global space.

-- Yehuda

2009/2/23 Berger, Daniel <Daniel...@qwest.com>

Florian Gilcher

unread,
Feb 23, 2009, 11:34:35 AM2/23/09
to ruby...@ruby-lang.org

On Feb 23, 2009, at 5:08 PM, Yehuda Katz wrote:

Can you explain *why* you don't like it?

Keep in mind that most people would never use this feature... it's mostly for frameworks to be able to make core extensions for their own use without polluting the global space.

-- Yehuda

Actually, couldn't you built something on top something like ContextR?[1]

Sure, it will never get as nice, but if you are not using it that often...

Regards,
Florian

[1]: http://contextr.rubyforge.org

Yehuda Katz

unread,
Feb 23, 2009, 11:50:58 AM2/23/09
to ruby-core
The people who would use it (i.e. frameworks and libraries) would probably use it copiously.

It looks like contextr would be super-slow, and unless I'm reading it wrong, it solves a completely different problem (i.e. it wouldn't work for class bodies; you'd have to use it at runtime at the place the code is being executed, and it doesn't seem to be able to handle literals, or things passed in from outside the block, which are the MAIN use-cases).

-- Yehuda

2009/2/23 Florian Gilcher <f...@andersground.net>

Eero Saynatkari

unread,
Feb 23, 2009, 12:11:42 PM2/23/09
to ruby...@ruby-lang.org
Excerpts from Yehuda Katz's message of Mon Feb 23 18:08:29 +0200 2009:

> Can you explain *why* you don't like it?

It is difficult to see the extent of changes. I prefer the method-wise
namespace:

"foo".Merb:to_url

Thomas Enebo

unread,
Feb 23, 2009, 12:19:26 PM2/23/09
to ruby...@ruby-lang.org
Yehuda Katz wrote:
> Can you explain *why* you don't like it?
>
> Keep in mind that most people would never use this feature... it's
> mostly for frameworks to be able to make core extensions for their own
> use without polluting the global space.
Famous last words...One poignant blog entry can undo your statement in a
heartbeat.

My quick take...

The good:
- Clearly demarcated syntax to express that you are changing
behavior. Much more visible than monkey patching.
- It is lexically defined. Your semantic change only affects the code
it is surrounding. The scope of the changes will not seep everywhere.
Though I suspect you may end up with a boilerplate at the top of every
file in your library.

The bad:
- This mostly just seems like monkey-patching defense to me. Maybe
you are fighting the symptom and not the problem by adding this? Not
sure I have much more to add to this...Redefining methods in Ruby is a
reality and a powerful tool. I think you are just trying to
counter-balance it so library authors can prevent users from changing
your libraries behavior.

Though you cannot really prevent users from doing anything right? They
can still modify Merb::String to do the things you were trying to
prevent in the first place. Maybe that is ok, but it still feels like
if someone wrecks the API you are consuming (String for example), then
they may feel the need to wreck your version of string also. Perhaps
then they deserve it....then again they deserved it the second they
ruined String.

I feel pretty ambivalent about this...

-Tom

Yehuda Katz

unread,
Feb 23, 2009, 1:13:45 PM2/23/09
to ruby-core
I'd be fine with "foo".Merb:to_url as one way of accessing the namespace, but frankly, in most cases this is for libraries and frameworks to be able to scope the extent of their changes to Ruby's core. In that context, being able to say: "use this namespace for all of the following code" is quite useful.

-- Yehuda

2009/2/23 Eero Saynatkari <rub...@kittensoft.org>

Yehuda Katz

unread,
Feb 23, 2009, 1:15:11 PM2/23/09
to ruby-core


2009/2/23 Thomas Enebo <Thomas...@sun.com>

Yehuda Katz wrote:
Can you explain *why* you don't like it?

Keep in mind that most people would never use this feature... it's mostly for frameworks to be able to make core extensions for their own use without polluting the global space.
Famous last words...One poignant blog entry can undo your statement in a heartbeat.  
My quick take...

The good:
 - Clearly demarcated syntax to express that you are changing behavior.  Much more visible than monkey patching.
 - It is lexically defined.  Your semantic change only affects the code it is surrounding.  The scope of the changes will not seep everywhere.  Though I suspect you may end up with a boilerplate at the top of every file in your library.

The bad:
 - This mostly just seems like monkey-patching defense to me.  Maybe you are fighting the symptom and not the problem by adding this?  Not sure I have much more to add to this...Redefining methods in Ruby is a reality and a powerful tool.  I think you are just trying to counter-balance it so library authors can prevent users from changing your libraries behavior.

Nope. It's perfectly fine for users to change my library's behavior if they want to. However, this is not the real-life problem we are facing. The issue is not that someone wants to change how camel_case works inside of Merb, it's that they want to change how camel_case works in different code.
 
Though you cannot really prevent users from doing anything right?  They can still modify Merb::String to do the things you were trying to prevent in the first place.    Maybe that is ok, but it still feels like if someone wrecks the API you are consuming (String for example), then they may feel the need to wreck your version of string also.  Perhaps then they deserve it....then again they deserved it the second they ruined String.

They can still change String however they want, and Merb::String would win inside of Merb's library code.
 
I feel pretty ambivalent about this...
-Tom



Daniel Berger

unread,
Feb 23, 2009, 10:48:13 PM2/23/09
to ruby...@ruby-lang.org
Yehuda Katz wrote:
> I'd be fine with "foo".Merb:to_url as one way of accessing the
> namespace, but frankly, in most cases this is for libraries and
> frameworks to be able to scope the extent of their changes to Ruby's
> core. In that context, being able to say: "use this namespace for all of
> the following code" is quite useful.

I'm not saying it might not be useful, I just want a more fine grained
approach available to me:

http://www.sapphire-lang.org/wiki/sapphire/Selector_namespaces

Regards,

Dan

Yehuda Katz

unread,
Feb 23, 2009, 11:53:33 PM2/23/09
to ruby-core
As long as that syntax is technically parsable, it's fine with me.

-- Yehuda

2009/2/23 Daniel Berger <djbe...@gmail.com>

Yukihiro Matsumoto

unread,
Feb 24, 2009, 5:07:46 AM2/24/09
to ruby...@ruby-lang.org
Hi,

In message "Re: [ruby-core:22322] Re: YASNP (Yet Another Selector Namespace Proposal)"


on Sun, 22 Feb 2009 11:35:41 +0900, Aaron Patterson <aa...@tenderlovemaking.com> writes:

|+1 as well, but I like the block. For me, it seems to be more clear as
|to what is going on.
|
| use Merb::String => String do
| "bla blah".some_special_merb_only_method
| end
|
| "bla blah".some_special_merb_only_method # => doh! doesn't exist

+1 to have some kind of selector namespace (it's planned for 2.0
anyway), but -1 for using block (or block-like syntax) to denote
namespace scope, because

* it's not really a block
* too small granularity for namespace switching might bring confusion

I'd prefer per file namespace switching.


matz.

Yehuda Katz

unread,
Feb 24, 2009, 12:48:43 PM2/24/09
to ruby-core
Matz,

I'm fairly amused by your response. If you go back to my very first post on this topic, the OP was for file-based selector namespaces. Charlie had already hacked together a working implementation before the discussion on this list.

I agree entirely that using a block is not ideal, because it's not *actually* a block (and might make people think there are block semantics involved when there aren't actually any). The alternative I proposed (using class/method/while syntax to lexically enclose the code to use the namespace) is acceptable to me, but more granular than I think will actually be used in real life.

The salient part of my proposal is that the heavy lifting could be done at parse-time (a special call node that remembers the namespace or a special call instruction with the namespaces in it when compiled) and then cached, so that a namespaced call would be roughly the same speed (and cachability) as a regular method call.

-- Yehuda

2009/2/24 Yukihiro Matsumoto <ma...@ruby-lang.org>

Charles Oliver Nutter

unread,
Feb 24, 2009, 1:03:20 PM2/24/09
to ruby...@ruby-lang.org
Yukihiro Matsumoto wrote:
> +1 to have some kind of selector namespace (it's planned for 2.0
> anyway), but -1 for using block (or block-like syntax) to denote
> namespace scope, because
>
> * it's not really a block
> * too small granularity for namespace switching might bring confusion
>
> I'd prefer per file namespace switching.

I think it's impossible to have per-file without making "use" a special
keyword, ideally at the top of the file. The block syntax made more
sense to me because I knew exactly when it started and ended, and a
'use' later in the file did not affect code that came before it. Also,
the example where I have both a namespace and a 'use' in the same file
would be impossible if the use applied to the whole file.

I'm willing to mock up anything else we want to try, including a
whole-file version.

- Charlie

Yehuda Katz

unread,
Feb 24, 2009, 1:12:26 PM2/24/09
to ruby-core
I don't think it's important that it be at the top of the file, but it does need to be a keyword.

-- Yehuda

2009/2/24 Charles Oliver Nutter <charles...@sun.com>

Ondrej Bilka

unread,
Feb 24, 2009, 5:00:48 PM2/24/09
to ruby...@ruby-lang.org
+1 to per-file
block would only give some superflows intendation.
use Foo:A do
use Bar:B do
use Baz:C do
some
code
end
end
end

--

those damn raccoons!

Brian Ford

unread,
Feb 24, 2009, 5:04:34 PM2/24/09
to ruby...@ruby-lang.org

In general, I think selector namespaces are a bad idea, even if they
are planned for 2.0. :( Rather than trying to argue persuasively for
my opinion, I'll throw out a couple things to think about.

In implementing Rubinius, we have only encountered one major issue
with redefining a core library method: mathn changing Fixnum#/.

At least as important (if not more) as seeing what a language feature
makes easy is seeing what a language feature makes hard. What will it
look like in code when folks inevitable try to work around the fences
you erect with your selector namespaces? They will try to work around
them.

Engineering software by trying to protect against the invisible,
unknowable, purely speculative demons that lurk in some future world
leads to horrible languages and even worse software. One of the things
Ruby has going for it is some very good software that judiciously
changes assumptions made at the time other software/code was written.

I would urge everyone to attempt to truly understand what sort of Ruby
software will be created with selector namespaces.

Cheers,
Brian

Charles Oliver Nutter

unread,
Feb 24, 2009, 5:21:41 PM2/24/09
to ruby...@ruby-lang.org
Ondrej Bilka wrote:
> +1 to per-file
> block would only give some superflows intendation.
> use Foo:A do
> use Bar:B do
> use Baz:C do
> some
> code
> end
> end
> end

This could certainly be simplified. I'm also leaning toward "using" and
making the body more like a class body, so it doesn't appear to be a
real block:

using Foo::A, Bar::B, Baz::C
some
code
end

- Charlie

Eero Saynatkari

unread,
Feb 24, 2009, 5:53:36 PM2/24/09
to ruby...@ruby-lang.org
Excerpts from brixen's message of Wed Feb 25 00:04:34 +0200 2009:

> In implementing Rubinius, we have only encountered one major issue
> with redefining a core library method: mathn changing Fixnum#/.

In addition to overriding, selectors can be used for adding (and,
if implemented file-/block-wise, deleting.)

> At least as important (if not more) as seeing what a language feature
> makes easy is seeing what a language feature makes hard. What will it
> look like in code when folks inevitable try to work around the fences
> you erect with your selector namespaces? They will try to work around
> them.
>
> Engineering software by trying to protect against the invisible,
> unknowable, purely speculative demons that lurk in some future world
> leads to horrible languages and even worse software. One of the things
> Ruby has going for it is some very good software that judiciously
> changes assumptions made at the time other software/code was written.

I think the two paragraphs contrast a bit :)

However, to offer an alternative consideration, how about a real
mechanism for "unrequiring" and/or "unextending"? Particularly the
non-methodwise variants of selector namespaces could very well be
replaced by being able to (really) activate and deactivate files
or modules at runtime.

Yehuda Katz

unread,
Feb 24, 2009, 6:17:34 PM2/24/09
to ruby-core


2009/2/24 Eero Saynatkari <rub...@kittensoft.org>

Excerpts from brixen's message of Wed Feb 25 00:04:34 +0200 2009:
> In implementing Rubinius, we have only encountered one major issue
> with redefining a core library method: mathn changing Fixnum#/.

In addition to overriding, selectors can be used for adding (and,
if implemented file-/block-wise, deleting.)

Frankly, the proposal is completely unrelated to something you would have encountered while implementing Rubinius. By definition, the core classes are globally available, and not suitable for selector namespacing.
 
> At least as important (if not more) as seeing what a language feature
> makes easy is seeing what a language feature makes hard. What will it
> look like in code when folks inevitable try to work around the fences
> you erect with your selector namespaces? They will try to work around
> them.

The proposal really does not erect any kind of fences. It establishes some core extensions for use only inside of a specific file. Nothing stops users from reopening the namespaces (in the proposal, they are simple modules) and modifying the methods. Likewise, nothing stops users from using the namespaces in their own code. There is nothing in the proposal designed to block users from doing what they want.
 
> Engineering software by trying to protect against the invisible,
> unknowable, purely speculative demons that lurk in some future world
> leads to horrible languages and even worse software. One of the things
> Ruby has going for it is some very good software that judiciously
> changes assumptions made at the time other software/code was written.

The proposal is based on real-life problems faced by real-life users using real-life frameworks. I captured the use-case in the OP (Rails and Merb both defining String#camel_case), which has actually bitten real users trying to use Merb with ActiveRecord.
 


I think the two paragraphs contrast a bit :)

However, to offer an alternative consideration, how about a real
mechanism for "unrequiring" and/or "unextending"? Particularly the
non-methodwise variants of selector namespaces could very well be
replaced by being able to (really) activate and deactivate files
or modules at runtime.

unrequiring is actually more complex of a feature to implement with no additional benefits that I can see. unextending doesn't solve the problem at all (except to provide a slow and extremely awkward way to emulate the feature on an object-by-object basis).
 
The proposal is actually fairly straight-forward, relatively simple to implement, and does not introduce any "barriers" for users at all.

--
Magic is insufficiently advanced technology.

Charles Oliver Nutter

unread,
Feb 24, 2009, 6:18:04 PM2/24/09
to ruby...@ruby-lang.org
Eero Saynatkari wrote:
> However, to offer an alternative consideration, how about a real
> mechanism for "unrequiring" and/or "unextending"? Particularly the
> non-methodwise variants of selector namespaces could very well be
> replaced by being able to (really) activate and deactivate files
> or modules at runtime.

Unrequiring and unextending make global changes. I think the selector
namespace ideas being bandied about are a nice way to hook calls within
a given context without invading core classes or making global changes
that could break other people's code. In truth, I think good selector
namespace could actually reduce the need for and danger of
monkeypatching, since you can make safe localized changes.

If I were to mock up a proposal, which one should I go with first?
Someone propose me a spec.

- Charlie

Charles Oliver Nutter

unread,
Feb 24, 2009, 7:12:03 PM2/24/09
to ruby...@ruby-lang.org
Yehuda Katz wrote:
> * "use" is scoped
> * no special namespace keyword; any module can be a namespace
> * use Merb::String for String
> * use Merb::* (equivalent to Merb.constants.each {|k| use k for
> k.split("::", 2).last.constantize })

Here's a new mock-up of this behavior in JRuby (without making parser
modifications that would certainly clean it up more):

{{
module Foo
module Bar
def to_s
puts 'inside namespace: ' + to_s
'blah'
end
end
end

using Foo::Bar => String

puts 'hello'.to_s
puts 1.to_s

#output:

inside namespace: hello
blah
1
}}

The improvements here are the use of a hash to associate a namespace
with a specific class, only applying the namespaces that map to the
target object's class, and (behind the scenes) resetting namespaces at
the end of the file. So the "using" flips them on, and the end of the
file flips them off. Multiple are also possible:

{{
module Foo
module Bar
def to_s
puts 'string namespace'
end
end
end
module Blah
def to_s
puts 'fixnum namespace'
end
end

using Foo::Bar => String
using Blah => Fixnum

'hello'.to_s
1.to_s

#output:

string namespace
fixnum namespace
}}

Again, this is only hacked for these specific call types, namely an
fcall with no block (for "using" to capture namespaces) and a call with
no args and no block (for the to_s calls).

Patch against JRuby trunk is attached as an example.

- Charlie

more_selector_namespaces.patch

Yehuda Katz

unread,
Feb 24, 2009, 8:03:12 PM2/24/09
to ruby-core
Big +1 Charlie!

One of the things that appealed to me about the original proposal was that it seemed likely to be implementable without massive changes to Ruby, while still supporting everything that is actually needed in selector namespaces without sacrificing performance. With this mock-up, Charlie is at least showing that it's not terrifically hard as a first approximation. :-D

-- Yehuda

2009/2/24 Charles Oliver Nutter <charles...@sun.com>
Yehuda Katz wrote:
diff --git a/src/org/jruby/ast/CallNoArgNode.java b/src/org/jruby/ast/CallNoArgNode.java
index 1b2cd40..081e1f0 100644
--- a/src/org/jruby/ast/CallNoArgNode.java
+++ b/src/org/jruby/ast/CallNoArgNode.java
@@ -32,8 +32,12 @@
 ***** END LICENSE BLOCK *****/
 package org.jruby.ast;

+import java.util.List;
 import org.jruby.Ruby;
+import org.jruby.RubyArray;
 import org.jruby.RubyClass;
+import org.jruby.RubyHash;
+import org.jruby.RubyModule;
 import org.jruby.exceptions.JumpException;
 import org.jruby.internal.runtime.methods.DynamicMethod;
 import org.jruby.lexer.yacc.ISourcePosition;
@@ -46,19 +50,48 @@ import org.jruby.runtime.builtin.IRubyObject;
 * A method or operator call.
 */
 public final class CallNoArgNode extends CallNode {
+    List<Node> namespaces;
    // For 'b.foo'
    public CallNoArgNode(ISourcePosition position, Node receiverNode, String name) {
        super(position, receiverNode, name, null, null);
    }
+
+    // For 'b.foo()'.  Args are only significant in maintaining backwards compatible AST structure
+    public CallNoArgNode(ISourcePosition position, Node receiverNode, String name, List<Node> namespaces) {
+        super(position, receiverNode, name, null, null);
+        this.namespaces = namespaces;
+    }

    // For 'b.foo()'.  Args are only significant in maintaining backwards compatible AST structure
    public CallNoArgNode(ISourcePosition position, Node receiverNode, Node args, String name) {
        super(position, receiverNode, name, args, null);
    }
+
+    // For 'b.foo()'.  Args are only significant in maintaining backwards compatible AST structure
+    public CallNoArgNode(ISourcePosition position, Node receiverNode, Node args, String name, List<Node> namespaces) {
+        super(position, receiverNode, name, args, null);
+        this.namespaces = namespaces;
+    }

    @Override
    public IRubyObject interpret(Ruby runtime, ThreadContext context, IRubyObject self, Block aBlock) {
-        return callAdapter.call(context, self, getReceiverNode().interpret(runtime, context, self, aBlock));
+        IRubyObject receiver = getReceiverNode().interpret(runtime, context, self, aBlock);
+        if (namespaces != null) {
+            DynamicMethod method = null;
+            for (Node node : namespaces) {
+                IRubyObject namespace = ((RubyArray)node.interpret(runtime, context, self, aBlock)).eltInternal(0);
+                RubyModule nsModule = ((RubyModule)((RubyHash)namespace).keys().eltInternal(0));
+                RubyClass targetClass = (RubyClass)((RubyHash)namespace).rb_values().eltInternal(0);
+                if (targetClass == receiver.getMetaClass()) {
+                    method = nsModule.searchMethod(callAdapter.methodName);
+                    if (method != null && !method.isUndefined()) break;
+                }
+            }
+            if (method != null && !method.isUndefined()) {
+                return method.call(context, receiver, self.getMetaClass(), callAdapter.methodName);
+            }
+        }
+        return callAdapter.call(context, self, receiver);
    }

    @Override
diff --git a/src/org/jruby/parser/ParserSupport.java b/src/org/jruby/parser/ParserSupport.java
index f3d9b97..267b54b 100644
--- a/src/org/jruby/parser/ParserSupport.java
+++ b/src/org/jruby/parser/ParserSupport.java
@@ -35,6 +35,8 @@
 ***** END LICENSE BLOCK *****/
 package org.jruby.parser;

+import java.util.ArrayList;
+import java.util.List;
 import org.jruby.ast.AndNode;
 import org.jruby.ast.ArgsPreOneArgNode;
 import org.jruby.ast.ArgsPreTwoArgNode;
@@ -182,6 +184,8 @@ public class ParserSupport {
    private ParserConfiguration configuration;
    private RubyParserResult result;

+    private List namespaces = new ArrayList();
+
    public void reset() {
        inSingleton = 0;
        inDefinition = false;
@@ -192,6 +196,10 @@ public class ParserSupport {
            throw new SyntaxException(PID.DUBY_EXTENSIONS_OFF, position, "Duby extensions not configured");
        }
    }
+
+    public List getNamespaces() {
+        return namespaces;
+    }

    public StaticScope getCurrentScope() {
        return currentScope;
@@ -922,8 +930,12 @@ public class ParserSupport {
        if (receiver == null) receiver = NilImplicitNode.NIL;

        if (iter != null) return new CallNoArgBlockNode(position, receiver, (String) name.getValue(), iter);
-
-        return new CallNoArgNode(position, receiver, (String) name.getValue());
+
+        if (namespaces.size() > 0) {
+            return new CallNoArgNode(position, receiver, (String) name.getValue(), namespaces);
+        } else {
+            return new CallNoArgNode(position, receiver, (String) name.getValue());
+        }
    }

    private Node new_call_complexargs(Node receiver, Token name, Node args, Node iter) {
@@ -972,8 +984,12 @@ public class ParserSupport {
        switch (args.size()) {
            case 0:
                if (iter != null) return new CallNoArgBlockNode(union(receiver, args), receiver, (String) name.getValue(), args, (IterNode) iter);
-
-                return new CallNoArgNode(union(receiver, args), receiver, args, (String) name.getValue());
+
+                if (namespaces.size() > 0) {
+                    return new CallNoArgNode(union(receiver, args), receiver, args, (String) name.getValue(), namespaces);
+                } else {
+                    return new CallNoArgNode(union(receiver, args), receiver, args, (String) name.getValue());
+                }
            case 1:
                if (iter != null) return new CallOneArgBlockNode(union(receiver, args), receiver, (String) name.getValue(), args, (IterNode) iter);

@@ -1014,6 +1030,14 @@ public class ParserSupport {

    private Node new_fcall_simpleargs(Token operation, ArrayNode args, Node iter) {
        String name = (String) operation.getValue();
+
+        // it if's a "using" call add a namespace and return a nil node
+        if (name.equals("using")) {
+            namespaces.add(args);
+            return new NilNode(union(operation, args));
+        }
+
+        // otherwise, if we have a namespace, pass it into the FCall

        switch (args.size()) {
            case 0:  // foo()

Brian Ford

unread,
Feb 24, 2009, 8:05:50 PM2/24/09
to ruby...@ruby-lang.org
On Feb 24, 3:17 pm, Yehuda Katz <wyc...@gmail.com> wrote:
> 2009/2/24 Eero Saynatkari <ruby...@kittensoft.org>

You have misunderstood my point. I'm not saying you don't have a
problem. I'm saying selector namespaces will be used in the way I
indicated. And it will lead to ugly, more confusing software. You can
solve your problem without selector namespaces. Instead of focusing on
why you think they are a good idea, I suggest considering how they can
be misused.

All you are saying is you want a way to define methods on the same
class with the same name but different behaviors, where the particular
method called is selected by context. I get it. I think it's a bad
idea.

Brian

Yehuda Katz

unread,
Feb 24, 2009, 8:13:42 PM2/24/09
to ruby-core


2009/2/24 Brian Ford <bri...@gmail.com>

What way is that exactly?
 

Jim Deville

unread,
Feb 24, 2009, 11:29:17 PM2/24/09
to ruby...@ruby-lang.org

I agree that this will be used in ways other than just framework creators. Rails and Merb may not use this to erect fences, but someone will. I think that before we go gung-ho on this, there should be a Devil’s advocate discussion of how one could misuse this feature, and how it could cause problems. The problems may not warrant dropping the idea, they may just help see issues with it. I think that is a really good exercise that we should do.

 

As an example, what if I am using Merb, and two plugins, which all define a namespaced method, which I want to change. That’s three namespaces that I have to __know about__ and modify. As opposed to one now.

JD

Charles Oliver Nutter

unread,
Feb 24, 2009, 11:49:27 PM2/24/09
to ruby...@ruby-lang.org
Jim Deville wrote:
> I agree that this will be used in ways other than just framework
> creators. Rails and Merb may not use this to erect fences, but someone
> will. I think that before we go gung-ho on this, there should be a
> Devil’s advocate discussion of how one could misuse this feature, and
> how it could cause problems. The problems may not warrant dropping the
> idea, they may just help see issues with it. I think that is a really
> good exercise that we should do.
>
> As an example, what if I am using Merb, and two plugins, which all
> define a namespaced method, which I want to change. That’s three
> namespaces that I have to __know about__ and modify. As opposed to one now.

Going out and changing (monkeypatching) libraries (or namespaces)
willy-nilly is what called for something more localized to begin with.
I've yet to see a case that monkeypatching makes simpler or easier, and
this is no different.

I think it's a question of what sort of pain you bring on yourself. If
you monkeypatch libraries, and someone else's patch conflicts, you both
deserve to get your knuckles rapped. If you monkeypatch someone else's
module and it leads to more complicated code or eventual bugs, you
deserve to get your knuckles rapped.

If anything, the namespace proposal is vastly safer than monkeypatching
to begin with...so much so that it could probably take over most of
monkeypatching's use cases, leading to *better* code.

I understand the concern, but anyone arguing that "feature X combined
with monkeypatching is too dangerous/confusing/complicated" should
probably consider whether it's monkeypatching's fault in the first place.

- Charlie

Jim Weirich

unread,
Feb 24, 2009, 11:53:21 PM2/24/09
to ruby...@ruby-lang.org

On Feb 24, 2009, at 11:29 PM, Jim Deville wrote:

> As an example, what if I am using Merb, and two plugins, which all
> define a namespaced method, which I want to change. That's three
> namespaces that I have to __know about__ and modify. As opposed to
> one now.

I must admit, I'm a little confused by the above. Maybe we have
different understandings about what selector namespaces are and what
they do.

If three plugins each define a method named "xyz" in different
modules, you have three different methods in three modules. Adding
namespaces doesn't change that. All the namespace does is allow
programmers to say "Over this section of code, calling a method named
'xyz' will come from this module rather than that module."

Could some elaborate about their fears of name spaces creating
fences. I don't quite understand what they are getting at.

Thanks.

--
-- Jim Weirich
-- jim.w...@gmail.com


Jim Deville

unread,
Feb 25, 2009, 12:13:30 AM2/25/09
to ruby...@ruby-lang.org

> -----Original Message-----
> From: Jim Weirich [mailto:jim.w...@gmail.com]
> Sent: Tuesday, February 24, 2009 8:53 PM
> To: ruby...@ruby-lang.org
> Subject: [ruby-core:22448] Re: YASNP (Yet Another Selector Namespace
> Proposal)
>
>

Clarification of my example: If three namespaces define xyz, and you want all of the xyz's to act differently, then you need to modify three namespaces with monkeypatching. This way you change their effects wherever you use them.

Rebuttal of my example: As pointed out by Charlie here and offlist, the proper way to handle this conflict of namespaces is to create your own namespace that does what you want.

Overall, the example wasn't my major point, my point was in asking the same community that is lively about this discussion, and very creative (just see the Ruby projects in existence), to come up with ways that this can be misused. Throw them out there so we can see if there is a large downside. I don't know if there is. This example wasn't meant to prove it wrong, just to give an idea.

I guess this kind of falls under bikeshedding, but I think that it is valid to partake in some of this kind of brainstorming before this, or any, proposal is accepted.

JD

Yehuda Katz

unread,
Feb 25, 2009, 12:17:37 AM2/25/09
to ruby...@ruby-lang.org
I'm also in favor of discussing this, but all I hear so far in opposition is vague FUD... no specific examples of problems that could be caused. It would be a lot easier to have a lively discussion about specific concerns, and I'd love to have it!

-- Yehuda

Jim Weirich

unread,
Feb 25, 2009, 12:20:56 AM2/25/09
to ruby...@ruby-lang.org
On Feb 25, 2009, at 12:13 AM, Jim Deville wrote:

> I guess this kind of falls under bikeshedding, but I think that it
> is valid to partake in some of this kind of brainstorming before
> this, or any, proposal is accepted.


That's why Charlie's prototyping is so important. Once we have real
code to play with, we can have concrete examples of problems rather
than vague fears about fences.

Charles Oliver Nutter

unread,
Feb 25, 2009, 12:32:09 AM2/25/09
to ruby...@ruby-lang.org
Jim Weirich wrote:
> That's why Charlie's prototyping is so important. Once we have real
> code to play with, we can have concrete examples of problems rather than
> vague fears about fences.

If folks are interested in playing with it more, I could expand it to
cover all call, fcall, and vcall forms. It would be easier to experiment
in a general way then.

- Charlie

Yehuda Katz

unread,
Feb 25, 2009, 1:11:48 AM2/25/09
to ruby-core
I'd like that a lot :)

-- Yehuda

2009/2/24 Charles Oliver Nutter <charles...@sun.com>
Jim Weirich wrote:

Ondrej Bilka

unread,
Feb 25, 2009, 2:21:46 AM2/25/09
to ruby...@ruby-lang.org
On Wed, Feb 25, 2009 at 01:12:03AM +0100, Charles Oliver Nutter wrote:
> Here's a new mock-up of this behavior in JRuby (without making parser
> modifications that would certainly clean it up more):
>
> {{
> module Foo
> module Bar
> def to_s
> puts 'inside namespace: ' + to_s
> 'blah'
> end
> end
> end
>
> using Foo::Bar => String
>
> puts 'hello'.to_s
> puts 1.to_s
>
> #output:
>
> inside namespace: hello
This code should output inside namespace: inside namespace: inside namespace: inside namespace: inside namespace: inside namespace: ...
> blah
> 1
> }}
>

--

boss forgot system password

Charles Oliver Nutter

unread,
Feb 25, 2009, 2:30:24 AM2/25/09
to ruby...@ruby-lang.org
Yehuda Katz wrote:
> I'd like that a lot :)

Here's a patch that extends it at least to all forms of CallNode, which
is probably the primary case. fcalls and vcalls are against self, and
will probably be less common to namespace. attr/op/element assignments
will probably be rare for similar reasons. But they'd probably all need
similar treatment.

This patch is a bit bigger and messier, but still only about a half
hour's work. A better design would be to enlist the parser in this
process. It would also produce better-performing code; I don't expect
this version to perform particularly well.

I've also attached a really primitive rspec that shows "using" inside an
eval. In the current prototype, using is scoped to the eval body as if
it were a file. I kinda like it.

- Charlie

more_selector_namespaces_2.patch
namespace_spec.rb

Charles Oliver Nutter

unread,
Feb 25, 2009, 2:32:26 AM2/25/09
to ruby...@ruby-lang.org

The namespace applies from that point forward; the original Foo::Bar
module is unaffected.

This could be modified to be for a full file, but it would require more
parser help and ideally would have to be at the top of the file.

- Charlie

Yukihiro Matsumoto

unread,
Feb 25, 2009, 3:07:29 AM2/25/09
to ruby...@ruby-lang.org
Hi,

In message "Re: [ruby-core:22427] Re: YASNP (Yet Another Selector Namespace Proposal)"


on Wed, 25 Feb 2009 07:04:34 +0900, Brian Ford <bri...@gmail.com> writes:

|In implementing Rubinius, we have only encountered one major issue
|with redefining a core library method: mathn changing Fixnum#/.

Interesting. I thought people behind Rubinius would love (or even
demand) some kind of selector namespace, to protect their core
libraries from users' monkey patching.

matz.

Yehuda Katz

unread,
Feb 25, 2009, 3:26:30 AM2/25/09
to ruby-core
To be honest, I'm not sure what Rubinius' experience has anything to do with the desire for namespacing. I could see why it would be useful for *users* of Rubinius, but as there aren't any users, yet, the issues that would likely cause them to want some kind of selector namespaces would not have come up yet. On the other hand, conflicts between Rails and Merb (or more realistically, Merb and ActiveRecord) have already happened in the wild, and have clearly illustrated the real-life need for something like this.

I'm really interested in a *real* example of the fears people have about this feature. So far all I've seen is vague fearmongering...

-- Yehuda

2009/2/25 Yukihiro Matsumoto <ma...@ruby-lang.org>

Florian Gilcher

unread,
Feb 25, 2009, 3:47:27 AM2/25/09
to ruby...@ruby-lang.org

On Feb 25, 2009, at 6:17 AM, Yehuda Katz wrote:

I'm also in favor of discussing this, but all I hear so far in opposition is vague FUD... no specific examples of problems that could be caused. It would be a lot easier to have a lively discussion about specific concerns, and I'd love to have it!

-- Yehuda

Is FUD the new "the opposition doesn't convince me"? I hear it a lot. I think it's overused. Also, I find it insulting or at least a "verbal" fauxpas as well as misplaced[1].

The problem is rather obvious: suddently, I can have multiple definitions of a method (or none!) depending on context. Nowadays, i can just inspect/test that behaviour in IRB/rdb and be sure that it is about the same everywhere (safe for the unusual catch that it could be un/redefined along the way). With selector namespaces, that catch would get commonplace. 
This could be fixed by additional inspection facilities, but it _is_ an additional layer of complexity (and not a small one). I also don't buy the "no one will use it" argument. Back when I started learning Ruby, I heard the same about redefining/extending core methods/objects. Nowadays, you cannot find a lib that doesn't have it's small extension to Object.

BTW: how will IRB handle file-based switches? 

In favor of the proposal, I also want to construct explain a case where I always missed it. Take ActiveRecord or DataMapper. The objects usually get passed into a template (a completely different context) where most of the methods are not intended to be used (#find being the common case, basically everything that does Database operations explicitly). The uninitiated (TM) still use them, causing all kinds of problems to the initiated (TM).

Some frameworks I know (mostly PHP) solve this problem by hydrating the database objects to an array before handing them over to the view. With selector namespaces, there would be an easy fix for this: let the view be a evaluted in a different Namespace. This would also allow for "convenience methods" to be added in the view exclusively.

Regards,
Florian

[1]: FUD stands for a marketing strategy after all. There is no market at ruby-core. And we are not corporate goons trying to keep you from something.
 
--
Florian Gilcher

gpg:    533148E2

Eero Saynatkari

unread,
Feb 25, 2009, 4:36:14 AM2/25/09
to ruby...@ruby-lang.org
Excerpts from Yukihiro Matsumoto's message of Wed Feb 25 10:07:29 +0200 2009:

Selector namespaces was and probably still is a planned feature; if
Ruby has it, the better. It is not really for strict protection,
there are other mechanisms for that, but it would be cleaner from
the user's point of view.

Michal Suchanek

unread,
Feb 25, 2009, 8:49:07 AM2/25/09
to ruby...@ruby-lang.org
2009/2/25 Florian Gilcher <f...@andersground.net>:
>

> BTW: how will IRB handle file-based switches?

This is a clear use case for fine-grained control of namespaces. You
may want to run a single call or block inside of particular
combination of namespaces for debugging or testing.

Also exceptions should carry the namespace combination in which the
failure occured and you should be able to tell what namespaces you are
using at any point in your code.

Thanks

Michal

Yehuda Katz

unread,
Feb 25, 2009, 11:31:31 AM2/25/09
to ruby-core


2009/2/25 Florian Gilcher <f...@andersground.net>


On Feb 25, 2009, at 6:17 AM, Yehuda Katz wrote:

I'm also in favor of discussing this, but all I hear so far in opposition is vague FUD... no specific examples of problems that could be caused. It would be a lot easier to have a lively discussion about specific concerns, and I'd love to have it!

-- Yehuda

Is FUD the new "the opposition doesn't convince me"? I hear it a lot. I think it's overused. Also, I find it insulting or at least a "verbal" fauxpas as well as misplaced[1].

Apologies.
 
The problem is rather obvious: suddently, I can have multiple definitions of a method (or none!) depending on context. Nowadays, i can just inspect/test that behaviour in IRB/rdb and be sure that it is about the same everywhere (safe for the unusual catch that it could be un/redefined along the way). With selector namespaces, that catch would get commonplace. 

Not really... because the namespaces would need to be specified on a per-file basis (as per Matz), it would be trivial to go into a file and determine which namespaces were in use. Remember, this is not a global facility, it's per-file facility that must be explicitly invoked. It's also not the case that when *I* invoke a selector namespace in my library code, it effects your library code or your app.
 
This could be fixed by additional inspection facilities, but it _is_ an additional layer of complexity (and not a small one). I also don't buy the "no one will use it" argument. Back when I started learning Ruby, I heard the same about redefining/extending core methods/objects. Nowadays, you cannot find a lib that doesn't have it's small extension to Object.

It's not really relevant if people will use it, because it must be explicitly invoked. In other words, someone else can't invoke a selector namespace on your code. I think the most common use-case will likely be frameworks and libraries, but if you want to extend string for the duration of your application, and explicitly include the namespace into your files, that doesn't bother me. In short, it doesn't seem as complex as people are making it out to seem, or even more complex than facilities we have in Ruby today.
 
BTW: how will IRB handle file-based switches? 

I'd assume that namespaces would apply to the rest of the IRB session. Perhaps a "using nil" could be specified to deactivate namespaces.
 
In favor of the proposal, I also want to construct explain a case where I always missed it. Take ActiveRecord or DataMapper. The objects usually get passed into a template (a completely different context) where most of the methods are not intended to be used (#find being the common case, basically everything that does Database operations explicitly). The uninitiated (TM) still use them, causing all kinds of problems to the initiated (TM).

Some frameworks I know (mostly PHP) solve this problem by hydrating the database objects to an array before handing them over to the view. With selector namespaces, there would be an easy fix for this: let the view be a evaluted in a different Namespace. This would also allow for "convenience methods" to be added in the view exclusively.

It wouldn't really work that way, unless you explicitly removed methods from the global ActiveRecord and only made them available in a specific namespace. Even then, it would be trivial to include the namespace in question into the templates.
 
Regards,
Florian

[1]: FUD stands for a marketing strategy after all. There is no market at ruby-core. And we are not corporate goons trying to keep you from something.

Hehe... Perhaps a strong term. I was trying to get across that the objections were vague, and in the interest of a vibrant discussion, I was hoping for some clear examples that would be so complex as to justify the derision. After all, Ruby is not a particularly simple language; instead, it aims to be NATURAL.
 
 
--
Florian Gilcher

gpg:    533148E2

Yukihiro Matsumoto

unread,
Feb 25, 2009, 11:59:05 AM2/25/09
to ruby...@ruby-lang.org
Hi,

In message "Re: [ruby-core:22460] Re: YASNP (Yet Another Selector Namespace Proposal)"


on Wed, 25 Feb 2009 17:47:27 +0900, Florian Gilcher <f...@andersground.net> writes:

|BTW: how will IRB handle file-based switches?

Good point.

Brian Ford

unread,
Feb 25, 2009, 12:23:03 PM2/25/09
to ruby...@ruby-lang.org
On Feb 24, 9:17 pm, Yehuda Katz <wyc...@gmail.com> wrote:
> I'm also in favor of discussing this, but all I hear so far in opposition is
> vague FUD... no specific examples of problems that could be caused. It would
> be a lot easier to have a lively discussion about specific concerns, and I'd
> love to have it!
> -- Yehuda
>

Seems Google ate my reply to this.

Apparently my thought experiment on possible misuses is too difficult.
Here is a concrete alternative exercise. What are the principles for
using selector namespaces?

When do you put one method in? If one method, why not two? Where are
the boundaries in a library, framework or application?

The essence of my objection is that you will so cleverly put into a SN
a method that someone else will want to change.

Again, there has been no justification for why SNs are *needed* to
solve the problem presented here. You want to have multiple methods
with the same name on the same public, common class but with different
behaviors. There is no justification for why #chars or #camel_case
*must* have different behaviors.

You think, "I'm so smart about programming my app, no one will want to
monkey patch this method." But they will! Just as they have done in
Ruby for a long time. And when they do, what will that look like? And
when you try to understand the behavior of some software, you now need
to look into N different definitions of one method name and determine
how those interact.

Complexity for what benefit? How is this more natural? And it is not
just in one file. There is no restriction of a class to one file in
Ruby. Open class gives the ability to build software in layers.

The following applies just as well to engineering software and
designing languages as to building furniture: http://www.johndilworth.com/95.

Brian

> > > -- jim.weir...@gmail.com

Brian Ford

unread,
Feb 25, 2009, 12:32:06 PM2/25/09
to ruby...@ruby-lang.org

Hi Matz,

On the contrary, I have strongly argued for Rubinius to be accessible
and modifiable to the deepest levels since hearing Evan's comment
about Rubinius kinda having evil built in. Of course it can be
misused, just as I can load a segfaulting C extension into MRI.

The case of mathn and Fixnum#/ is an anomaly IMO. Had there not been
the distinction between methods in C and methods in Ruby, mathn would
not have been written that way. Perhaps redesigning the Numeric tower
so that real number math was the default.

I understand how selector namespaces can be used. My concern is that
they can be misused in a way that makes software harder to understand
or that requires an even stronger antidote than monkey patching to
work around someone's well-intentioned assumptions that may be invalid
in a different context.

Considering the possible unintended consequences isn't FUD, it's a
sincere effort to maintain the quality of Ruby software and the
enjoyment of writing it.

Cheers,
Brian

Radosław Bułat

unread,
Feb 25, 2009, 12:38:26 PM2/25/09
to ruby...@ruby-lang.org
Yehuda, I wonder on one thing. If you want in your framework/library
custom method behavior, for example String#foo and you want only use
it inside framework/library why not just put it somewhere inside
framework class? For example instead:
"bar".foo

just do this:
MyFramework.foo("bar")

?

The second is even cleaner and says clearly what method you call.
Using NS you must remember which method you imported to file and which
not.


--
Pozdrawiam

Radosław Bułat
http://radarek.jogger.pl - mój blog

Brent Roman

unread,
Feb 25, 2009, 1:08:46 PM2/25/09
to ruby...@ruby-lang.org

At least regarding blocks vs. a special keyword:

There may be a middle way

If the parser were modified such that upon encountering the
EOF token, it terminated the current do/end block, then
:use could be a normal Kernel method that simply takes block,
without introducing spurious indentation.

use MyWorld do
....
<EOF>

This also allows quite handy expressions such as:

ruby -e "3.times do print 'Howdy, '"

or

eval "3.times do print 'Howdy, '"

There is still the question of whether EOF should terminate nested
do style blocks in order to handle:

use MyWorld do
use OtherWorld do
.....
<EOF>

This parser change certainly is easy to implement.
And, it cannot break any working code.

- brent


Charles Oliver Nutter-2 wrote:
>
> Yukihiro Matsumoto wrote:
>> +1 to have some kind of selector namespace (it's planned for 2.0
>> anyway), but -1 for using block (or block-like syntax) to denote
>> namespace scope, because
>>
>> * it's not really a block
>> * too small granularity for namespace switching might bring confusion
>>
>> I'd prefer per file namespace switching.
>
> I think it's impossible to have per-file without making "use" a special
> keyword, ideally at the top of the file. The block syntax made more
> sense to me because I knew exactly when it started and ended, and a
> 'use' later in the file did not affect code that came before it. Also,
> the example where I have both a namespace and a 'use' in the same file
> would be impossible if the use applied to the whole file.
>
> I'm willing to mock up anything else we want to try, including a
> whole-file version.
>
> - Charlie
>
>
>

--
View this message in context: http://www.nabble.com/-ruby-core%3A22246--YASNP-%28Yet-Another-Selector-Namespace-Proposal%29-tp22094654p22208463.html
Sent from the ruby-core mailing list archive at Nabble.com.


Yehuda Katz

unread,
Feb 25, 2009, 1:23:18 PM2/25/09
to ruby-core
You end up needing to do:

Extlib::String.constantize(Extlib::String.to_path(Extlib::String.underscore(str)))

instead of:

str.underscore.to_path.constantize

Honestly, we tried this in DataMapper for a while, but it got too bulky to be realistic (outside of Java, I suppose).

-- Yehuda

2009/2/25 Radosław Bułat <radek...@gmail.com>

Yehuda Katz

unread,
Feb 25, 2009, 1:28:44 PM2/25/09
to ruby-core


2009/2/25 Brian Ford <bri...@gmail.com>

On Feb 24, 9:17 pm, Yehuda Katz <wyc...@gmail.com> wrote:
> I'm also in favor of discussing this, but all I hear so far in opposition is
> vague FUD... no specific examples of problems that could be caused. It would
> be a lot easier to have a lively discussion about specific concerns, and I'd
> love to have it!
> -- Yehuda
>

Seems Google ate my reply to this.

Apparently my thought experiment on possible misuses is too difficult.
Here is a concrete alternative exercise. What are the principles for
using selector namespaces?

When do you put one method in? If one method, why not two? Where are
the boundaries in a library, framework or application?

You put any core extensions that you don't want to automatically expose globally into your namespace. Then you use that namespace in your library.
 
The essence of my objection is that you will so cleverly put into a SN
a method that someone else will want to change.

And? I'm not sure we're talking about the same thing. In the proposal, namespaces are just regular modules. They can be reopened and modified at will, just like normal Ruby.
 
Again, there has been no justification for why SNs are *needed* to
solve the problem presented here. You want to have multiple methods
with the same name on the same public, common class but with different
behaviors. There is no justification for why #chars or #camel_case
*must* have different behaviors.

We can just observe the *reality*. In *reality* Merb, DataMapper, and Rails were all using the same names to mean subtly different things. I included one such example in the OP. The only way to avoid this is a massive coordination effort on the part of every library doing core extensions, which has so far proven unrealistic, even with the relatively small number of popular libraries we have today.
 
You think, "I'm so smart about programming my app, no one will want to
monkey patch this method."

That really has nothing to do with the proposal. People can happily monkey-patch anything they want.
 
But they will! Just as they have done in
Ruby for a long time. And when they do, what will that look like? And
when you try to understand the behavior of some software, you now need
to look into N different definitions of one method name and determine
how those interact.

Why? How? You look at the software. There either is or is not a "using" declaration present. If there is not, Ruby behaves as it does today. If there is, it adds some additional behavior. How is this significantly different from the (much more ambiguous) changes that can be made via module inclusion?
 
Complexity for what benefit? How is this more natural? And it is not
just in one file. There is no restriction of a class to one file in
Ruby. Open class gives the ability to build software in layers.

What? The proposal lexically scopes the new behavior. It has nothing to do with open classes...
 
The following applies just as well to engineering software and
designing languages as to building furniture: http://www.johndilworth.com/95.

+1
 

Florian Gilcher

unread,
Feb 25, 2009, 1:31:38 PM2/25/09
to ruby...@ruby-lang.org
Yehuda is correct there. Thats the stuff you need an IDE and imports
for...

And if i wanted code like that, i'd use a functional language ;).

Regards,
Florian

Charles Oliver Nutter

unread,
Feb 25, 2009, 1:46:31 PM2/25/09
to ruby...@ruby-lang.org
Florian Gilcher wrote:
>
> On Feb 25, 2009, at 6:17 AM, Yehuda Katz wrote:
>
>> I'm also in favor of discussing this, but all I hear so far in
>> opposition is vague FUD... no specific examples of problems that could
>> be caused. It would be a lot easier to have a lively discussion about
>> specific concerns, and I'd love to have it!
>>
>> -- Yehuda
>
> Is FUD the new "the opposition doesn't convince me"? I hear it a lot. I
> think it's overused. Also, I find it insulting or at least a "verbal"
> fauxpas as well as misplaced[1].

I think the FUD here is "oh no, what if this happens or that happens and
code gets more complicated!". You can what if any feature to death, but
without considering the probability of real issues it really is FUD.

And of course the "what iffers" may not be weighing those scenarios
against the positive uses of namespaces.

> The problem is rather obvious: suddently, I can have multiple
> definitions of a method (or none!) depending on context. Nowadays, i can
> just inspect/test that behaviour in IRB/rdb and be sure that it is about
> the same everywhere (safe for the unusual catch that it could be
> un/redefined along the way). With selector namespaces, that catch would
> get commonplace.

I wanted to point out that having the following namespace:

module Foo; def to_s; 'blah'; end; end
using Foo
'hello'.to_s

Is really no different from the following code, other than being cleaner
and shorter:

module Foo; def Foo.to_s(str); 'blah'; end; end
Foo.to_s('hello')

You can't really control what any library decides to do today, so I
don't think you lose any more control with namespaces. And
monkeypatching code because you want *others* to be affected has always
been a losing proposition...since they may have monkeypatched code to
affect *you* already.

> BTW: how will IRB handle file-based switches?

It would need to have modifications to its parser logic to support
namespacing, just as it needed modifications to allow stabby lambdas
through.

- Charlie

Ola Bini

unread,
Feb 25, 2009, 1:54:10 PM2/25/09
to ruby...@ruby-lang.org
Brent Roman wrote:
> At least regarding blocks vs. a special keyword:
>
> There may be a middle way
>
> If the parser were modified such that upon encountering the
> EOF token, it terminated the current do/end block, then
> :use could be a normal Kernel method that simply takes block,
> without introducing spurious indentation.
>
> use MyWorld do
> ....
> <EOF>
>
> This also allows quite handy expressions such as:
>
> ruby -e "3.times do print 'Howdy, '"
>
> or
>
> eval "3.times do print 'Howdy, '"
>
> There is still the question of whether EOF should terminate nested
> do style blocks in order to handle:
>
> use MyWorld do
> use OtherWorld do
> .....
> <EOF>
>
> This parser change certainly is easy to implement.
> And, it cannot break any working code.
>
> - brent
>
>
Of course, this change would mask many legitimate errors where you
forget to close something deeply nested, that then will be closed by the
wrong "end" and so on. Not good at all.
I'm strongly opposed to this.

--
Ola Bini (http://olabini.com)
Ioke creator (http://ioke.org)
JRuby Core Developer (http://jruby.org)
Developer, ThoughtWorks Studios (http://studios.thoughtworks.com)
Practical JRuby on Rails (http://apress.com/book/view/9781590598818)

"Yields falsehood when quined" yields falsehood when quined.

Charles Oliver Nutter

unread,
Feb 25, 2009, 1:52:05 PM2/25/09
to ruby...@ruby-lang.org

I'm starting to think that if we don't have explicitly bounded
namespacing, there should be a way to turn it off. Like "using nil" but
not as ugly..

- Charlie

Florian Gilcher

unread,
Feb 25, 2009, 1:51:10 PM2/25/09
to ruby...@ruby-lang.org

Is FUD the new "the opposition doesn't convince me"? I hear it a lot. I think it's overused. Also, I find it insulting or at least a "verbal" fauxpas as well as misplaced[1].

Apologies.

Accepted, no hard feelings.

 
The problem is rather obvious: suddently, I can have multiple definitions of a method (or none!) depending on context. Nowadays, i can just inspect/test that behaviour in IRB/rdb and be sure that it is about the same everywhere (safe for the unusual catch that it could be un/redefined along the way). With selector namespaces, that catch would get commonplace. 

Not really... because the namespaces would need to be specified on a per-file basis (as per Matz), it would be trivial to go into a file and determine which namespaces were in use. Remember, this is not a global facility, it's per-file facility that must be explicitly invoked. It's also not the case that when *I* invoke a selector namespace in my library code, it effects your library code or your app.

Yes. I'm more about reconstruction what happens later on. Say... you have an Object A in Context C, because you have a breakpoint there. You have an assertion about a property of the object that you will use later on. You want to check that assertion _now_. But as "later on" happens to be in Context D, you assertion is true now but wrong later on.

I don't want to present this as a showstopper. But it _is_ something that can happen which couldn't happen before. It will certainly not happen to us good programmers.

 
This could be fixed by additional inspection facilities, but it _is_ an additional layer of complexity (and not a small one). I also don't buy the "no one will use it" argument. Back when I started learning Ruby, I heard the same about redefining/extending core methods/objects. Nowadays, you cannot find a lib that doesn't have it's small extension to Object.

It's not really relevant if people will use it, because it must be explicitly invoked. In other words, someone else can't invoke a selector namespace on your code. I think the most common use-case will likely be frameworks and libraries, but if you want to extend string for the duration of your application, and explicitly include the namespace into your files, that doesn't bother me. In short, it doesn't seem as complex as people are making it out to seem, or even more complex than facilities we have in Ruby today.

Sure, but one of your arguments was that it won't be widly used anyways ;). 

I don't see it as something overly complex. But then again I also see this with the mind of my collegues that really struggle even with the concept of :method_missing. So I try to illustrate both sides. I like to adopt both viewpoints for the sake of an internal discussion.

 
BTW: how will IRB handle file-based switches? 

I'd assume that namespaces would apply to the rest of the IRB session. Perhaps a "using nil" could be specified to deactivate namespaces.

Hm, i would prefer to actually being able to switch. Especially, because i use irb heavily for development of new code, not just to check.

 
In favor of the proposal, I also want to construct explain a case where I always missed it. Take ActiveRecord or DataMapper. The objects usually get passed into a template (a completely different context) where most of the methods are not intended to be used (#find being the common case, basically everything that does Database operations explicitly). The uninitiated (TM) still use them, causing all kinds of problems to the initiated (TM).

Some frameworks I know (mostly PHP) solve this problem by hydrating the database objects to an array before handing them over to the view. With selector namespaces, there would be an easy fix for this: let the view be a evaluted in a different Namespace. This would also allow for "convenience methods" to be added in the view exclusively.

It wouldn't really work that way, unless you explicitly removed methods from the global ActiveRecord and only made them available in a specific namespace. Even then, it would be trivial to include the namespace in question into the templates.

Oh, sure, nothing is foolproof. But it shows an intention.[1] I also just wanted to construct a case i see coming for DataMapper and ActiveRecord, but some future library might make use of semantics like that. And it is a case most people handle every day.


[1]: FUD stands for a marketing strategy after all. There is no market at ruby-core. And we are not corporate goons trying to keep you from something.

Hehe... Perhaps a strong term. I was trying to get across that the objections were vague, and in the interest of a vibrant discussion, I was hoping for some clear examples that would be so complex as to justify the derision. After all, Ruby is not a particularly simple language; instead, it aims to be NATURAL.
  

I never got that NATURAL. ATM, I work at a company where everything outside of Java, RFC calls and XML is unnatural. For those people, Java is natural. Because thats the nature of the context.
I like Ruby for keeping a complex thing complex. Perhaps thats natural, perhaps not.

Regards,
Florian

[1]: I like code hinting at the intention of a programmer. It gives you the possibility not to support people that work against your intentions. "But I was able to make it available" is far less of an argument then "I was able to make it available".
The same argument goes for private methods. "But I was able to use __send__ to call it in the last version" is different from "But i was able to call it". I don't give out support for people using my private methods while I do invite them to do whatever they want with it if they know what they are doing.

Eero Saynatkari

unread,
Feb 25, 2009, 1:50:50 PM2/25/09
to ruby...@ruby-lang.org
Excerpts from Brent Roman's message of Wed Feb 25 20:08:46 +0200 2009:

>
> At least regarding blocks vs. a special keyword:
>
> There may be a middle way
>
> If the parser were modified such that upon encountering the
> EOF token, it terminated the current do/end block, then
> :use could be a normal Kernel method that simply takes block,
> without introducing spurious indentation.
>
> use MyWorld do
> ....
> <EOF>

...Why oh why? :)

(Mind you, the "block" is not actually a block, so the `do .. end`
notation would be possibly misleading; hence my `using ... end`
suggestion. The point is of course moot if we go with matz' file-
wide modifier.)

Martin DeMello

unread,
Feb 25, 2009, 2:04:12 PM2/25/09
to ruby...@ruby-lang.org
On Wed, Feb 25, 2009 at 10:53 PM, Brian Ford <bri...@gmail.com> wrote:
>
> Apparently my thought experiment on possible misuses is too difficult.
> Here is a concrete alternative exercise. What are the principles for
> using selector namespaces?
>
> When do you put one method in? If one method, why not two? Where are
> the boundaries in a library, framework or application?
>
> The essence of my objection is that you will so cleverly put into a SN
> a method that someone else will want to change.

I'm not seeing your point - selector namespaces aren't a fence to keep
client code out, they're a fence to keep framework code in. Let's say
merb defines String#chars, wrapped neatly within a namespace so that
all the code in merb can make use of it and no code outside merb sees
it. Now as a merb user/extender, if you want to change the way
String#chars behaves within merb, simply reopen the namespace and
change it. All that the SN is preventing is merb's String#chars from
leaking out into the global namespace - in fact, I'd go so far as to
say that it changed monkeypatching from being dynamically scoped to
being lexically scoped, which cannot be other than a good thing.

> Again, there has been no justification for why SNs are *needed* to
> solve the problem presented here. You want to have multiple methods
> with the same name on the same public, common class but with different
> behaviors. There is no justification for why #chars or #camel_case
> *must* have different behaviors.

In fact SNs could fix something that has always bothered me about ruby
- that 'require' introduces dynamically scoped changes to your
environment.

martin:~ $ cat a.rb

class String
def length
1
end
end

martin:~ $ cat b.rb

class B
def foo
"hello".length
end

def bar
require 'a.rb'
end
end

b = B.new
p b.foo
b.bar
p b.foo

martin:~ $ ruby b.rb
5
1

With your code, you know what you are doing; with a framework, you
shouldn't need to worry that 'require' is doing something other than
giving you access to that framework's defined API simply because
*within the context of the framework* it was found convenient to
redefine some core classes.

> You think, "I'm so smart about programming my app, no one will want to
> monkey patch this method." But they will! Just as they have done in
> Ruby for a long time. And when they do, what will that look like? And
> when you try to understand the behavior of some software, you now need
> to look into N different definitions of one method name and determine
> how those interact.

Let them monkeypatch it and be happy. They'll just need to do it
within the namespace.

> Complexity for what benefit? How is this more natural? And it is not
> just in one file. There is no restriction of a class to one file in
> Ruby. Open class gives the ability to build software in layers.

And selector namespaces give the ability to have your code lexically
rather than dynamically scoped.

martin

Charles Oliver Nutter

unread,
Feb 25, 2009, 2:05:02 PM2/25/09
to ruby...@ruby-lang.org
Yehuda Katz wrote:
> To be honest, I'm not sure what Rubinius' experience has anything to do
> with the desire for namespacing.

I think Matz is referring to a desire to ensure that within Rubinius's
"string.rb" that implements String, they are able to guarantee for
certain methods that the "internal" versions are called. Then
monkey-patching a core class would not (in theory) break Rubinius internals.

- Charlie

Yehuda Katz

unread,
Feb 25, 2009, 2:09:51 PM2/25/09
to ruby-core


2009/2/25 Florian Gilcher <f...@andersground.net>


Is FUD the new "the opposition doesn't convince me"? I hear it a lot. I think it's overused. Also, I find it insulting or at least a "verbal" fauxpas as well as misplaced[1].

Apologies.

Accepted, no hard feelings.

 
The problem is rather obvious: suddently, I can have multiple definitions of a method (or none!) depending on context. Nowadays, i can just inspect/test that behaviour in IRB/rdb and be sure that it is about the same everywhere (safe for the unusual catch that it could be un/redefined along the way). With selector namespaces, that catch would get commonplace. 

Not really... because the namespaces would need to be specified on a per-file basis (as per Matz), it would be trivial to go into a file and determine which namespaces were in use. Remember, this is not a global facility, it's per-file facility that must be explicitly invoked. It's also not the case that when *I* invoke a selector namespace in my library code, it effects your library code or your app.

Yes. I'm more about reconstruction what happens later on. Say... you have an Object A in Context C, because you have a breakpoint there. You have an assertion about a property of the object that you will use later on. You want to check that assertion _now_. But as "later on" happens to be in Context D, you assertion is true now but wrong later on.

That can already happen if the framework does A.extend(Something). That's what I don't get about all of this. Ruby is already a very flexible language that allows fairly crazy things to happen to objects and the global space. This allows the same features that already exist in Ruby, but in a targeted, explicit scope. I don't see how this introduces vast NEW confusion.
 
I don't want to present this as a showstopper. But it _is_ something that can happen which couldn't happen before. It will certainly not happen to us good programmers.

 
This could be fixed by additional inspection facilities, but it _is_ an additional layer of complexity (and not a small one). I also don't buy the "no one will use it" argument. Back when I started learning Ruby, I heard the same about redefining/extending core methods/objects. Nowadays, you cannot find a lib that doesn't have it's small extension to Object.

It's not really relevant if people will use it, because it must be explicitly invoked. In other words, someone else can't invoke a selector namespace on your code. I think the most common use-case will likely be frameworks and libraries, but if you want to extend string for the duration of your application, and explicitly include the namespace into your files, that doesn't bother me. In short, it doesn't seem as complex as people are making it out to seem, or even more complex than facilities we have in Ruby today.

Sure, but one of your arguments was that it won't be widly used anyways ;).

I was just trying to say that I anticipated the main use of this to be in frameworks. I have no problem with advanced users using it in their apps, and in the same way that instance/class_eval isn't common in Rails apps (but is very common in Rails itself), I would expect selector namespaces to be common in frameworks and less common in applications.
 
I don't see it as something overly complex. But then again I also see this with the mind of my collegues that really struggle even with the concept of :method_missing. So I try to illustrate both sides. I like to adopt both viewpoints for the sake of an internal discussion.

I don't see it as any more complex than method_missing. It is perhaps simpler, since you need to include the namespace in the same file that it is used.
 

 
BTW: how will IRB handle file-based switches? 

I'd assume that namespaces would apply to the rest of the IRB session. Perhaps a "using nil" could be specified to deactivate namespaces.

Hm, i would prefer to actually being able to switch. Especially, because i use irb heavily for development of new code, not just to check.

 
In favor of the proposal, I also want to construct explain a case where I always missed it. Take ActiveRecord or DataMapper. The objects usually get passed into a template (a completely different context) where most of the methods are not intended to be used (#find being the common case, basically everything that does Database operations explicitly). The uninitiated (TM) still use them, causing all kinds of problems to the initiated (TM).

Some frameworks I know (mostly PHP) solve this problem by hydrating the database objects to an array before handing them over to the view. With selector namespaces, there would be an easy fix for this: let the view be a evaluted in a different Namespace. This would also allow for "convenience methods" to be added in the view exclusively.

It wouldn't really work that way, unless you explicitly removed methods from the global ActiveRecord and only made them available in a specific namespace. Even then, it would be trivial to include the namespace in question into the templates.

Oh, sure, nothing is foolproof. But it shows an intention.[1] I also just wanted to construct a case i see coming for DataMapper and ActiveRecord, but some future library might make use of semantics like that. And it is a case most people handle every day.

Sure.
 


[1]: FUD stands for a marketing strategy after all. There is no market at ruby-core. And we are not corporate goons trying to keep you from something.

Hehe... Perhaps a strong term. I was trying to get across that the objections were vague, and in the interest of a vibrant discussion, I was hoping for some clear examples that would be so complex as to justify the derision. After all, Ruby is not a particularly simple language; instead, it aims to be NATURAL.
  

I never got that NATURAL. ATM, I work at a company where everything outside of Java, RFC calls and XML is unnatural. For those people, Java is natural. Because thats the nature of the context.
I like Ruby for keeping a complex thing complex. Perhaps thats natural, perhaps not.

Hehe ;)
 

Regards,
Florian

[1]: I like code hinting at the intention of a programmer. It gives you the possibility not to support people that work against your intentions. "But I was able to make it available" is far less of an argument then "I was able to make it available".
The same argument goes for private methods. "But I was able to use __send__ to call it in the last version" is different from "But i was able to call it". I don't give out support for people using my private methods while I do invite them to do whatever they want with it if they know what they are doing.


--
Florian Gilcher

gpg:    533148E2

Ola Bini

unread,
Feb 25, 2009, 2:08:19 PM2/25/09
to ruby...@ruby-lang.org
Yehuda Katz wrote:
> The idea is to make selectors like optional versions of Python
> imports. Example:
>
> # merb/core_ext/string.rb
>
> namespace Merb
> class String
> def to_s
> super + "Awesome"
> end
> end
> end
>
> # merb/application.rb
>
> use Merb::String
>
> class Foo
> def bar(str)
> str.to_s
> end
> end
Hi,

I have read the full thread now, and have some concrete questions about
the proposal. I'm not opposed to the proposal, but these are things I'd
really like to understand before agreeing to it.
If any of this has been answered, or if I misunderstood something, I
apologize in advance:

- How would this interact with send?
- How would it interact with other introspection facilities? Kernel#method ?
Basically, what is the runtime behavior of all metaprogramming and
introspection features here...
- Do I understand correctly that this is supposed to be a lexical
effect, and not a dynamic one?
... in that case I have no idea how it's supposed to work at parse
time. Basically, if you use modules as possible namespaces, there is no
way the parser can know which methods are supposed to be possibly
selector-based. And even so, you don't actually know in the above
example that "str" is a String, so how do you know that Merb::String
should be applied to that variable at parse time? The thread has said
it's a lexical effect, but all the examples I see have confused lexical
and dynamic effects, and parse time with runtime.

Once again, the third point could relate to me misunderstanding things
here. But if not, I'm not sure how this is supposed to work.

Cheers

Florian Gilcher

unread,
Feb 25, 2009, 2:18:05 PM2/25/09
to ruby...@ruby-lang.org

On Feb 25, 2009, at 7:46 PM, Charles Oliver Nutter wrote:

> Florian Gilcher wrote:
>> On Feb 25, 2009, at 6:17 AM, Yehuda Katz wrote:
>>> I'm also in favor of discussing this, but all I hear so far in
>>> opposition is vague FUD... no specific examples of problems that
>>> could be caused. It would be a lot easier to have a lively
>>> discussion about specific concerns, and I'd love to have it!
>>>
>>> -- Yehuda
>> Is FUD the new "the opposition doesn't convince me"? I hear it a
>> lot. I think it's overused. Also, I find it insulting or at least a
>> "verbal" fauxpas as well as misplaced[1].
>
> I think the FUD here is "oh no, what if this happens or that happens
> and code gets more complicated!". You can what if any feature to
> death, but without considering the probability of real issues it
> really is FUD.
>
> And of course the "what iffers" may not be weighing those scenarios
> against the positive uses of namespaces.

That may be true or not, but it is still against the rules of a good
discussion to generally calling it FUD. Disprove the other or ignore
him. Accept if he doesn't have your point of view. Tell him that he
doesn't convince you. For me, that comment was ad hominem, because it
also has generic implications about the others state of mind and
behaviour.

>
>> The problem is rather obvious: suddently, I can have multiple
>> definitions of a method (or none!) depending on context. Nowadays,
>> i can just inspect/test that behaviour in IRB/rdb and be sure that
>> it is about the same everywhere (safe for the unusual catch that it
>> could be un/redefined along the way). With selector namespaces,
>> that catch would get commonplace.
>

> You can't really control what any library decides to do today, so I
> don't think you lose any more control with namespaces. And
> monkeypatching code because you want *others* to be affected has
> always been a losing proposition...since they may have monkeypatched
> code to affect *you* already.

As i pointed out more then once: I am on the side of having
namespaces, i just wanted to illustrate that it is not impossible to
find things get more complex. But i was also not speaking about
control but about making sense of a current and future state of a
system at a given moment.

>
>> BTW: how will IRB handle file-based switches?
>
> It would need to have modifications to its parser logic to support
> namespacing, just as it needed modifications to allow stabby lambdas
> through.
>
> - Charlie

Well, thats for sure. Will it be able to switch namespaces, will it
not? I wanted to raise the question, not imply that it is hard to
answer.

Regards,
Florian

Charles Oliver Nutter

unread,
Feb 25, 2009, 2:21:44 PM2/25/09
to ruby...@ruby-lang.org
Eero Saynatkari wrote:
> (Mind you, the "block" is not actually a block, so the `do .. end`
> notation would be possibly misleading; hence my `using ... end`
> suggestion. The point is of course moot if we go with matz' file-
> wide modifier.)

Yes, +1 for using ... end. If we go with explicit scoping (or maybe make
it optional somehow?) this would be the right way. using needs to be
something the parser is aware of for any of this to work, so we might as
well do it right.

- Charlie

Charles Oliver Nutter

unread,
Feb 25, 2009, 2:26:27 PM2/25/09
to ruby...@ruby-lang.org
Brian Ford wrote:
> On the contrary, I have strongly argued for Rubinius to be accessible
> and modifiable to the deepest levels since hearing Evan's comment
> about Rubinius kinda having evil built in. Of course it can be
> misused, just as I can load a segfaulting C extension into MRI.
...

> I understand how selector namespaces can be used. My concern is that
> they can be misused in a way that makes software harder to understand
> or that requires an even stronger antidote than monkey patching to
> work around someone's well-intentioned assumptions that may be invalid
> in a different context.

So on the one hand you support Rubinius being totally open, even if that
openness can be misused, but on the other you don't want selector
namespaces because they can be misused. Aren't these opposite positions?

And if Rubinius is as open as you want it to be, wouldn't it be simple
for someone to implement selector namespaces in Rubinius? And would you
support that or not?

So clarify for me: are you saying you support Rubinius's total openness
and its vastly more likely potential for misuse, but you don't support
namespaces and their relatively limited potential for misuse?

- Charlie

Yukihiro Matsumoto

unread,
Feb 25, 2009, 2:28:33 PM2/25/09
to ruby...@ruby-lang.org
Hi,

In message "Re: [ruby-core:22490] Re: YASNP (Yet Another Selector Namespace Proposal)"


on Thu, 26 Feb 2009 04:08:19 +0900, Ola Bini <ola....@gmail.com> writes:

|If any of this has been answered, or if I misunderstood something, I
|apologize in advance:

Here's MY opinion.

|- How would this interact with send?

send should honor namespaces.

|- How would it interact with other introspection facilities? Kernel#method ?
| Basically, what is the runtime behavior of all metaprogramming and
|introspection features here...

and other introspection features as well.

|- Do I understand correctly that this is supposed to be a lexical
|effect, and not a dynamic one?

I think so.

| ... in that case I have no idea how it's supposed to work at parse
|time.

One possible idea is making symbols to belong to each namespace, like
Common Lisp does, in that case,

obj.foo(bar)

should be work as

obj.<namespace::foo>(bar)

where <namespace::foo> means "symbol foo in that namespace", and its
correspondence can be modified by (dynamic) method definitions.

matz.

Charles Oliver Nutter

unread,
Feb 25, 2009, 2:29:56 PM2/25/09
to ruby...@ruby-lang.org

Yeah, I don't see it as being too difficult, though IRB does force the
issue of "turning namespaces off" at some point, since you may want to
do that in a long IRB session. And if you can turn namespaces
off...maybe they should be explicitly scoped :)

- Charlie

David Flanagan

unread,
Feb 25, 2009, 3:16:41 PM2/25/09
to ruby...@ruby-lang.org
I have not been following this thread, and have no detailed
understanding of the proposal at all. But, I think it is worth
mentioning that a bunch of smart people tried very hard to add
namespaces to JavaScript (in ECMAScript 4) and have recently abandoned
the effort. The proposals sounded very cool; I'm not sure what the
practical difficulties were, but it would be great if someone who
understood the ECMAScript experience with namespaces could comment on
its implications for Ruby. Perhaps someone could have a chat with
Brendan Eich...

David Flanagan

Jim Weirich

unread,
Feb 25, 2009, 3:18:56 PM2/25/09
to ruby...@ruby-lang.org

On Feb 25, 2009, at 1:23 PM, Yehuda Katz wrote:

> You end up needing to do:
>
> Extlib
> ::String
> .constantize(Extlib::String.to_path(Extlib::String.underscore(str)))
>
> instead of:
>
> str.underscore.to_path.constantize
>
> Honestly, we tried this in DataMapper for a while, but it got too
> bulky to
> be realistic (outside of Java, I suppose).

Plus this technique wouldn't allow polymorphic methods based on the
target's type. That's a serious disadvantage.

--
-- Jim Weirich
-- jim.w...@gmail.com


Charles Oliver Nutter

unread,
Feb 25, 2009, 3:29:57 PM2/25/09
to ruby...@ruby-lang.org
Jim Weirich wrote:
> Plus this technique wouldn't allow polymorphic methods based on the
> target's type. That's a serious disadvantage.

GREAT point...I hadn't even considered that. That's a much stronger
argument than the verbosity.

- Charlie

Jim Weirich

unread,
Feb 25, 2009, 3:48:19 PM2/25/09
to ruby...@ruby-lang.org

On Feb 25, 2009, at 2:08 PM, Ola Bini wrote:

> - How would this interact with send?
> - How would it interact with other introspection facilities?
> Kernel#method ?
> Basically, what is the runtime behavior of all metaprogramming
> and introspection features here...
> - Do I understand correctly that this is supposed to be a lexical
> effect, and not a dynamic one?

Ola asks some great questions. I have a few as well:

(1) If two selector namespaces are in scope, and they both define a
method of the same name, which one takes precedence? (i.e. Assume
that namespaces X and Y both defined a method "to_xml" on Object, and
that both are in scope. Which version will be invoked?)

(2) With a particular namespace in scope, will there be a way to
explicitly invoke a conflicting method from a different namespace
(i.e. Assume that namespaces X and Y both define a method "to_xml" on
Object. Will there be a way to explicitly invoke the Y version of
"to_xml" from code that is currently in the scope of the X namespace.)

Charles Oliver Nutter

unread,
Feb 25, 2009, 4:07:16 PM2/25/09
to ruby...@ruby-lang.org
Jim Weirich wrote:
> (1) If two selector namespaces are in scope, and they both define a
> method of the same name, which one takes precedence? (i.e. Assume that
> namespaces X and Y both defined a method "to_xml" on Object, and that
> both are in scope. Which version will be invoked?)

In my prototype they're first-come, first-served. You can have many
namespaces affect the same class and provide the same methods, and
they're searched in "using" order:

module Foo; def to_s; 'here'; end; end
module Bar; def to_s; 'there'; end; end
using Foo => String
using Bar => String
puts 'hello'.to_s # => outputs "here"

It seems like the most straight-forward behavior to me.

> (2) With a particular namespace in scope, will there be a way to
> explicitly invoke a conflicting method from a different namespace (i.e.
> Assume that namespaces X and Y both define a method "to_xml" on Object.
> Will there be a way to explicitly invoke the Y version of "to_xml" from
> code that is currently in the scope of the X namespace.)

Probably not. This would probably be a rare case, but it would be a
strong argument for making namespaces more fine-grained. Of course, Dan
Berger's proposal of a per-call syntax would resolve this, but it's more
verbose.

- Charlie


Ola Bini

unread,
Feb 25, 2009, 4:07:37 PM2/25/09
to ruby...@ruby-lang.org
Good questions. At this point I'm getting confused about terminology.

We have all been using the words "namespace" and "selector" pretty much
interchangeably in this thread.
I'm becoming a bit confused about talking about several selectors being
in scope at the same time here. One of my points in the other mail I
sent was that there is no real way to know what a namespace contains
until runtime - and the parser needs to know at parse time - otherwise
it can't choose the right namespace. Which is why I thought there could
only be _one_ namespace active at the same time.

For more reference, I urge a look at Common Lisp packages.

Jim Weirich

unread,
Feb 25, 2009, 4:09:48 PM2/25/09
to ruby...@ruby-lang.org

On Feb 25, 2009, at 12:23 PM, Brian Ford wrote:

> When do you put one method in? If one method, why not two? Where are
> the boundaries in a library, framework or application?

You should use a namespace whenever you add a method to a module or
class that is not part of your library. For example, Rake adds an
"ext" method to String. If selector namespaces were available, Rake
would scope that "ext" method in a Rake namespace. Allowing other
libraries/frameworks to also define their own independent version of
"ext" and allow users to explicit control which version they call.

You should probably not use namespaces on modules or classes that you
own and control.

> The essence of my objection is that you will so cleverly put into a SN
> a method that someone else will want to change.

Putting something in a namespace does nothing to prevent someone from
intentionally changing the method.

> Again, there has been no justification for why SNs are *needed* to
> solve the problem presented here. You want to have multiple methods
> with the same name on the same public, common class but with different
> behaviors.

A better way to say this is that we want to be able to enhance shared
classes with framework specific methods without:

(1) needing to coordinate non-conflicting names across all libraries
for all time,
(2) needing to name our methods with ugly, conflict resolving prefixes
(e.g. calling using "rake_ext" instead of "ext").

> You think, "I'm so smart about programming my app, no one will want to

> monkey patch this method." ...

Selector namespaces are not about preventing intentional monkey
patching. If Rake put the "ext" method into a namespace, you could
still monkey patch it.

It is to prevent accidental name collision. If anything, it makes
monkey patching safer and easier. Knowing that no one will accidently
overwrite my 'ext' method on String, I am more likely to go ahead and
add the method to String (where it belongs).

Yehuda Katz

unread,
Feb 25, 2009, 4:12:19 PM2/25/09
to ruby-core
I think it's likely the case that explicit calls to namespaced methods should be allowed:

X.Y:to_xml
X.send_with_namespace(Y, :to_xml)

Something like ^^?

-- Yehuda

2009/2/25 Charles Oliver Nutter <charles...@sun.com>

Ola Bini

unread,
Feb 25, 2009, 4:11:50 PM2/25/09
to ruby...@ruby-lang.org
Yukihiro Matsumoto wrote:
> Hi,
>
> In message "Re: [ruby-core:22490] Re: YASNP (Yet Another Selector Namespace Proposal)"
> on Thu, 26 Feb 2009 04:08:19 +0900, Ola Bini <ola....@gmail.com> writes:
>
> |If any of this has been answered, or if I misunderstood something, I
> |apologize in advance:
>
> Here's MY opinion.
>
> |- How would this interact with send?
>
> send should honor namespaces.
>
> |- How would it interact with other introspection facilities? Kernel#method ?
> | Basically, what is the runtime behavior of all metaprogramming and
> |introspection features here...
>
> and other introspection features as well.
>
> |- Do I understand correctly that this is supposed to be a lexical
> |effect, and not a dynamic one?
>
> I think so.
>
OK, my main question about how this should work then is basically that
to support a lexically scoped feature for dynamic methods (such as send
and method_missing and things like that) all the code within the
selector namespace need to capture lexical scope. That is one of the
reasons that packages in Common Lisp turn out to be so complicated, and
is still a static feature in most cases.

> | ... in that case I have no idea how it's supposed to work at parse
> |time.
>
> One possible idea is making symbols to belong to each namespace, like
> Common Lisp does, in that case,
>
> obj.foo(bar)
>
> should be work as
>
> obj.<namespace::foo>(bar)
>
> where <namespace::foo> means "symbol foo in that namespace", and its
> correspondence can be modified by (dynamic) method definitions.
>
>

I definitely like this thinking. As I see a selector proposal, it
basically works like this:
every method call has an associated namespace. that namespace defaults
to the Parsing Default for that file.
if a namespace is set for a file, then THAT namespace will be the
Parsing Default for that file.
of course, this means that namespaces/selectors should just be names -
not modules.

When you start having modules as namespaces, then it gets really
complicated to see what is actually scoped inside of another namespace
or not, since the parser can't know this.

Yehuda Katz

unread,
Feb 25, 2009, 4:15:07 PM2/25/09
to ruby-core
I addressed some of this in the original proposal. Using a namespace would modify the call node (or instruction) to include a list of the namespaces included, which would then be looked up when methods were looked up. This could also be cached (the selector name and the list of namespaces).

-- Yehuda

2009/2/25 Ola Bini <ola....@gmail.com>

Charles Oliver Nutter

unread,
Feb 25, 2009, 4:19:45 PM2/25/09
to ruby...@ruby-lang.org
Ola Bini wrote:
> I have read the full thread now, and have some concrete questions about
> the proposal. I'm not opposed to the proposal, but these are things I'd
> really like to understand before agreeing to it.
> If any of this has been answered, or if I misunderstood something, I
> apologize in advance:

And these are my opinions...

> - How would this interact with send?

I think it would be tricky to make it work with send unless send were
officially elevated in status a bit. Namespaces would not effect
"secondary calls" made by methods I directly call, and I consider send's
eventual invocation of a real target method to be a "secondary call".

In order for send to work, we'd have to special-case "send" behavior to
also know about namespaces active in the caller's scope. And I think
I've made it clear how I feel about caller-scoped data being implicitly
accessible for *any* purpose. Not only is it a real pain to implement
and optimize, it leads to greater complexity of the system overall. And
if that's not enough...it grants yet another special behavior to core
methods that's impossible to emulate with normal Ruby code. That's bad.

> - How would it interact with other introspection facilities?
> Kernel#method ?
> Basically, what is the runtime behavior of all metaprogramming and
> introspection features here...

I would imagine you'd want introspection APIs for "in effect"
namespaces, but I don't see that normal introspection of a target class
would produce different results. At least in my understanding of this,
the namespace is really a transparent layer on top of the call
protocol...not on top of the target type. You might liken it to Groovy's
categories, but without the messy downstream threading effects.

Of course, we could be describing different proposals here. As much as I
support Matz taking an implementation-agnostic approach to new features,
we do need to be able to implement those features *somehow* and I don't
see a clean way to do so with support for send and introspection at the
moment.

> - Do I understand correctly that this is supposed to be a lexical
> effect, and not a dynamic one?

Yes. Lexical and largely bound up at parse time. But how does the parser
know about runtime structures? .....

> ... in that case I have no idea how it's supposed to work at parse
> time. Basically, if you use modules as possible namespaces, there is no
> way the parser can know which methods are supposed to be possibly
> selector-based. And even so, you don't actually know in the above
> example that "str" is a String, so how do you know that Merb::String
> should be applied to that variable at parse time? The thread has said
> it's a lexical effect, but all the examples I see have confused lexical
> and dynamic effects, and parse time with runtime.

My prototype doesn't do it yet, but I would see a real implementation
using whatever a namespace resolves to at the point which "using" lives
in the code, so usually at top-level.

So at parse time:

1. The "using" is encountered, and the "locator" for the namespace is
saved at that point in the list of active namespaces
2. The list of active namespaces is from then on attached to parsed
calls, possibly by adding new node types to avoid encumbering existing
call logic with namespace behavior.


At runtime:

1. The using is encountered during execution, and the locator is fired.
From then on that locator points to a single namespace and is not
reevaluated.
2. The locators attached to methods later in that file are then
pre-populated with an appropriate namespace, and do not re-execute the
locator.
3. The namespaced methods then would all be guaranteed to use the same
namespace for calls.

There's no way to have it all be parse time since Ruby does not support
static declarations of modules or classes. And there's no way to make it
all at runtime without a large penalty, since all calls would have to
always be checking for namespaces, even in the majority of code that
doesn't use them.

Have a look at the patch; since you're familiar with JRuby it might
explain a bit about it. Note that I'm reevaluating the "locator" for the
namespace every time, but that's easily fixed.

- Charlie

Charles Oliver Nutter

unread,
Feb 25, 2009, 4:27:32 PM2/25/09
to ruby...@ruby-lang.org
Ola Bini wrote:
> I definitely like this thinking. As I see a selector proposal, it
> basically works like this:
> every method call has an associated namespace. that namespace defaults
> to the Parsing Default for that file.
> if a namespace is set for a file, then THAT namespace will be the
> Parsing Default for that file.
> of course, this means that namespaces/selectors should just be names -
> not modules.

They certainly could be names, or the namespaces could be declared in a
new way that the parser is more aware of. Using modules right now is
mostly for convenience.

> When you start having modules as namespaces, then it gets really
> complicated to see what is actually scoped inside of another namespace
> or not, since the parser can't know this.

My prototype is basically just overloading modules to use as a method
bag. In this sense it's similar to the "borrow" feature you added to
JRuby to steal methods from a target module or class.

As for the resolution of the namespace, I think doing it once when the
"using" is encountered at runtime would work fine.

- Charlie

Charles Oliver Nutter

unread,
Feb 25, 2009, 4:28:55 PM2/25/09
to ruby...@ruby-lang.org
Yehuda Katz wrote:
> I think it's likely the case that explicit calls to namespaced methods
> should be allowed:
>
> X.Y:to_xml
> X.send_with_namespace(Y, :to_xml)
>
> Something like ^^?

Yeah, that shouldn't be hard; send_with_namespace would just explicitly
enlist in the exact same protocol that "namespaced calls" implicitly
enlist in.

- Charlie

Charles Oliver Nutter

unread,
Feb 25, 2009, 4:32:13 PM2/25/09
to ruby...@ruby-lang.org
Ola Bini wrote:
> For more reference, I urge a look at Common Lisp packages.

Given that "Common List packages" is probably a fairly large topic, can
you provide a "Lisp eye for the Ruby guy" description of them or how
they differ from the current proposals? In my quick reading of them they
sound pretty similar to what I prototyped.

- Charlie

Jim Weirich

unread,
Feb 25, 2009, 4:33:19 PM2/25/09
to ruby...@ruby-lang.org

On Feb 25, 2009, at 4:07 PM, Ola Bini wrote:

> We have all been using the words "namespace" and "selector" pretty
> much interchangeably in this thread.

Good call. I understand "selector" to mean "message selector", i.e.
the symbol used to identify a method during a message send.

"Namespace" is anything the divides a set of names into distinct
spaces (modules and classes in Ruby are namespaces). Selector
namespaces are a particular kind of namespace that allows the same
selector to select different methods, usually based on lexical
information (as opposed to dynamic runtime information).

In this thread, namespace probably refers specifically to selector
namespaces.

> I'm becoming a bit confused about talking about several selectors
> being in scope at the same time here. One of my points in the other
> mail I sent was that there is no real way to know what a namespace
> contains until runtime - and the parser needs to know at parse time
> - otherwise it can't choose the right namespace.

I think it only needs to know what the namespaces are at lex time.
You would still need to search the namespaces to find the method
definition (just as today we search the class hierarchy for the actual
method).

Ola Bini

unread,
Feb 25, 2009, 4:33:41 PM2/25/09
to ruby...@ruby-lang.org
Well, my point was that in that case namespaces/selectors isn't strictly
a parse time feature, and as such will incur a cost on EVERY method call
in the lexical scope of a namespace - since you don't know which
CALL/FCALL/VCALL will actually resolve into something that is part of
the other namespace. Which means you'll have to create SEL_CALL nodes
for all CALL nodes inside of that lexical scope, since all can
potentially be a namespaced call. This will incur a heavy performance
cost which I think was one of the main objectives to avoid in the
original proposal.

Ola Bini

unread,
Feb 25, 2009, 4:38:49 PM2/25/09
to ruby...@ruby-lang.org
Yehuda Katz wrote:
> I addressed some of this in the original proposal. Using a namespace
> would modify the call node (or instruction) to include a list of the
> namespaces included, which would then be looked up when methods were
> looked up. This could also be cached (the selector name and the list
> of namespaces).
Yes, right. Sorry about that, I totally forgot that detail in your proposal.

This could of course handle send and those other introspection things,
if we provide a way for a method to get access to the selectors that
were activated for invoking method node... Or make those methods
extra-special in the way Charles really dislikes. =)

Cheers
>
> -- Yehuda
>
> 2009/2/25 Ola Bini <ola....@gmail.com <mailto:ola....@gmail.com>>

Ola Bini

unread,
Feb 25, 2009, 4:41:43 PM2/25/09
to ruby...@ruby-lang.org

Thanks Charles,

I think I've gotten most of my questions answered to some degree now.
There is definitely some varying opinions on how to do things, but now I
see how this could be done. I will crawl back under my rock now.

Charles Oliver Nutter

unread,
Feb 25, 2009, 4:43:03 PM2/25/09
to ruby...@ruby-lang.org
Jim Weirich wrote:
> I think it only needs to know what the namespaces are at lex time. You
> would still need to search the namespaces to find the method definition
> (just as today we search the class hierarchy for the actual method).

I regret not just doing this in the prototype, but I would see the
lex/parse time handling of namespaces as holding a "slot" that's
attached to parsed calls, and then at runtime that slot is filled with
the runtime structures necessary.

- Charlie

Charles Oliver Nutter

unread,
Feb 25, 2009, 4:44:18 PM2/25/09
to ruby...@ruby-lang.org
Yukihiro Matsumoto wrote:
> Hi,
>
> In message "Re: [ruby-core:22490] Re: YASNP (Yet Another Selector Namespace Proposal)"
> on Thu, 26 Feb 2009 04:08:19 +0900, Ola Bini <ola....@gmail.com> writes:
>
> |If any of this has been answered, or if I misunderstood something, I
> |apologize in advance:
>
> Here's MY opinion.
>
> |- How would this interact with send?
>
> send should honor namespaces.

Very difficult. Perhaps we're thinking about namespaces differently? For
me, namespaces are simply hooking the call process to provide a
different method lookup channel. The fact that they're attached to a
given type is largely unrelated. And namespaces as described would not
affect downstream "secondary calls", so you couldn't namespace "each"
and have "map" honor that change. I consider "send"'s eventual call of
the target method to be a similar "secondary call".

Of course the namespace proposal could be modified to be bound to a
specific type or to affect downstream calls, but those are much larger
changes.

> |- How would it interact with other introspection facilities? Kernel#method ?
> | Basically, what is the runtime behavior of all metaprogramming and
> |introspection features here...
>
> and other introspection features as well.

Same reasons as above; if namespaces are just a call-protocol hook,
their effect on a given type is irrelevant for introspection purposes.
Yes, I may be namespacing calls to String#to_s to do something
different. But String doesn't suddenly define different methods as a result.

> One possible idea is making symbols to belong to each namespace, like
> Common Lisp does, in that case,
>
> obj.foo(bar)
>
> should be work as
>
> obj.<namespace::foo>(bar)
>
> where <namespace::foo> means "symbol foo in that namespace", and its
> correspondence can be modified by (dynamic) method definitions.

This is probably fine, so long as we don't go down the path of having to
reevaluate the namespace every time we want to make a namespaced call.
That would make it prohibitively expensive.

- Charlie

It is loading more messages.
0 new messages