Treating Non-Boolean Types as Logic Values

October 26th, 2009

Historically, I have always disliked the idea of using boolean test operations on types that can take a number of values. This deep-seated aesthetic grudge comes from cases like this:

int x = 0;
if (not x)
   cout << "X is zero" << endl;

I’m simply bothered by this. Perhaps it’s a cognitive thing where I just don’t feel there’s any “truth” to the idea that every non-zero integer is somehow “true” but zero is somehow “false”. It could just as easily be that negative numbers are false and non-negative numbers are true. Or if you ask a mathematical purist, they might suggest that at a more foundational level it is primes that are true and non-primes are false!

My comfort zone is when I’m only testing for “truth” and “falsehood” those things that can only have the values true and false. If I could, I would enforce this. So in the example above I would always write something more like:

int x = 0;
if (x == 0)
   cout << "X is zero" << endl;

That particular example is not very controversial, and I think most programmers would agree with me that’s a better way to test against a literal zero. It’s just better code for capturing the intention.

Yet I have historically considered that a logical extension of “zero is not false” is the premise that “null pointers are not false”. And that belief is contrary to practice:

shared_ptr< foo > fooPointer;
if (not fooPointer)
   cout << "fooPointer is null" << endl;

In fact, look what a mouthful you get if you insist on comparing against null literally:

shared_ptr< foo > fooPointer;
if (fooPointer.get() == nullptr)
   cout << "fooPointer is null" << endl;

In the past I have tried to work around this by creating inline template wrappers like “isNull()” so that I could stick to my guns and avoid flattening pointers into booleans. It doesn’t cost any more in the runtime, so I figured what’s the harm?

template< class T > inline bool isNull(shared_ptr< T > ptr) {
	return !ptr;
}

Yet I’ve decided this is a lost cause and too much of a speed bump in sharing my code with other C++ programmers. They’ve accepted the notion that null pointers are false and non-null pointers are true, and you use boolean logic to test this—not some other operator. It’s not worth it to pick this particular fight.

I’m not happy about it. But I now accept this for pointers only. And I’m going to use “not” instead of “!”… it’s part of the language and a lot more readable.

Tweaking Analog Literals (C++ humor)

August 29th, 2009

Jeremy Friesner brought this site about analog literals to my attention. It provides the long-needed ability to represent integer constants in C++ not as numbers (like 42) but rather as 1-D, 2-D, or 3-D shapes whose length, area, or volume correspond to the number’s quantity. So for instance:

assert( ( o-------------o
          |L             \
          | L             \
          |  L             \
          |   o-------------o
          |   !             !
          !   !             !
          o   |             !
           L  |             !
            L |             !
             L|             !
              o-------------o ).volume == 
 
( o-------------o
  |             !
  !             !
  !             !
  o-------------o ).area * int(I-------------I) );

That’s great! As the inventor of Arecibo ASCII, I fully support this visual double-check with our intuitions about numbers! What if aliens are trying to read our code, but don’t know about our arbitrary choices of digits and numeric base?? This could bridge that important gap! :P

But there’s one nagging concern I have, which is that I don’t think the 1-D numeric values are very intuitive. Look at these examples from the site:

assert( I-I == 0 );
assert( I---I == 1 );
assert( I-----I == 2 );
assert( I-------I == 3 );

I’d prefer it to more consistently depict the historic concept of zero, and be less arbitrary with the “2N+1″ formula of dashes to implement value N. So why not overload dereference and multiply, and define “II” to be the constant value zero? This way you can get:

assert(II == 0);
assert(I*I == 1);
assert(I**I == 2);
assert(I***I == 3);

The implementation is relatively straightforward from the proposal. But I went ahead and wrote it, and it is complete enough to give errors when compiling invalid literal specifications:

int test1 (I); // compile error!
int test2 (*I); // compile error!
int test3 (I*); // compile error!
int test4 (*I*I); // compile error!
int test5 (I*I*); // compile error!

I hope this makes it more practical for people to apply analog literals to real-world situations! Source below…

Read the rest of this entry »

Smart Pointer Casting Study

July 10th, 2009

If you’re using public inheritance in C++, the compiler will implicitly “upcast” from a Derived class pointer to a Base class pointer. So I thought a std::auto_ptr to a Derived class would have a similar implicit upcast. It does…but only for assignment and construction!

auto_ptr_cast.cpp

The example shows that if you try to pass an auto_ptr<Derived> to a function that takes an auto_ptr<Base>, it fails to convert due to an ambiguity. You must put an explicit static_cast< auto_ptr<Base> > at the calling site.

This “minor” problem led me down an investigation of the state of auto_ptr and its alternative, unique_ptr. I sought the wisdom of friends and people on the Freenode IRC. Wound up even building a newer version of gcc than came with the latest Kubuntu distribution! Though my findings are not the most exciting subject for a blog, I thought writing them up might help someone.

So I have good news, and bad news…

Read the rest of this entry »

8-Year-Olds Should *Read* My Code

June 16th, 2009

A couple years ago, I read an article that gained popularity on social-bookmarking sites which was entitled “8-year-olds should test my code”. It’s a story about a child named Brian (no relation :P), who crashed UCBLogo only seconds after encountering it for the first time:

Logo Crash Caused By 8-Year-Old

The author is an engineer at Google, and said this:

“I had played with UCBLogo for two weeks and hadn’t made it crash once. Brian brought the whole thing down in three commands. The most telling part is that when I tried to reproduce the defect a week later I couldn’t. I issued rt with a ton of 9s and just couldn’t get it to break. As it turns, it only crashes when you omit the space, which of course I didn’t think of doing. It took me more time to reproduce the defect than it took Brian to discover it.”

We’re offered the conclusion that we need legions of 8-year old testers, since their lack of preconceptions makes them great sources of unanticipated input. I strongly disagree.

For one thing, automated fuzz testing can be made much more genuinely random. But more importantly: 8-year-olds have better things to do than feed random data into programs that were developed using defective methods! It’s much more gratifying if kids are using solid software tools that enable creativity and learning. Even better is if their curiosity about the tool can be satisfied by reading its implementation!

This is not as unattainable as it sounds. I’ll go deeper into this example to make my case…by showing what caused this bug and how far ahead modern techniques are.

Read the rest of this entry »

Takeaways from the Extjs Licensing Fiasco

June 15th, 2009

Now and again, I look at the searches that bring people to hostilefork.com For some period of time, the largest search phrase bringing people here is “extjs fork”. Sadly, they aren’t looking for the articles I wrote in 2007. Instead…it turns out there was a huge backlash against the Extjs project surrounding a change of the license from LGPL to GPL.

People have been up in arms and threatening to fork the codebase, and independently develop it under the previous contract. (To the best of my knowledge, the only place such a forked codebase has been posted is OpenEXT. But with very few commits and the most recent patch being applied in October of 2008 it is not too promising.)

Since people are finding my blog because of this question, I’ll take a stab at addressing the issue and offer my thoughts. I think they made a mistake in doing this change the way they did. Extjs should revert the current 2.0 repository to LGPL—applying the GPL to only 3.0 and beyond—so anyone using v2 who needs LGPL can use all the bugfixes that body of code has.

I’ll explain in more detail.

Read the rest of this entry »


Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported
Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported