Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: I'm writing a leanpub book about Common Lisp web programming (ppenev.com)
107 points by pavelludiq on March 26, 2013 | hide | past | favorite | 33 comments



Wow, definitely something I am going to check out. From a quick look, it seems that your Lisp code for the example looks a lot like HTML itself. For example:

  (defun blogpage (&optional (posts *posts*))
       (html-frame
        "Restas Blogdemo"
         (<:div 
       	     (<:a :href (genurl 'add) "Add a blog post")
  	     (<:hr)
  	     (render-posts posts))))
I don't know much about functional programming though, so sorry if that's an incorrect assumption.


Most of the Lisp web frameworks look like that, taking advantage of Lisp's flexible syntax.

Here's a Racket example. If you download http://racket-lang.org, you can just run this (no extra libraries or anything) and a browser window will pop up for you.

    #lang web-server/insta
    
    ;; A "hello world" web server
    (define (start request)
      (response/xexpr
        '(html
           (body (h1 "Hello, world!")
                 (a ([href "http://google.com"]) "Google")
                 (br)
                 "I hope you like my site!"))))
This example renders as: <html><body><h1>Hello, world!</h1><a href="http://google.com>Google</a><br />I hope you like my site!</body></html>

See also: http://docs.racket-lang.org/continue/


I need help understanding one thing. This code generates HTML code. Fine. But how come code and declaration (web designer and developer) are separated with this. Is this a good practice? I've been reading about lisp for a long time, not in depth, but I keep stumbling similar snippets a lot. Are there any good examples out there? I am teaching myself Clojure (reading the book with the bird cover) these days.


They are not separated. This approach appeals to geeks/programmers, but is completely impractical, as I've learned the hard way in several projects.

In a practical setting you will get a set of pre-cut HTML/CSS and images. Good luck splitting that into semantic markup and styling. And good luck teaching a designer how to work with it afterwards.

Because of hard-earned experience I try very hard not to put any HTML into my code, keeping it all in templates, which are much more accessible to designers and easier to modify.


Yes, this is exactly why I stayed away from things like this, despite my love for Racket and Clojure, until someone above pointed out the Enlive library. It lets you use normal HTML files as your templates but requires no code in it (not even for loops!) Basically, you use CSS-style selectors to replace the contents of elements, giving you the full power of Clojure but without having to either put code in your templates or put HTML into your code.

https://github.com/swannodette/enlive-tutorial/


I have decided to investigate the possibility to include a sub-chapter to chapter 3 to discuss Caramel for people who like enlive(me included). I didn't already do so because caramel is brand new, and I haven't had the time to try it out beyond a few simple examples.

The choice to use s-expressions was made because It makes it easier to just type code in a repl and experiment, without having to worry about dealing with templates, and also because I wanted the first example to fit in a single file.


Oh, I was addressing the Racket example and the response to it, as opposed to your book; I'm not familiar with what you are doing in the book. I am still going to look into your book, as I have no CL experience, only Racket/Clojure. But adding a sub-chapter on Caramel would be really nice!


Enlive looks great!

If you prefer, Racket also includes a templating library that lets you compile arbitrary HTML from separate files right into your application:

http://docs.racket-lang.org/web-server/templates.html?q=in-t...

It's not as fancy as enlive though (for example, because it's not sensitive to the structure of XML, user input isn't escaped automatically, which is quite an awkward tradeoff)


It's up to you to separate them. This is true of all languages and all frameworks.

I keep all my view functions in one .rkt file, and I move all my logic functions to another.


http://github.com/ober/thinatra

(get "/hello/:person1/:person2" "Hello #{person1} and #{person2}")

http://localhost:8021/hello/Jack/Jill "Hello Jack and Jill"

Much nicer imho than many of the ugly lisp ways. And all in Emacs Lisp.


That's a great text templating engine, but how does it handle the structure of HTML? Though our lisp solutions might be uglier than that, they:

- Are guaranteed to automatically produce perfect, valid HTML (or XML in my case),

- Automatically escape user-supplied input

- Make it very easy to generate lots of repetitive elements, or conditional elements, like other template languages.

Maybe I'm misunderstanding the spirit of your post? It seems like thinatra excels at the "routing requests from varying URLs" part, which solves a slightly different problem than the code we posted (racket for example provides a default path of http://localhost:40986/servlets/standalone.rkt -- definitely not what you would want)


Be sure to take a look at hiccup for clojure. https://github.com/weavejester/hiccup


Nice, so if I understand correctly, this defines a function to return a simple html response any time a request is started.


See cl-who for another example: http://weitz.de/cl-who/#syntax

Also, this has nothing to do with functional programming but rather with creating a DSL (http://en.wikipedia.org/wiki/Domain-specific_language)

More links:

http://www.tfeb.org/lisp/hax.html#HTOUT

https://github.com/franzinc/aserve/blob/master/htmlgen/test....


Ah, thanks. That was very helpful, specially the second link.


Functions starting with <: are generated by the sexml library for outputting xml and html from lisp expressions. There are many similar libraries in pretty much every lisp dialect.


Is there any Django/Jinja-like templating engine for CL or Clojure?

...this way or the Clojure Hiccup way is cool for an ubergeek doing full-stack development, but in the real world you'll want your HTML templates separate and in a designer or front-end-coder friendly format. Otherwise, you may have the full power of Lisp at your fingertips, but you'll need to have your entire team used to this workflow and knowledgeable of Lisp, and by having logic in templates and such you're dangerously close to leaning towards the "PHP way".

...the only realistic "homogenous" solution for one language on the server and the client are the Javascript based way, in the Node ecosystem. Good designers or good front-end guys in general will also have coding skills, some will be Javascript gurus, but by doing things this way and writing Javascript code in Parenscript/Clojure script you'll have to force them to learn Lisp in order to work at 100%. And my bet is that they're not gonna like it, so team-wise, you'll lose all the productivity increase you gain in the first place by using Lisp.

IF you can find a team of lispers that also have webdesign and frontend coding skills, great, but this will be fucking hard as far as I know it. I would just love working in such an environment, but it seems like a non-existent Nirvana right now...


There is a port of Googles closure-template system. It compiles closure templates to CL functions. They work pretty well. I have written about them in the book: http://lispwebtales.ppenev.com/chap04.html#closure-template

It also compiles to js, so you can even share templates between the client and the backend.

I'm experimenting with using both sexml and closure-template, but in the book I use almost exclusively sexml to make the code simpler. Also s-expressions are much easier to type in than sgml :)


> but in the real world you'll want your HTML templates separate and in a designer or front-end-coder friendly format.

For Clojure - it sounds like you're looking for Christophe Grand's work on enlive: https://github.com/cgrand/enlive

You can read a tutorial here: https://github.com/swannodette/enlive-tutorial/


Note that you'll need to change (def base-url "http://news.ycombinator.com/) to (def base-url "https://news.ycombinator.com/) in the first example in order for it to work properly.


There is also a recent Common Lisp enlive like library called Caramel: https://github.com/pocket7878/Caramel


Great! When you're done with this, can you be persuaded to write one about Weblocks?

I'm kidding, but not entirely. Weblocks is an extremely powerful and sophisticated framework, but it has a bit of a learning curve. It desperately needs a good tutorial.


What would the case for CL+Hunchentoot+... vs. Clojure+Noir+... sound like?


In general if you prefer FP, clojure is a great choice. If you like multi-paradigm, and mixing up OO with FP, and procedural as you see fit, go with CL. I'm a multi-paradigm kind of guy, but clojure remains my second favorite language :)


You can actually get quite far just with Hunchentoot (and even its built-in "easy handlers"), CL-WHO and some Parenscript.


Many lispers prefer to roll their own thin layers on top of hunchentoot, or even use it raw, but I prefer the slightly ticker layer of restas.


Link to leanpub page: https://leanpub.com/lispwebtales


An incredible coincidence -- I was starting to look into common lisp web programming just this morning, for a personal project. Do you have any estimate on when the book will be finished?


You should add a section about how a beginner is supposed to install all the components you're using.

Right now, you're treating it like they're all "just there".


I also want to put in a plug for my site: http://articulate-lisp.com/

:)



Clojure buster? Great!


Why not use Thinatra?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: