Tatu Tarvainen will be giving a talk at ClojuTRE 2017. His talk is called Scrap your query boilerplate with specql.
PurelyFunctional.tv: What is your favorite feature of Clojure?
Tatu Tarvainen: Immutable data and the facilities for working with data structures in a general way. Most of my professional life, I've been working in Java and I have seen so many cases of classes that exist solely for the purpose of holding some data. Often there are even different versions of basically the same classes for different purposes (like DTOs).
The problem with objects is that everything you need to do, you must explicitly support. Again, I have seen (and written) much Java code to simply shovel data from one class to another and it amounts to tens or hundreds of lines of code for what in Clojure would be a simple
(merge b a) call :). The "maps with keyword keys" approach that we usually take in Clojure allows such flexibility and generality that seeing getters and setters now feels like an obstacle course in our way to a working program.
Immutability, while possible in many languages, really shines in Clojure as it is the default and so easy to work with. The biggest plus for me is that I never have to worry about giving arguments. It removes the need to care what the receiver does with it. In OO languages you often need to worry if the receiver will mutate the object you have given it or do pre-emptive copying to protect your objects. Even returning or giving something as simple as a Date in Java is dangerous as the class has setters (albeit deprecated, but still working).
PF.tv: What is your least favorite feature of Clojure?
TT: I think Clojure, overall, is pretty well designed. Of course there are some rough edges. Many people have a problem with error messages. Coming from Java, I'm used to reading long stack traces so I don't mind them but even I appreciate that they are being improved.
There are a couple of features that come to mind. First is STM which initially seemed like something that would be really useful but I almost never use it.
My least favorite feature is laziness. While it is sometimes useful, having it as the default in
for and the like is something that bites even experience Clojure programmers from time to time. I have many times mistakenly tried to return a lazy value for example from within a transaction block and had a confusing result. I think the lazy functions perhaps should have been eager by default with laziness reserved for the few cases you really need it. It is especially
difficult to explain to newcomers to add a
doall call or use
PF.tv: Can you briefly describe your talk?
TT: It is about specql, a new library for interfacing with PostgreSQL. Specql tries to remove boilerplate from the most common SQL queries and bring full clojure.spec specs to the data. Specql introspects your tables at compile time to generate clojure.spec definitions and retain runtime information. The runtime information can be used to automatically do queries, inserts, updates and deletes to the tables with fully namespaced keys and validated data. I've tried to give a good rationale and overview of the library in the documentation at specql.
In the talk I will give some examples of specql and how it is used and also show what it takes to integrate type information from an external system with clojure.spec.
PF.tv: Why did you choose this topic?
TT: I'm the author of the library :). But really specql is the culmination of different approaches I've used to interface with SQL databases. I don't claim that specql "solves" SQL. I do like SQL as a query language but I don't like writing the almost same query over and over again. I think others may find specql directly useful or as a starting point for interfacing with other databases.
PF.tv: What is one thing I will be able to do after watching your talk?
TT: Hopefully you will be able to use specql simply by having watched my talk. Also specql is a somewhat unconventional macro as it reads information not just from it's parameters but from an external system at compile time. After watching the talk you will have an idea of what making such macros entails.
PF.tv: What are the three most important concepts I need to know to follow the conversation?
TT: To fully understand you should have used clojure.spec or at least namespaced keys in Clojure. Also understanding what macros are and how they are expanded is useful. Lastly, of course, knowing SQL in general and PostgreSQL in particular is useful but not absolutely necessary.
PF.tv: Where can people follow you online?
TT: I'm on twitter and github with the handle "tatut".
PF.tv: Are there any projects you'd like people to be aware of? How can people help out?
TT: There are two projects that are the main inspirations for specql:
PostgREST is a Haskell application that automatically publishes a REST API from a PostgreSQL database. That showed me how well you can introspect PostgreSQL databases. If you want a JSON REST API from your database without having to write it yourself, give PostgREST a try.
Zalando's incubator project "java-sproc-wrapper" is interesting and it integrates PostgreSQL types and stored procedures to Java.
To help I think the best approach is to find something in your stack that is not (yet) Clojure and make it be Clojure. Everything is better when you can interact it with it as Clojure data. If you are using PostgreSQL and want to help with specql, the best is to try it out and see how it fares in your use-cases.
PF.tv: What one feature from another language would you like to see in Clojure?
Lisps being as extensible as they are, I don't think there are many that can't be added by libraries. If the JVM wasn't a limiting factor, full tail call optimization would be nice and a Common Lisp style condition & restart system.
PF.tv: What is your favorite Clojure function or macro?
My favorite Clojure function, if we choose only from the core, is probably
juxt. It is a perfect example of the power of functional programming. It is the sort of glue that Clojure provides to combine your functions in interesting ways. It's always a delight to introduce
juxt to someone coming from OO land for a visit.
I was thinking of a favorite macro and the threading macros are a nice example that I don't remember being used in Common Lisp or Scheme, but came about from Clojure. But really my favorite macro is not in the core, but an add on: go from core.async. It is pretty much a compiler for Clojure and showcases the power of lisp. I don't know of any languages apart from lisp that allow such functionality to be added by libraries.