Jonathan Fischer

Home | Archives | Projects | About

Boot as a sort-of Quicklisp

Really quick: after dismissing Clojure for years (I have Common Lisp, I don’t care about the JVM, why do I need it?) I finally took the time to learn it about a year ago and OMG I love it and I want to use it for everything (much to the dismay of my team at work).

One of the pain points though is how project-based everything seems to be: if you want to pull in any sort of third party library, you have to build some sort of project, be it Maven, Leiningen, or something similar. List the libraries you want to pull in there and start (or restart) your REPL before you can use them.

Coming from Quicklisp, it’s super annoying, especially if you just want to give something a quick spin.

Enter Boot! It’s a relatively new way to handle building Clojure projects, but it allows you to easily name dependencies when you run it, like so:

$ boot -d com.google.code.gson/gson:2.5 repl

That gives me a REPL with Gson loaded and ready to use.

boot.user=> (import [com.google.gson Gson JsonObject])
com.google.gson.JsonObject
boot.user=> (def o (JsonObject.))
#'boot.user/o
boot.user=> (.addProperty o "hello" "world")
nil
boot.user=> (.toJson (Gson.) o)
"{\"hello\":\"world\"}"
boot.user=>

To make life a little easier, I have a task in my ~/.boot/profile.boot that pulls in the dependencies Cider needs:

(deftask cider
  "Switch up the default dependencies and middleware to support cider-nrepl."
  []
  (require 'boot.repl)
  (swap! @(resolve 'boot.repl/*default-dependencies*)
         concat '[[org.clojure/tools.nrepl "0.2.12"]
                  [cider/cider-nrepl "0.10.1"]])
  (swap! @(resolve 'boot.repl/*default-middleware*)
         concat '[cider.nrepl/cider-middleware])
  identity)

So when I want to tool around with something, I just run boot -d whatever:version cider repl, fire up Emacs, connect and go to work.

I haven’t take the time to get comfortable with Boot for full projects yet, so I’m still using Leiningen for most things, but I love it for quick one-off experiments. It’s not as good as being able to load whatever I want from the comfort of the REPL, but it makes things a lot less painful.


Do I really need that database?

I’m pretty sure that every time I’ve built a web application of any sort in the last decade, I’ve reached for a database. Usually SQLite, at least to start, because it lets me get going fast without any infrastructure in place. It’s not even a question, really: if I’m building a web app, it needs a database of some kind behind it.

Actually, let me rewind just a smidge. I really dig Clojure lately, and my favorite thing about it are the immutable data structures: once you’ve created your map, or vector, or whatever, you can’t change it. Instead, you can derive new things from it. Now that I’m comfortable working with immutable by default things, working without them feels almost like I’m building on shaky foundations.

Read more...


9 years and counting

Today is my and Jackie’s 9 year anniversary.

It’s funny how things work out. Around when we got married, we had this vague plan to move away from Southern California, to try living other places, to travel a bit and see the world before we really settled down to have kids.

After a year or so it was pretty obvious we weren’t going to do it anytime soon, and we didn’t want to wait forever to have kids, so we had Kayla. Talk about turning our world upside down. Suddenly owning a house became critically important, even if it meant moving well away from work. Suddenly, even though we planned for Jackie to go back to work, we were going to have to get by on just my salary.

Suddenly we were responsible for a child. For a human being. The day Kayla was born, when I went down to the cafeteria alone to get a bite to eat, I cried at how overwhelming it all was.

Somehow, we’ve pulled it off so far. Bought a house 6 months after Kayla was born. 9 months after that we decided she shouldn’t grow up alone, and 9 months after that Colin showed up. The kids are 7 and 5 now, Jackie hasn’t had to go back to work, and we’re still making it. It’s been hard, and continues to be hard, but we’re making it.

Most important: we’re happy.

9 years and counting. We make a pretty good team, Jackie. I love you.

Here’s to many, many more.

Us at the Monterey Bay Aquarium

Kayla and Colin


Delaying deserialization with Mantle until it's needed

I’m using Github’s Mantle in a small side project where I recently started running into performance bottlenecks with it. I have JSON that looks roughly like this:

[{"id": 1,
  "title": "My Thing",
  "widgets": [...]},
 {"id": 2,
  "title": "Another Thing",
  "widgets": [...]},
 {"id": 3,
  "title": "Third Thing",
  "widgets": [...]},
 ...etc.

A bunch of Things, which each has an array of Widgets. I’ve been working with a fairly large data set recently: 70ish things, and a grand total of 1,341 widgets across all of the things at the moment. On older devices (iPhone 4, iPad 2) deserializing all of that at once was unreasonably slow: I could easily see 5-10 second times for it.

Profiling showed that most of the time was spent in Mantle. I really didn’t want to have to drop it: i’s straightforward to write the deserialization code myself, but there are a lot of types that I’d need to do it for, and this particular project I only get to spend a few hours a week on.

Fortunately, I came up with a good workaround: I don’t need that widgets array until it’s time to render a Thing, and there’s only ever one Thing on the screen at a time. I can just delay deserializing the Widgets until rendering time.

How do we do that with Mantle?

First, the class interface looks like this:

@interface Thing : MTLModel<MTLJSONSerializing>

@property (readonly, assign, nonatomic) uint64_t thingId;
@property (readonly, copy  , nonatomic) NSString *title;
@property (readonly, strong, nonatomic) NSArray *widgets;

@end

And in the implementation file, I tell Mantle what class that widgets array is supposed to be:

@implementation Thing

+ (NSValueTransformer *)widgetJSONTransformer
{
    return [NSValueTransformer mtl_JSONArrayTransformerWithModelClass:Widget.class];
}

@end

What I can do instead is remove the +widgetJSONTransformer method so Mantle no longer knows how to deserialize that field: that results in Mantle just setting widgets to the raw NSArray of NSDictionaries that it was handed in the first place. Then, add a new readonly field that deserializes those widgets on demand.

In the header file:

@interface Thing : MTLModel<MTLJSONSerializing>

@property (readonly, assign, nonatomic) uint64_t thingId;
@property (readonly, copy  , nonatomic) NSString *title;
@property (readonly, strong, nonatomic) NSArray *widgets;

// Deserializes the widgets array on demand
@property (readonly, strong, nonatomic) NSArray *parsedWidgets;

@end

And in the implementation:

@interface Thing ()

@property (readwrite, strong, nonatomic) NSArray *parsedWidgets;

@end

@implementation Thing

- (NSArray *)parsedWidgets
{
  if (_parsedWidgets == nil) {
    NSError *error;

    _parsedWidgets = [MTLJSONAdapter modelsOfClass:Widget.class fromJSONArray:self.widgets error:&error];
    if (error != nil) {
        NSLog(@"Thing -parsedWidgets: An error occurred while decoding widgets: %@", error.localizedDescription);
        _parsedWidgets = @[];
    }
  }

  return _parsedWidgets;
}

@end

With that, we’re good to go: I just replace references to -widgets with -parsedWidgets in the rendering code.

Due to when I’m calling -parsedWidgets the deserializing ends up happening on the main thread, so I might need to get a bit fancier in the future. For now things are sped up dramatically without having to write a bunch of accessor code, so I’m happy.


A silly Swift dilemma

I have this side project I’ve been working on in my spare time for the last 14 months or so: a native iOS client for groov.

Read more...