From: Austin Ziegler Date: 2005-05-07T12:42:19+09:00 Subject: Re: RCR 303: nil should accept missing methods and return nil On 5/6/05, Cyent wrote: > On Sat, 07 May 2005 02:28:18 +0900, Austin Ziegler wrote: >> On 5/5/05, John Carter wrote: >> I said this on the RCR comment area, but PDF::Writer is *correct* >> to blow up when it gets nil. Without this, there are things that >> I could not *possibly* have debugged. With the silent eating of >> messages, the generated PDF files would be incorrect -- invalid >> -- and there's not a damned thing I could do to tell where the >> problem is. >> >> I don't really know what to say to this -- this will turn a >> correct behaviour into a completely invalid behaviour. > Ah, but _would_ it. On any other object I would agree with you. > But nil occupies a special place in the ruby world. Not really. > nil means in effect, no thing is here. And, if I'm expecting that some thing will be there, then I have an error condition. Putting your nileater mechanism in place will simply *mask* that I have a very real and very serious error. It will also cause me to output incorrect information to my PDF files. > What happens if I tell no thing to do something. > No thing happens and I'm left with no thing. You may, however, be left with incorrect output. "\n#{@oid} 0 obj\n<>" If @owner is nil, then using your proposal I will get: 234 0 obj <> This is INCORRECT. This will, AT BEST, cause the page you're looking at in a PDF reader to be partially or completely not rendered. Equally likely, it will cause your PDF reader to crash. (Object references are ALWAYS "id version R" in PDF.) However, since I know that @owner should never be nil, when that line blows up during execution, I can start tracing it from the blow up. I can find out where and why @owner becomes nil and I can fix it. Without the fatal error, I am left with a mysteriously crashing PDF document -- and almost no debugging possible from a PDF reader. This is real code, John. It's a bit simplified from the real case (the real case is about 20 lines long and contains a lot more). Indeed, I don't even need to go that far: arr.empty? This doesn't return +true+ if arr is +nil+. This means that carefully crafted logic will, in fact, break. (It also ignores the fact that nil *can* be a useful value.) > Is your assertion correct? Yes, John, it's correct. I know this without taking your challenge. > Do you actually generate incorrect PDF? (In which case you are right) Yes, I'm right. I know this without taking your challenge. > Does it just plain work? (In which case I am right) No, it doesn't. Never has, never will. I know this without taking your challenge. > Or does it blow up with an exception or error report somewhen > else? (I which case I'm still right.) You're not right. I know this without taking your challenge. > I'm better a beer (to be collected in Christchurch New Zealand) > that practical software will find that... > a) Mostly it will just do the right thing. This will be true so long as the program does not interact with other programs that require strict conformance to output (or input!) formats. > b) Otherwise it will do the right thing for now, and be caught later as an > Exception or error report. (I suspect by adding a few more things like > class NilClass > def respond_to?( sym) > true > end > end > may cure some of those... Not in the case where you have to have strict conformance to data formats. Not when you're dealing with numbers. What is 2 + nil? Is it 2 or nil? > c) And very rarely, far more rarely than people suspect, will it > silently do the wrong thing. Far more often. > Also as you go along, consider cases where you could just drop > conditionals. How many if branches would you be quietly dropping? Well, strictly speaking, I *don't* have a branch now. I simply assume that @owner is set and is set properly. If it isn't, I have a serious error -- and no amount of pretending that this will work will change that incorrect data will be output. > As for debugging, if you look at the RCR, the implementation I > give creates state on nil that records which method was missing > and in which calling context. Still won't help with the case where the error is in the generated code (that is quite large and hard to read) -- it's very disconnected from the real error. -austin -- Austin Ziegler * halostatue@gmail.com * Alternate: austin@halostatue.ca