Archive for December 2003
Thursday, December 18, 2003
There’s a new round of spams that can be hard for SpamSieve to catch if it hasn’t seen many of them before. They have subjects like:
Re: GSF, despite the promise
Re: IOWRGW, the magician disappeared
and, when the spam-generating software doesn’t work properly:
Re: %RND_UC_CHAR[2-8], rimsky suddenly reached
Generally, my approach with SpamSieve is to make it better at learning from tactics used in spam messages, rather than try to match transient characteristics with a countless number of rules. Sometimes, however, rules work great, and if you add the ones below to your copy of SpamSieve 2.1, it should be easy to catch these new spams.
If you want to copy and paste, the rule text is:
(?:(?-i)^(Re: )?[A-Z]{2,8}, [ a-z]*$)
RND_UC_CHAR
Monday, December 15, 2003
Joel Spolsky reviews The Art of UNIX Programming and discusses Windows/Mac vs. Unix culture differences.
Jamie Zawinski fisks Wired’s story on RFID.
Jan Erik Moström pointed me to Natural Docs, a clean, JavaDoc-like utility that supports several languages.
John Gruber and Christopher Clark discuss keyboard shortcuts. I’m more optimistic than Gruber in that I think Apple can come up with a good system for user-customizable keyboard shortcuts, without applications having to explicitly register them. Instead of having a preferences panel, there should be a more direct interface, like Menu Master’s. Apple writes the menu manager, after all. Also, Joshua Dady pointed me to /Library/Scripts/Mail Scripts/Scripts Menu, which has instructions for adding keyboard shortcuts to menu scripts.
I must admit that my own applications are currently guilty of not supporting Close All Windows and Minimize All Windows. I’m working to correct that. For Cocoa developers, here is a category that will help:
@implementation NSApplication (yourPrefix)
- (NSArray *)yourPrefixVisibleRegularWindows
{
NSMutableArray *result = [NSMutableArray array];
foreach ( window, [self orderedWindows] )
if ( [window isVisible] && [window canBecomeMainWindow] )
[result addObject:window];
return result;
}
@end
Don’t forget to implement -validateMenuItem:
so that the commands are disabled when there are no windows. OmniOutliner currently supports the commands, but gets the validation wrong.
Friday, December 12, 2003
Buzz Andersen:
The problem with Project Looking Glass is that it falls for a common fallacy in UI design: the idea that the more literally a user interface apes the real world, the easier it will be to use.
Thursday, December 11, 2003
Amazon is selling the low-end 12" PowerBook for $500 off.
Wednesday, December 10, 2003
Goombah is an intriguing new application/service that examines your iTunes music library and compares it with other users’ libraries. It then recommends tracks that you might like and lets you listen to them using the iTunes Music Store.
-
You should know that other Goombah users can browse the entire contents of your music library, including play counts and ratings (but not comments).
-
It’s not clear to me how it knows which of the music in my library I like. For instance, two of the top four tracks it recommended to me were Carmen and Wagner, although I have not rated or played any classical music since starting my current iTunes library.
-
Most of the recommended tracks are not (yet) available at the iTunes Music Store.
-
It would be great if a future version could let me rate the recommended items, as Amazon does.
-
It’s written using PyObjC.
Tuesday, December 9, 2003
SpamSieve 2.1 includes the following enhancements:
- Added support for Apple Mail POP accounts. POP messages can be marked as junk
and colored, but (due to limitations in the present version of Apple Mail) they cannot
be moved to another mailbox.
- Added a Training Tip window that gives advice on how to improve SpamSieve’s
accuracy, based on the current state of the corpus and preferences.
- Rules in the whitelist and blocklist are no longer limited to just matching sender
addresses. They can now match a variety of message fields (To, CC, Subject, etc.), as
well as the message body. In addition to exact matches, rules now support the following
match styles: contains, starts with, ends with (useful for matching domains), and
Perl-compatible regular expressions. You can now edit rules and add new rules manually
(as opposed to automatically, as a result of training SpamSieve with a message).
- When trained with a good message from a mailing list, SpamSieve will automatically
create a whitelist rule based on a mailing list header, if present.
- SpamSieve can now read in the Entourage address book and use it as a whitelist. Thus,
the Entourage rule can now give SpamSieve all the messages, not just the ones that
were from unknown senders. This means that SpamSieve can now accurately notify the
user when non-spam messages are received. Also, the statistics it keeps will be more
complete.
- Improved the accuracy of the Bayesian classifier when the corpus is unbalanced.
-
More Changes
SpamSieve
Monday, December 8, 2003
Jonathan Rentzsch is back with a post about the macros he uses to tame Cocoa’s enumeration idiom. Here’s the macro I’ve been using:
#define foreach(object, enumerator)
id mjtForeachEnumerator ## object = (enumerator);
if ( [mjtForeachEnumerator ## object respondsToSelector:@selector(objectEnumerator)] )
mjtForeachEnumerator ## object = [mjtForeachEnumerator ## object objectEnumerator];
SEL mjtNextObjectSEL ## object = @selector(nextObject);
IMP mjtNextObjectIMP ## object = [mjtForeachEnumerator ## object methodForSelector:mjtNextObjectSEL ## object];
id object;
while ( (mjtForeachEnumerator ## object) &&
object = mjtNextObjectIMP ## object(mjtForeachEnumerator ## object, mjtNextObjectSEL ## object) )
-
Like Rentzsch’s macro, this will call
-objectEnumerator
for you. Rentzsch looks for objects that are NSEnumerator
s and doesn’t call -objectEnumerator
in that case; I look for objects that support -objectEnumerator
and do call it in that case.
-
Unlike Rentzsch’s macro, the control variables are not local to the loop. His way is better, but at the time I wrote this, it either wasn’t possible to get the Objective-C compiler in C99 mode (without using Objective-C++) or I didn’t know how to do it. Thus, I glue the element name to the end of each control variable name, to try to make it unique. This lets me use
foreach
more than once in a single scope.
-
After using the macro for six months or so, I added the code to cache the
IMP
for -nextObject
. All the code using foreach
took advantage of the change with just a recompile. The speed increase was noticeable (without a stopwatch) in some cases. (In retrospect, I should probably have just used @selector(nextObject)
instead of mjtNextObjectSEL
, since @selector
happens at link time, not runtime.)
-
We use the opposite parameter order. My macro is used like:
foreach( word, words )
, which means foreach word in words
. (In fact, if you really wanted to, you could #define
in
to be a comma and then write foreach ( word in words )
, but I don’t recommend that.)
Cocoa Macros Objective-C Optimization Programming
Sunday, December 7, 2003
Jonathan Rentzsch has written a great article about what he loves and hates about Objective-C. [Update (2015-05-09): Here’s an archive.org link since the original site is down.] I’ve wanted to write this article for a long time, but now Rentzsch has saved me the time and also done a better job than I probably would have. Now I can just cover the places where I disagree or have something to add.
-
Love 7: Key Value Coding
-
I like Key Value Coding, too, but I think it’s really part of the framework, not the language. It’s made possible by Love 3: (Fairly Good) Runtime Object Model.
-
Hate 1: Method-call Syntax
-
I think the Smalltalk-style interspersing of the method name and the parameters (contra keyed parameters) is a big win. This is probably my favorite part of Objective-C. The square braces, though by no means bad once you get used to them, are kind of ugly and annoying for editing. (It helps to use a BBEdit glossary item such as #inline#[#select##insertion#], coupled with the Balance command.) Smalltalk uses parens instead of braces, and you can omit them in certain circumstances. I don’t know whether this would be possible with Objective-C, given that it has to be compatible with C’s grammar.
-
Hate 6: Initialization Idiom
-
This is kind of a restatement of Hate 2: Lightweight. I agree that assigning to
self
is disturbing, even if it affords a little extra power. However, I don’t think it’s fair to blast Objective-C because many of its users like to put assignments in conditions. This is a feature inherited from C, and you could say that deficiencies in Objective-C encourage the use of this idiom. But it doesn’t bother me. I’ve read about how people accidentally use =
instead of ==
, and how some experienced programmers like to contort the order of their equality operands to help catch this error, but I don’t think this has ever bitten me—so I vote for the extra expressiveness.
-
Hate 7: No Stack Objects
-
This is on the right track, but I’m not convinced that stack objects are the right solution.
-
Hate 10: Messaging nil
-
I’ve got mixed feelings on this one. I really like the expressiveness of being able to message
nil
, for instance with locks, broadcasters, and releasing. Wacky idea: perhaps there should be a way to tell the compiler (via a type modifier, perhaps) in which cases you want to be able to message nil
silently.
-
Hate 14: id should be id*
-
I think this is historical. Originally, all Objective-C objects had type
id
, and you were supposed to treat them like primitives, not pointers. It was only later that static typing, such as NSString *foo
, was added. So it might be more appropriate to ask why we have to write NSString *
instead of NSString
.
-
Indifferent 2: Memory Management
-
Conceptually, this doesn’t bother me, but my intuition is that the hybrid scheme is the worst of both worlds, performancewise.
And the conclusion:
ObjC is a mediocre language propped-up by a great framework.
The framework is certainly the gem. Whether the language is mediocre depends on what you compare it to. It’s no Dylan, but I generally like it better than C++ and Java.
Further reading: the discussion on Erik Barzeski’s blog.
Friday, December 5, 2003
SpamSieve users can delete rules and words from table views by pressing Delete. I’d like to add an option to delete without confirmation by holding down a modifier key. Which should it be?
In many applications, such as the Finder and BBEdit, holding down Option removes the ellipsis from a menu command, so that you can use the command without confirming it or specifying any additional options. This is definitely the right behavior for menu commands, however even though SpamSieve aliases the Clear command in the Edit menu to the Delete key, I doubt most users think of pressing Delete as a menu command.
Internet Explorer’s Favorites window is more similar to the situation in SpamSieve. It’s a list/table that uses Delete to delete with confirmation and Command-Delete to delete without confirmation. However, I can’t think of any other programs that work this way.
Thursday, December 4, 2003
I’ve long shied away from LCD font smoothing because the colored artifacts bothered me. However, after some convincing I decided to give it a try. After a few weeks, the colors are still there but I no longer really notice them (except when using Exposé) unless I’m trying to see them. When I switch back to CRT font smoothing to take screenshots, the text seems noticeably less black.
Similarly, now that I’m used to Panther, when I switch back to Jaguar to do some testing the window striping looks much more pronounced than I remember.
Eric Blair mentions that there’s a hidden Go To Folder command in Panther’s file choosing dialogs. It’s activated with Command-Shift-G, just like in the Finder. This came in handy a few weeks ago when I was explaining to a customer how to open a file in an invisible folder.
Panther’s incarnations of these dialogs are the best since Mac OS 9, but I still make mistakes when I try to navigate them with the keyboard. Either the key commands aren’t consistent, or my brain is too hard-wired to the old keys that I don’t even know what I’m doing wrong. For instance, a few days ago I was trying to syntax check a folder in BBEdit, and I kept accidentally choosing a folder instead of drilling down a level.
Mike Wendland, who switched to the Mac one year ago, lists five reasons why he won’t switch back, including:
The Mac community—I used to think they were fanatical nuts mesmerized by the cult of Apple. Now, I find them to be the most friendly, creative, caring, sharing, connected, informed and intelligent group of computer enthusiasts I have ever encountered.
Wednesday, December 3, 2003
Congratulations to the winners of the 2003 Macworld Eddy awards, particularly Bare Bones, Ranchero, and the Safari team—makers of great software that I use every day. Thanks also to Macworld for honoring SpamSieve with an Eddy and to everyone who has supported SpamSieve, in one way or another.
SpamSieve
Tuesday, December 2, 2003
The December issue of ATPM is out.