Why No External Templates?

I was asked on Twitter:

Could you expand in why [Swiccup] versus a template language?

I gave a brief answer there, but I think it’s worth talking about a bit more. Many of the HTML templating languages out there are simply trying to solve the problem that crafting HTML in code (or crafting HTML in general) can be a real pain.

As an example, the desired output might be this:

<b>resque</b>
<b>hub</b>
<b>rip</b>

You have the data structure of:

"repo": [
  { "name": "resque" },
  { "name": "hub" },
  { "name": "rip" }
]

Using HTML libraries in code are generally a huge pain. But if you can have a file that simply describes this as (in mustache):

{{#repo}}
  <b>{{name}}</b>
{{/repo}}

Or in Leaf, maybe it looks like this:

#loop(repo, "name") {
  <b>#(name)</b>
}

This is so much easier to read, understand, maintain, and author than authoring this by hand which might look something like:

for repo in repos {
  output.writeln("<b>\(repo)</b>")
}

Of if you’re using a typical HTML library:

for repo in repos {
  parent.addChild(HtmlBoldElement(repo))
}

The templates are just better.

So what’s the problem?

The problem is that they still come at a cost. Maybe times we’re moving from a typed system to an untyped system, so typos are easy to have happen. Most of the time there are no tools to help ensure that the templates are actually structured properly. This makes everything a runtime validation check.

The other problem is that we are introducing another language to understand, and in many normal use cases, figure out the interop between the host and the templating language for custom formatting or serialization of data.

The question is then: is there some tradeoffs that we can make to get the majority of the benefits from both sides? That is, more type safety and language similarity without the horrendous code that we typically write when authoring our templates in code?

Yes, but you need a language that is “powerful” enough to be able to create mini-DSLs.

Instead of writing the #loop from above, we could do something like:

repros.map { name in
  b |> name
}

Now we can leverage many of the benefits of using our compiled language while still getting the the vast majority of the benefits from our template system. The really awesome thing is that extensibility is already built in. If you need to format the name in a specific way, you just need to call your function. Depending on the template system you are using, this could actually be a fairly difficult and time consuming thing to get done.

So, why don’t I use external template? I find them redundant and don’t add much to solving the problem.

Why No External Templates?

Swiccup, Round 2

Just a follow up from my previous post: Swiccup.

Sidenote: Swiccup might be a bit of a dumb name… I was thinking about renaming it SwiftyML, but then I saw another project that is similar called SwifTML, so that might be too confusing…

As I mentioned previously, the first round was a bit of prototyping. I spent a bit more time on it today and have come up with a more flushed out implementation and a more streamlined approach, but it does make use of a couple of operators overloads, essentially creating a mini DSL (domain specific language).

Let’s compare, the original:

The new version:

There are a few differences:

  1. There are now two operators: |> and <|
  2. The signature of all of the tag constructs are now uniformed; this greatly reduces the codegen boilerplate and complexity of the system.
  3. String interpolation now works

The |> and <| operators

The |> operator is used to denote a child relationship between two different HtmlElement structs. The left hand side is the parent and the right hand side is the child. This can be a single entity or an array of children.

The <| operator is used to denote attributes that should be assigned to the HtmlElement to its left, hence the arrow pointing left. This allows either a dictionary to be merged into the attributes store for the element. Above is an example of both single entry dictionaries and multiple entry dictionaries being merged in.

Streamlined Method Signature

The signature for each tag is really nice now, it’s simply:

(_ attributes: [String:String] = [:]) -> HtmlElement

Before, I had a nasty mess of things as I was trying to figure out the best call site API feel. The other nice thing about this is that I only need a handful of operator overloads to handle all of the cases too.

String Interpolation

So yeah, to get string conversion to work properly, you need to implement four different protocols:

  1. ExpressibleByStringLiteral
  2. ExpressibleByUnicodeScalarLiteral
  3. ExpressibleByExtendedGraphemeClusterLiteral
  4. ExpressibleByStringInterpolation

Good times. Also, the ExpressibleByStringInterpolation one is a real doozy. It’s also marked as deprecated, but there is no alternative yet until Swift 4, so you’ll have to ignore the warning if you want to “build clean” (e.g. with no warnings). If you don’t implement that last one, you won’t be able to use string interpolation like:

"item #\($0)"

Wrapping Up

I’m going to keep playing with it. Once I get pretty comfortable about the syntax, I’ll post it up to my github account.

Oh… and just to show the comparison of what the code looks like without the operator helpers:

You know, just the terrifying normal HTML element construction you see in pretty much every OOP language.

UPDATE @ 10:58PM

While the <| is “clever”, I think I like this API usage better:

h1("class", "welcome", "id", "title") |> "Welcome to Swiccup",

To each their own though and your mileage may vary.

Swiccup, Round 2

Swiccup

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.

Implementation Woes

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.

 

Swiccup