4 ms·
Sure thing. So superficially, Compojure and Sinatra look similar: get "/greet/:name" do |name| "Hello #{name}" end (GET "/greet/:name" [name
by weavejester 15y ago
Sure thing. So superficially, Compojure and Sinatra look similar:
get "/greet/:name" do |name|
"Hello #{name}"
end
(GET "/greet/:name" [name]
(str "Hello " name))
But these snippets of code are actually pretty different in what they do.
The Sinatra code generates a new route and adds it to an instance variable on the current object: it's a side-effectful method.
The Compojure code returns an anonymous function; it has no inherent side effects. If we wanted to do anything with it we'd want to bind it to a symbol:
(def greeting
(GET "/greet/:name" [name]
(str "Hello " name)))
The other main difference is that Compojure has no implicit variables like "params" or "request". For instance, in Sinatra we could rewrite the example as:
get "/greet/:name" do
"Hello #{params[:name]}"
end
But in Compojure, you don't get access to any variable you haven't explicitly bound:
(GET "/greet/:name" {params :params}
(str "Hello " (params :name)))
So Compojure is effectively very explicit where Sinatra is implicit.
The advantage of this approach is that Compojure is (IMO at least) better at nesting and abstracting functionality. For example:
(context "/user/:id" [id]
(let [user (find-user id)]
(routes
(GET "/history"
(get-history user))
(GET "/profile"
(get-profile user)))))