I’ve been playing around with some server-side Swift the past couple of days. One of the things I really enjoyed when playing with ClojureScript was the Hiccup library. Sure, all the cool kids might be using something else, but all the time invested in templating languages felt like time spent on the wrong problem. I personally would rather just write the code to construct the view. To each their own, I guess.
If you’ve not played with Hiccup, it basically looks like this:
That will generate the HTML:
Well, I wanted something similar in Swift. I’m still playing around a bit, but this is what I’ve got so far:
The above generates the following HTML:
I call it Swiccup.
So far, it’s working out alright. Though, I’m not terribly happy with implementation side of things. There is a lot of duplicated code. So much so, that after I’m done with the prototyping, the only reasonable thing to do is to write a code generator for it.
You know, like I’d do with C++. 😝
Improving the Flow
However, the code was still too clunky. In order for this to actually be useful, it needs to be streamlined and as much as the syntax needs to be removed as much as possible. So I came up with this:
I’m pretty happy with the above usage. Unfortunately, I still have that errant call to string() that I cannot get rid of. For some reason, within the closure, Swift is unable to convert my string literal properly to an HtmlElement.
Like I briefly mentioned above though, the implementation sucks. Maybe I can do this a little better, but at first pass, I need the three following functions to make this work:
The first is is to allow for partial application. This is the magic function that allows the |> operator to work as the left hand side expects a function signature of: ([HtmlElement]) -> HtmlElement. And since Swift cannot do partial applications automatically, we need to hand roll it.
The next second function is the full signature. Now, you might ask why not put the attributes parameter at the end and mark it with a default value. Surely, that would reduce this boiler plate code, right?
Well… yes, but the API call would be backwards. I don’t want to group the nested children before configuring all of the details of the the current element. So, this means that I end up with three different functions.
The real problem is that I need one of these functions for every single HTML tag I want to support. This is where I really wish Swift had a proper macro or meta programming surface to make use of. Instead, I’ll be writing a simple code generator that will generate all of these methods for me.