Vincent Gable’s Blog

March 15, 2008

Standard Error Messages

Filed under: Programming,Research,Usability | , ,
― Vincent Gable on March 15, 2008

UPDATE 2010-04-08 CLANG/LLVM comes through!. OK, I can believe I’m living in the 21st century now :-)

All languages should include well-written error messages as part of their specification. These messages should include a link to a good explanation of the problem, and anything someone learning the language might want to know, like the design behind the error.

Every standards-compliant compiler would be required to emit the readable error messages.

This could eliminate inscrutable error messages, in one fell swoop.

(The old MPW Compiler had some
quirky and humorous error messages. “This struct already has a perfectly good definition”, for example. Unfortunately, I don’t know of any compiler that had different but more useful error messages. It’s time somebody wrote one.)

March 10, 2008

Red Fire Bar

Filed under: Cocoa
― Vincent Gable on March 10, 2008

I shared a “Red Fire Bar” with some coworkers today, and we all agreed it was very good. It tasted a lot like Mexican Hot Chocolate, with the chili peppers rounding out the flavor quite nicely. I do not normally like dark chocolate, but peppers add a “richness” that compliments it well.

Despite the name, the candy was not spicy — I’d rate it about the same as mild salsa.

March 7, 2008

Low Level Optimization Decays With Time

Filed under: MacOSX,Programming,Tips
― Vincent Gable on March 7, 2008

Did you know that hand-optimized assembler is slower then allegedly “slow” languages, say, Lisp or JavaScript? It’s true, if you wait long enough.

Imagine you have found some old hand-tuned Lisp code, and a hand-tuned PDP-1 assembly language version. If you executed both programs today, using a modern Lisp interpreter and a modern PDP-1 emulator, the Lisp code would perform much better. That’s because it could take advantage of all the improvements in Lisp interpreters and computers since the 1960’s, while the PDP-1 code would be held back by trade-offs made long ago to appease obsolete hardware.

I expect that ultimately JavaScript will outperform contemporary SSE code, because hardware inevitably becomes obsolete over time.

When assembly code becomes obsolete, you are stuck with two slow options. Use obsolete hardware to execute the code, or emulate your obsolete hardware on a new computer (since computers keep getting faster, emulation will become the fastest choice). Meanwhile the high-level code will still be executable, and able to take advantage of all subsequent hardware improvements.

Some x86 instructions are already obsolete; by which I mean they give worse performance then more common instructions.

Assembly/Compiler Coding Rule 31. (ML impact, M generality) Avoid using complex instructions (for example, enter, leave, or loop) that have more than four µops and require multiple cycles to decode. Use sequences of simple instructions instead.

Intel®64 and IA-32 Architectures Optimization Reference Manual

You could say that this is all academic, because in half a century the code you wrote today will be irrelevant, and I would agree. PDP-1 vs Lisp was hypothetical hyperbole, show that the benefits of low-level optimization decrease the longer the code is in use, because the advantages compared to high-level code decrease over time.

What really drove this home for me was Apple’s switch from PPC to x86. Suddenly all the AltiVec code I’d ever written was obsolete. If someone bought a new Mac, my AltiVec code would be emulated, and slower then unchanged (but recompiled) C code! I could have reused existing AltiVec code to create SSE code, but then I would be stuck doing optimization work every time a sufficiently new computer came out.

Algorithmic-level optimization holds it’s value over time; low-level optimization does not. However, software is such a rapidly-changing environment that a short-term investment can still make a hell of a lot of sense.

March 5, 2008

Calling the Command Line from Cocoa

Filed under: Cocoa,MacOSX,Objective-C,Programming,Tips,UNIX | , , , ,
― Vincent Gable on March 5, 2008

The best way to call a shell-command from Coca is by using an NSTask. Here are the three resources on using an NSTask that I found the most helpful:
CocoDev’s write up
A few quick exaples
NSTask Class Refrence

And here is some sample code to do it for you. You are free to use this code however you please, but attribution is always appreciated. The two principle functions are:

+ (NSString*) executeShellCommandSynchronously:(NSString*)command executes the command “command” with sh, wait until it finishes, and return whatever it printed to stdout and stderr as an NSString.
CAUTION: may deadlock under some circumstances if the output gets so big it fills the pipe. See http://dev.notoptimal.net/search/label/NSTask for an overview of the problem, and a solution. I have not experienced the problem myself, so I can’t comment.

executeShellCommandAsynchronously: will have sh execute command in the background, without blocking anything.

For quick hacks, the POSIX int system(const char* command) function, might be a good one-line solution. It synchronously evaluates command with sh.

Enjoy!

EDITED 2009-11-29: this code probably won’t have the same $PATH you would get if you used Terminal. See this question on stackoverflow for more details. A solution that seems to work is to do,

    [task setLaunchPath:@"/bin/bash"];
    NSArray	*args = [NSArray arrayWithObjects:@"-l",
    				 @"-c",
    				 commandlineHere,
    				 nil];
    [task setArguments: args];

This launches bash (not in sh compatibility mode), and -l (lowercase L) tells it to “act as if it had been invoked as a login shell”. I haven’t tested this on systems where bash isn’t the default shell. There are lots of ways $PATH could be set, and I haven’t tested them all. But you are almost certainly going to be OK if everything you refer to is in /usr/bin:/bin:/usr/sbin:/sbin.

February 26, 2008

this is Confusing, self is Not

Filed under: C++,Objective-C,Programming,Usability | , ,
― Vincent Gable on February 26, 2008

Most diction decisions, like choosing the keyword nil over NULL seem inconsequential. Sure, n-i-l is probably faster to type then shift+n-u-l-l, but the difference is too small to matter. Both terms are clear.

However after today I’m convinced that the C++ convention of using the keyword this, over self, was a mistake. “This” is just too common of a pronoun. It’s too easy to say something like “..this is invalid..”, and leave people wondering if you meant that-this or self-this.

I’d be interested to know the reasoning behind choosing the ambiguous keyword “this” over the precedent “self”.

I plan to refer to “this” as “self” whenever possible for a time, to see if it’s less confusing, even to habitual C++ users.

February 24, 2008

UUID (GUID) Support in Cocoa

Filed under: Cocoa,Objective-C,Programming,UNIX | , ,
― Vincent Gable on February 24, 2008

To easily create a new UUID (aka GUID) in Cocoa, add the following method as a category to NSString:

+ (NSString*) stringWithUUID {
   CFUUIDRef uuidObj = CFUUIDCreate(nil);//create a new UUID
   //get the string representation of the UUID
   NSString *uuidString = (NSString*)CFUUIDCreateString(nil, uuidObj);
   CFRelease(uuidObj);
   return [uuidString autorelease];
}

That’s it, just 4 lines of code. There’s really no need to deal with an entire UUID class. All you ever need to do with UUIDs is create them, compare them, and store/retrieve them. + stringWithUUID handles creation. The string it returns responds to - isEqual:, and is easy to write or read using the mature Foundation APIs. What more could you ask for from a UUID object?

Simpler Ways:

You might only need: [[NSProcessInfo processInfo] globallyUniqueString]. As the name implies, it gives you a UUID that can be used to identify a process.

If you want a UUID without messing with compiled code, the uuidgen command-line tool generates them, or you can use this website.

« Newer Posts

Powered by WordPress