6 ms·
Can you elaborate on this? I'm mostly curious because I have used Sinatra, and I am starting to look at both Noir and Compojure.
by thmzlt 15y ago
Can you elaborate on this? I'm mostly curious because I have used Sinatra, and I am starting to look at both Noir and Compojure.
- weavejester 15y agoSure 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)))))