On Mon, February 21, 2005 8:04 pm, Pit Capitain said:
> ES schrieb:
>> Wouldn't it be possible to override the TrueClass, NilClass
>> and FalseClass methods to yield the correct behaviour for
>> this object? I'm assuming 'if something' expands to
>> 'if something == true' or something like that?
>
> If you look at the Ruby source code (this is 1.8.2), in eval.c:
>
>        case NODE_IF:
> 	if (trace_func) {
> 	    call_trace_func("line", node, self,
> 			    ruby_frame->last_func,
> 			    ruby_frame->last_class);
> 	}
>  >>>	if (RTEST(rb_eval(self, node->nd_cond))) {
> 	    node = node->nd_body;
> 	}
> 	else {
> 	    node = node->nd_else;
> 	}
> 	goto again;
>
> This is the code to handle an if statement. The marked line is the code that
> evaluates the condition. The "then"-part of the if statement is executed iff
> the
> RTEST macro returns true (in C). RTEST is defined in ruby.h as:
>
> 	/* special contants - i.e. non-zero and non-fixnum constants */
> 	#define Qfalse 0
> 	#define Qtrue  2
> 	#define Qnil   4
>
> 	#define RTEST(v) (((VALUE)(v) & ~Qnil) != 0)
>
> The objects false, true, and nil are encoded internally as 0, 2, and 4
> respectively. (You can get those values in Ruby with "p false.id".) The only
> values for which RTEST returns false (in C) are the values 0 and 4, in other
> words the objects false and nil. So more or less
>
>    if something
>
> expands to
>
>    if something != nil && something != false

Well, this *would* be overridable. If, however, the test is done at the C
level through direct object ID comparison, things are a bit more complicated.
The only option, then, would be to masquerade as Qnil while adding the
necessary behaviour.

I suppose the question is, then, is it necessary to have the above behaviour?
As I understood it, the desired functionality was something like (my syntax):

 ob.not_nil?.do_something

Conceptually expands to:

 ob.do_something unless ob.nil?

For this purpose, it should be sufficient to add a method to both Object
and NilClass. NilClass could then return an object that simply consumes
all methods fed to it and propagates itself after each call, like was
described in the original post as far as I can recall its contents. This
behaviour would then not be accessible except when using NilClass#not_nil?
so it wouldn't cause problems in other conditionals. Is there a use case
where this would cause a problem, or why is it desirable that the explicit
comparison be allowed for the special NIL and not just the chaining?

Again, sorry if this has already been covered; feel free not to reply,
I'll read the NG in the evening. I'm just bored at work :)

> I think Christian is right that you cannot work around this in Ruby. (Maybe
> Florian Gro? can do it...)
>
> Regards,
> Pit

E