Archive
Your update is not more important than my work
I love TextMate, but I just saw the most user-hostile, infuriating thing. I’m doing work when all of a sudden I get the pop-up:
It closed my document (thankfully giving me a chance to save), and now the program refuses to launch until updated.
sigh
CAPTCHAs must die
I just tried to leave a post on a site which uses a CAPTCHA to prevent bots from leaving spam comments. I must be a bot, because I failed the test – not once, not twice… not even three times. I tried over ten times in a row and it kept rejecting me after offering a new option each time. I assume this is a software glitch, and I gave up.
For the purposes of validating comments, I find CAPTCHAs completely unnecessary. There’s a better solution – it’s called machine learning. I use Akismet in WordPress as my spam filter and it performs incredibly well.
Let the computers do the hard work of spam filtering. Don’t frustrate and slow down legitimate users by making them fill out these things unnecessarily.
Java annoyances
Asymmetry in standard libraries
String[] strings = ...; StringBuilder b = new StringBuilder(); for (int i = 0; i < strings.length; i++) { b.append(strings[i]); if (i != strings.length -1) { b.append(","); } } System.out.println(b.toString());
print(",".join(strings))
println(strings.mkString(","))
Different treatment of primitives and objects
It is a lot harder to deal with variable length collections of primitive types than it should be. This is because you cannot create collections out of things that are not objects. You can create them out of the boxed primitive type wrappers, but then you have to iterate through and convert back into the primitive types.
// Need a double[] but don't know how long it's going to be List<Double> doubles = new LinkedList<Double>(); for (...) { doubles.append(theComputedValue); } // Option 1: Use for loop and iterate over Double list, converting to primitive values through // auto unboxing // Bad: leads to O(n^2) running time with LinkedList double[] doubleArray = new double[doubles.size()]; for (int i = 0; i < doubleArray.length; i++) { doubleArray[i] = doubles.get(i); } // Option 2: Use enhanced for loop syntax (described below), along with // additional index variable. // Better performance but extraneous index value hanging around int index = 0; // Automatic unboxing for (double d : doubles) { doubleArray[index++] = d; } ... b[index] // Oops
Patchwork iteration support
Collection<String> strings = new ArrayList<String>(); Iterator<String> it = strings.iterator(); while (it.hasNext()) { String theString = it.next(); }
for (String s : strings) { // deal with the String }
class IterableIterator<T> implements Iterable<T> { private Iterator<T> iter; public IterableIterator(Iterator<T> iter) { this.iter = iter; } // Fulfill the Iterable interface public Iterator<T> iterator() { return iter; } }
Lack of type inference for constructors with generics
Yes, we all know we should program to an interface rather than to a specific implementation; doing so will allow our code to be much more flexible and easily changed later. Furthermore, we also know we should use generics for our collections rather than raw collections of objects; this allows us to catch typing errors before they occur. So in other words
// BAD: Raw hashmap and programming to the implementation! HashMap b = new HashMap(); // Good Map<String, Integer> wordCounts = new HashMap<String, Integer>();
Map<String, Integer> wordCounts = Maps.newHashMap();
Map<String, Integer> wordCounts = new HashMap<String, Integer>();
Map<String, Integer> wordCounts = new HashMap<>();
Conclusion
Give an indication of why a button is disabled