Monday, July 1, 2013

What language Y is to LISP as Mac OS X is to Unix?

In his Rarely Asked Questions, Paul Graham once more espouses LISP as the ultimate, untoppable programming language (and yes, autocomplete wants to approriately turn that into "unstoppable").

One of the points he makes to support this, is that for any language to become as good as LISP, it would actually need to become LISP. While it is a cogent point and well argued, I don't buy it. More precisely, this is what he writes on what it would take to add the equivalent of LISP macros to another language:

But it would be hard to do that without creating a notation for parse trees; and once you do, your language has become a skin on Lisp, in much the same way that in OS X, the Mac OS became a skin on Unix.
Hmmm...I am not sure that this analogy is making his point, because Mac OS X is far, far superior to raw Unix for most people, and preferred by hackers, as he himself writes in Return of the Mac:
All the best hackers I know are gradually switching to Macs.
Of course, I may be stretching the analogy too far, but it seems to me that it doesn't support Paul's thesis of LISP superiority, but rather clearly points to some language Y that delivers LISP's power in a much more useful and usable form.

Any ideas what this language Y might be?

Sunday, June 30, 2013

Inbox management for RSS and Mail

Marco Arment notes that those complaining of RSS Inbox overload are not using RSS correctly: it should be used to check on a possibly large number of rarely updated but valuable sites.

He recommends simply deleting feeds that are updated frequently. I have a slightly different approach: two basic feed directories. One is my A-List, which contains feeds that roughly fall into the "rarely updated but valuable" category, and the other is my River of News, which are feeds that I enjoy and which keep me up-to-date, but which I don't mind clearing out by marking all as read.

Incidentally, pretty much the same goes for my E-Mail Inbox: as much of the lower priority stuff as possible is sorted into specific mailboxes automatically. The rest I triage quickly into one of 3 categories: action, read-ponder, will-file.

I used to sort by categories and that didn't work at all. In fact, it frequently managed to invert the actual priorities, leaving me focused on e-mails that weren't actually important, just hard to categorize, whereas most of the important e-mails would have their own categories and disappear from view.

Saturday, June 8, 2013

NSBezierPath description...

...shows the path segments as Postscript commands. So the following code:
  id p= [NSBezierPath bezierPathWithRect: NSMakeRect(10,20,200,100)];
  NSLog(@"p: %@",[p description]);
yields this output:
  Bounds: {{10, 20}, {200, 100}}
  Control point bounds: {{10, 20}, {200, 100}}
    10.000000 20.000000 moveto
    210.000000 20.000000 lineto
    210.000000 120.000000 lineto
    10.000000 120.000000 lineto
    closepath
    10.000000 20.000000 moveto
Neat!

Monday, May 27, 2013

Root View Controller and Autorotation

Must have the former or the latter won't work.

For some reason my Mussel Wind application was running fine without a root view controller, but with the annoying "Applications are expected to have a root view controller at the end of application launch" message. I vaguely remember autorotation being somewhat tricky, but in the end it was working and all was good.

Until I got the request to add zoom to the large version of the web cam view (you get it when you tap the image). Put in the scroll view, set it to zoomable, added the tap gesture recognizer. All good. Except nor more autorotation. Put in all the debugging messages for rotation masks, and shouldRotate etc. All called, but only on creation, not when the device is rotated. Nada.

On a whim, decided to fix the missing root view controller message by adding the view controller manually. First, no joy because UIKit was sending a "viewControllers" message that wasn't being handled. This despite the fact that my class is a straight UIViewController subclass and rootViewController is documented as taking just that. Oh well, just implement that as returning an empty NSArray and presto: autorotation!

Monday, January 21, 2013

More Objective-C Drawing Context Pleasantries

It's been a little over half a year since I first made my pleasant Objective-C drawing contextpublic, and I haven't been idle. In the process of retrofitting my own code to use MPWDrawingContext and adding more and more graphics (for example, I now do my icons in code), I've discovered a lot about making drawing with code a more pleasant experience.

Blocks

Blocks seem to be a really wonderful match for a graphics context, and most of the changes involve blocks in some way.

Bracketing operations such as gsave/grestore now have block versions, so the Objective-C block structure reflects the nesting:

    [context ingsave:^(Drawable c ){
        [c translate:@[ @130 ,@140]];
        [c setFont:[context fontWithName:@"ArialMT" size:345]];
        [c setTextPosition:NSMakePoint(0, 0)];
        [c show:@"\u2766"];
    }];
This is somewhat more compact than the plain code, which for correctness should also have a @try/@finally block wrapped around the basic drawing so exceptions don't mess up the graphics state stack.
    [context gsave];
    [context translate:@[ @130 ,@140]];
    [context setFont:[context fontWithName:@"ArialMT" size:345]];
    [context setTextPosition:NSMakePoint(0, 0)];
    [context show:@"\u2766"];
    [context grestore];
Similar for drawing shadows:
    [context withShadowOffset:NSMakeSize(0, -8 * scale) blur:12 * scale  color:[context  colorGray:0 alpha: 0.75] draw:^(Drawable c ){
        [[[c setFillColorGray:0.9 alpha:1.0] ellipseInRect:ellipseRect] fill];
    }];
Again, this seems a little clearer than having to explicitly set and unset, makes it harder to miss the end of the bracket when moving code around and remains exception-safe.
    [context sethadowOffset:NSMakeSize(0, -8 * scale) blur:12 * scale  color:[context  colorGray:0 alpha: 0.75]];
    [[[context setFillColorGray:0.9 alpha:1.0] ellipseInRect:ellipseRect] fill];
    [context clearShadow];

Stored, delayed and repeated drawing

You can create an object for later drawing by sending the -laterWithSize:(NSSize)size content:(DrawingBlock)commands message. For example, here is a simple diamond shape:
    NSSize diamondSize=NSMakeSize(16,16);
        id diamond = [context laterWithSize:diamondSize
                              content:^(id  context){
            id red = [context colorRed:1.0 green:0.0 blue:0.0 alpha:1.0];
            [context setFillColor:red];
            [[context moveto:diamondSize.width/2 :2] 
				lineto:diamondSize.width-2 :diamondSize.height/2];
            [[context lineto:diamondSize.width/2 :diamondSize.height-2]
				lineto:2 :diamondSize.height/2];
            [[context closepath] fill];
        }];
We can now draw this anywhere we want, and at any scale or orientation, using the -drawImage: message.
    [context drawImage:diamond];
You also have layerWitSize:content: and bitmapWithSize:content: messages if you want to specifically use CGLayer or CGImage instead, but using laterWithSize:content: preserves maximum quality, and it will automatically switch to a CGLayer when rendering to a PDF context in order to minimize PDF file size.

Patterns

I talked about patterns earlier. What I didn't mention then was that this is just the ability to use a stored set of drawing commands (see previous section) as a color:
    [context setColor:diamond];
I am not going to post the comparison to plain CG here, you can read it in the original Apple documentation.

I should note that this currently works for colored patterns, not for uncolored patterns, due to the fact that I haven't yet exposed color spaces. The basic process will be very similar.

Polymorphic object arguments

Path construction and graphics state messages with point arguments are now available in a version that takes a single object argument, in addition to the format with anonymous float arguments (moveto:(float)x :(float)y).
  • moveto:
  • lineto:
  • translate:
  • scale:
The single argument can be an Objective-C array:
    [context moveto:@[ @10, @20]];
Alternatively, any custom object that responds to count and either objectAtIndex:, (float)realAtIndex: or getReals:(float*)buffer length:(int)maxLen can be used. The scale: message can also take a single NSNumber and will treat that as uniform x and y scale.

Linecap parameters

Linecap parameters can now be set using distinct message:
  • setlinecapRound
  • setlinecapButt
  • setlinecapSquare
Having multiple messages rather than a single message with a parameter probably seems odd, but it actually reduces the number of names involved, and these names are nicely scoped to this context. The constant strings or enums that are typically used have global scope and therefore tend to need ugly and hard-to-remember prefixes:
    [context setlinecapRound];
vs.
    [context setLinecap: kCGContextLinecapRound];

Future

Another reason to be as purely message-based as possible is that it makes bridging to other languages easier, for example for interactive drawing environments: Creating a badge (youtube).

I've also started experimenting with other outputs, for example creating a version of the same badge composed of CALayer objects using the same drawing commands. Other output should follow, for example web with SVG or HTML 5 Canvas or direct OpenGL textures.

I also want to finally add image processing operations both stand-alone and as chained drawing contexts, as well as getting more complex text layout options in there.

p.s.: now on hacker news

(The People) 45874 : 1 (Carmen Ortiz)

As of right now, the White House Petition to remove Carmen Ortiz has garnered 45874 signature in the 9 days since January 12th. The one asking to recognize her 'outstanding' contributions, active for 5 days now received a slightly smaller number: 1. Maybe I should graph this?

Monday, January 7, 2013

Dependency Injection is a Virtue

DHH recently made a claim of Dependency Injection not being entirely virtuous, and got support from Tim Bray. While both make good points, they are both wrong.

Having hard-coded class-names like in the example Time.now is effectively the same as communicating via global variables. DHH's suggestion of stubbing out the Time class's now is selling us mutable global variables as the solution to global variables. Or more precisely: passing an argument to a method by modifying a global variable that the method reads out and restoring the state of the global variable afterward.

If that's "better", I don't really want to see "worse", and not wanting that sort of thing has nothing to do with being a Java drone limited by the language. And my experience with time-dependent systems tells me that you really want to pass the time into such a system generally, not just for unit testing.

Of course, having n-levels of AbstractFactoryFactory indirection could actually be argued as being worse, as Tim convincingly does, but that's one implementation of DI that's hobbled by Java's limitations. For a DI solution that's actually simple and elegant, check out Newspeak's  module system (PDF): there is no global namespace, modules are parametrized and all names dynamically resolved.

If you want synthetic time for a module, just instantiate that module with your own Time class.