But, if you are familiar already, and just wanna see examples of neat macros that makes the API nicer than what a function could provide, here are a few:
- https://github.com/clojure/core.async/blob/master/examples/w...
- https://github.com/weavejester/compojure
- https://github.com/ptaoussanis/timbre
- https://github.com/krisajenkins/yesql
Furthermore, macros enables APIs like this, that would be impossible to have in JavaScript for example:
(spy :info (* 5 4 3 2 1)) => 120
%> 15-Jun-13 19:19:13 localhost INFO [my-app.core] - (* 5 4 3 2 1) => 120
`spy` here doesn't just print what the `` form is returning, but the form itself too. You wouldn't be able to achieve this without macros, as the evaluation of the `` form would happen before it gets passed to `spy`, so the initial form is already gone. Instead, a macro received the very code you pass into it, so you can print it, inspect it, rewrite it or whatever.There are many opportunities to grow this, e.g. transforming the SQL files into stored procedures, and being able to lint and check against a DB schema definition. However, I'm not sure that the indirection step of hiding the SQL away from the code actually makes sense in the long run. A tight coupling allows filters and other optimisations to be easily added to the end of a query, and saves one lookup that is not yet supported in your editor.
[0] https://github.com/krisajenkins/yesql [1] https://github.com/honza/anosql
After dealing with ActiveRecord for the past few years, I'm ready to just be able to write plain old SQL again. It seems like yesql is a pretty sweet solution, but I haven't tried it in earnest.
1. http://www.sandimetz.com/blog/2016/1/20/the-wrong-abstractio...
I've gone through the FP language snob mill over the last few years, and have to agree -- I don't love it, it doesn't make me feel all chipstered out, but Java is actually a pretty decent language for getting stuff done.
There are even helper libraries to make keeping your SQL separate and executing it safely easy. I use yesql (https://github.com/krisajenkins/yesql) in Clojure, and a quick google shows that sqlt (https://github.com/eugeneware/sqlt) exists for the same purpose in javascript.
p.username = "Carl"\n p.age = 33\n p.save\n
\ninstead of "update users set username=:username, age=:age where id=:id" has a ton of advantages. For one, some sort of syntax or type checker is actually trying to understand your queries and makes it easy to find typos before the database laments in the middle of a huge transaction. Strongly typed languages are even cooler here (most notably Slick for Scala, which has a fully type-checked DSL for database querying which makes it really difficult to create typos) [1].However, the downside of this is that it only works as long as whatever you need from your database is the lowest common denominator of database features. I'm currently working on a Clojure + Postgres project and I'm using all the bells & whistles that Postgres has to offer: HStore types, Json Types, subqueries in subqueries, Upserts, functions, etc. I have a rather complex database that I'm running analytical queries against, and using an ORM for this would simply not work. I'd spend half my time trying to figure out how to implement a certain Postgres feature in -insert-or-name-here. I actually started with Korma [2], a simple Clojure ORM, and gave up because it was too tedious trying to figure out how to get it to correctly run my 4-function column result query.
I've since switched to YeSQL [3] which follows a very interesting idea: You write queries in .sql files (full editor support, jay) and tag every query with a name. YeSQL then reads these .sql files during compile time and dynamically generates clojure functions with the correct amount of parameters based on these queries. It is kinda the best of both worlds. Example:
queries.sql:
-- name: get-users\n -- a function to retrieve the user by name\n select * from users where username=:name\n
\nclojure.clj: (defqueries "some/where/queries.sql")\n\n ;; now I can do:\n (get-users "carl")\n
\nI think it really depends on the use case. If the database model is simple and there're no crazy database technologies in use, I'd rather go and use an ORM again I guess.[1] http://slick.typesafe.com/\n[2] http://sqlkorma.com/\n[3] https://github.com/krisajenkins/yesql