3 ms·
It's worth pointing out that even if noir wasn't built explicitly to look like Sinatra, it's built on top of compojure, which was.
by moomin 15y ago
It's worth pointing out that even if noir wasn't built explicitly to look like Sinatra, it's built on top of compojure, which was.
- weavejester 15y agoCompojure was originally built to look a lot like Sinatra, but since then the design has diverged a fair bit.
- thmzlt 15y agoCan 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)))))