Wednesday, December 26, 2007

Confusion

On two occasions I have been asked, – "Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?" In one case a member of the Upper, and in the other a member of the Lower, House put this question. I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question.

-- Charles Babbage, English mathematician, philosopher, and mechanical engineer

 

Saturday, December 22, 2007

Calculate Difference in Days

Java has no built-in "give me the difference in days" API methods. One commonly-suggested solution is to get the difference in milliseconds between two dates and, using the number of milliseconds in a day, determine the number of days. Unfortunately, daylight savings time creates some problems with this method, as the following Groovy script demonstrates:
#! /usr/bin/groovy

df = new java.text.SimpleDateFormat('yyyy-MM-dd')

// These dates cross DST...
startDate = df.parse('2007-03-10')
endDate = df.parse('2007-03-12')

expectedDifferenceInDays = 2

// Here's the problem with millis:
millisInADay = 1000 * 60 * 60 * 24
differenceInMillis = endDate.time - startDate.time
actualDifferenceInDays = differenceInMillis / millisInADay

assert expectedDifferenceInDays != actualDifferenceInDays
assert actualDifferenceInDays < expectedDifferenceInDays


Here's a more straightforward solution using Java's Calendar API:
#! /usr/bin/groovy

df = new java.text.SimpleDateFormat('yyyy-MM-dd')

// These dates cross DST...
startDate = df.parse('2007-03-10')
endDate = df.parse('2007-03-12')

expectedDifferenceInDays = 2

calendar = Calendar.instance
calendar.time = startDate
actualDifferenceInDays = 0
while (calendar.time.before(endDate)) {
actualDifferenceInDays++
calendar.add(Calendar.DATE, 1)
}
assert expectedDifferenceInDays == actualDifferenceInDays


Note that what constitutes "a day" is subject to interpretation... :o)

Wednesday, October 03, 2007

Write simple code

Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.
-- attributed to Brian Kernighan

Friday, September 14, 2007

Integer Palindromes

File this one under "Silly, Simple Code Snippet Of The Day"™...

Several times on various programming forums, I've seen question about how to find out if an integer value is a palindrome or not (the number is the same "forwards" and "backwards"; e.g., 71317 would be a palindrome, while 71316 would not). Most of the suggested solutions revolve around converting the integer value to a string and reversing the characters. This makes sense, given that "71317" is just a character representation of a number, and many language APIs have ready-made facilities for reversing strings of characters (or at least arrays). That said, finding out if a number is a palindrome using basic math is dead simple, too. Here's a base-10 example in C#:
    using System.Diagnostics;

class ScratchUtils
{
public static int Reverse(int i)
{
int result = 0;
while (i != 0)
{
result = (result * 10) + (i % 10);
i /= 10;
}
return result;
}

public static bool IsPalindrome(int i)
{
return i == Reverse(i);
}

public static void Main()
{
Debug.Assert( 0 == Reverse(0));
Debug.Assert( 1 == Reverse(1));
Debug.Assert( 21 == Reverse(12));
Debug.Assert(-21 == Reverse(-12));

Debug.Assert(IsPalindrome(1));
Debug.Assert(IsPalindrome(11));
Debug.Assert(!IsPalindrome(12));
Debug.Assert(IsPalindrome(121));
}
}

Tuesday, September 11, 2007

Java - Cannot Resolve Symbol

You get a "cannot resolve symbol" message because the compiler doesn't recognize something you've typed. It's as if you instructed your friend to "fernt PL^%", to which s/he would likely reply, "Huh?". The compiler errors will tell exactly which symbols it does not recognize; correct these errors by properly defining variables, importing the correct classes, implementing the appropriate methods, etc.

Sunday, September 02, 2007

.NET - Connecting to SQL Server Express from VWDE

I was trying a tutorial for Visual Web Developer Express, and kept running into problems connecting to SQL Server Express. When I tried to configure the security settings by clicking on the security tab in the ASP.NET Web Site Administration Tool, I received the following error:
There is a problem with your selected data store. This can be caused by an invalid server name or credentials, or by insufficient permission. It can also be caused by the role manager feature not being enabled. Click the button below to be redirected to a page where you can choose a new data store.

After researching a bit, I used the SQL Server Configuration Manager to use "Local System" as the built-in account (found under the [Log On] tab for the running SQL Server Express instance). Then, I had to add a Web.config to my project with the following connection strings:

<connectionStrings>
<remove name="LocalSqlServer"/>
<add name="LocalSqlServer"
connectionString="Data Source=localhost;
Initial Catalog=aspnetdb;
Integrated Security=True"
providerName="System.Data.SqlClient"/>
</connectionStrings>


After that, the connection succeeded, and I was able to continue with the tutorial.

Wednesday, August 15, 2007

Newsbite Of The Day

From a story about rising food prices:
Half the nation’s families earn below the median family income of about $56,000.

Well, yeah. That's pretty much what "median" means.

In other shocking news, half the nation’s families earn above the median family income of about $56,000.

Friday, July 06, 2007

Groovy and the Lambda Calculus

I've been playing around with the Groovy language, and have recently been involved in a discussion regarding the addition of closures to Java. Tangents lead to tangents, and all of a sudden, I find myself reading about Perl and the Lambda Calculus. Oy.

I had just started trying to get my head around the idea of the lambda calculus when the author brought up the subject of "currying", and discussed the "Lambda Calculus Way"™ of writing an addition function built on the concept that functions can only take a single argument. The author showed how to express such a thing in Perl:
    sub add {
my $x = shift;
my $f = sub {
my $y = shift;
return $x + $y;
}
return $f;
}

Groovy supports writing code like this too, so I thought I'd see what I could come up with in Groovy syntax. Here's the beast:
    def add (x) {
return {
y -> return x + y
}
}

And the test...
    assert 7 == add(3)(4) // whew.

If there's a Groovy expert out there reading this blog, let me know if there's a better way. All right, back to the essay...

Wednesday, July 04, 2007

Non-Static Members and Static Contexts

A question commonly asked on Java forums concerns an error message similar to the following:

non-static variable cannot be referenced from a static context

In Java, static means "something pertaining to an object class". Often, the term class is substituted for static, as in "class method" or "class variable." Non-static, on the other hand, means "something pertaining to an actual instance of an object. Similarly, the term instance is often substituted for non-static, as in "instance method" or "instance variable."

The error comes about because static members (methods, variables, classes, etc.) don't require an instance of the object to be accessed; they belong to the class. But a non-static member belongs to an instance -- an individual object. There's no way in a static context to know which instance's variable to use or method to call. Indeed, there may not be any instances at all! Thus, the compiler happily tells you that you can't access an instance member (non-static) from a class context (static).

Monday, June 25, 2007

Java Strings and Hash Codes

The question often arises as to how Java can use String values in switch/case statements; e.g.:
switch(s) {
case "Foo": doSomething(); break;
case "Bar": doSomethingElse(); break;
}
The short answer is that one can't. In Java (versions before 5), the expression evaluated in the switch statement must be a char, byte, short, or int. With auto-unboxing and the new enum capabilities of Java 5 and later versions, switch expression may also include Character, Byte, Short, Integer, or enum types. Furthermore, every case expression must be assignable to the same type as what is declared in the switch statement. This means that if your switch statement is an int type, your case statements can be int types, byte types, short types, etc. If, on the other hand, your switch statement is a byte type, the compiler will bark if you try to use an int type in a case expression. In short, however, switch statements with String types (and any type not mentioned above) are simply not available in Java.

Back to the problem of using String values... Every so often, someone will suggest using the string's hash code (an int value) as the value to use as a switch. There are a couple problems with this idea. First, the case expressions must be constant, meaning that the compiler isn't going to accept the result of hashCode() as a valid case. Second, and perhaps a more fundamental issue, string hash codes aren't guaranteed to be unique. Far from it, in fact. The only thing string hash codes guarantee is that strings with different hash codes are guaranteed to be not equal.

So, what is an appropriate solution? It all depends on the design, of course. Most likely, using enums would be a fair approach. In his seminal book Refactoring, Martin Fowler recommends looking at polymorphism for a more object-oriented design. And if one must have switchy strings in a Java-ish environment, there is always Groovy...

~

Thursday, June 21, 2007

Final Variables and Anonymous Inner Classes

Anonymous inner classes require final variables because of the way they are implemented in Java. An anonymous inner class (AIC) uses local variables by creating a private instance field which holds a copy of the value of the local variable. The inner class isn't actually using the local variable, but a copy. It should be fairly obvious at this point that a "Bad Thing"™ can happen if either the original value or the copied value changes; there will be some unexpected data synchronization problems. In order to prevent this kind of problem, Java requires you to mark local variables that will be used by the AIC as final (i.e., unchangeable). This guarantees that the inner class' copies of local variables will always match the actual values.

~