On Wed, Mar 21, 2012 at 22:11, Xavier Noria <fxn / hashref.com> wrote:
> On Wed, Mar 21, 2012 at 9:51 PM, Nikolai Weibull <now / bitwi.se> wrote:
>
>> There a timing issue with using const_defined? followed by const_get
>> instead of calling const_get directly and catching NameError.
>
>
> What do you mean?

I mean that if const_defined? returns true, then between that code
being executed and the call to const_get, some other piece of code may
remove the constant, resulting in an uncaught NameError.

> The problem with const_get is that it follows the ancestors, of course, and
> you have no way around that in 1.8.

Yes, wee already come to that conclusion.  You don needo keep
repeating it.

I see that you completely cut out the part about const_defined? not
calling const_missing, which is a rather big part of the problem with
using const_defined? in the first place.

>> I guess
>>
>> def feature?(path)
>>  path.split('::').reduce(Object){ |o, e|
>>   c = begin o.const_get(e); rescue NameError; return nil end
>>   return nil if c == (o != Object and begin Object.const_get(e);
>> rescue NameError; nil end)
>>   c
>>  }
>> end

> Nikolai, I don't really understand what you need.

Xavier, please don°«t begin sentences with the person you°«reesponding
to°«s name like that.  It°«s like your speaking to me as if Ias a
child and it feels very condescending.

> You are askind for
> defined? X::Y that goes step by step and your original code does raise an
> error for X::Y integer.

I don°«t follow.

> Then this second version cannot say that X::Y is defined in
>
>   module X
>    Y = nil
>  end

True.

> And you refuse to reuse much more simple and proven existing solutions.

You°«re making it sound like I°«m being stubborn.  I just don°«t think
your proposed solution is better.

> You want something with so special semantics that definitely is NOT
> built-in. That answers you original question.

Thank you for building me a straw man.  I°«ve always wanted one.

I want a way to tell if a class or module has been defined/loaded.
The check would then be to see if X was loaded in your example above,
not X::Y.

An alternative is to check $LOADED_FEATURES.  This isn°«t
straightforward either, as it doesn°«t contain the exact argument given
to require.  There are internal functions like rb_provided that could
have been exposed to make it easy to check if a feature had been
loaded/is available.

This part of Ruby is surely inspired by Emacs°« way of doing this, see

http://www.gnu.org/software/emacs/manual/html_node/elisp/Named-Features.html

but doesn°«t provide a way to check if a feature has been loaded.
(There°«s a difference here, of course, as Ruby implicitly uses the
(expanded) path, with possible suffixes/extensions, of the argument to
require as the feature, not a symbol as Emacs forces you to explicitly
use as an argument to provide.)

To sum up, ruby should provide a method °»provided?°… that checks if its
argument would return true or false when given as an argument to
require.  Provided? would return this results negation.

Checking the presence of constants is a workaround that I°«ve been
using in the past, but was recently burned by, as, even in the case of
using defined?, this may travel unwanted paths in the resolution of
such constants.