1. 52
(defun browse-menu ()
 (let ((default '((:front "hottest" "/hot")
                  (:new "newest" "/new")
                  (:pop "top all-time" "/pop")
                  (:topsub "top submitters" "/topsub"))))
   (if (logged-in-p)
       (append default '((:saved "saved" "/saved")))
default)))
  1.  

  2. 21

    I love how this thing is written: only plain old Lisp that directly translates to plain old HTML and plain old SQL. No complex template engines, ORMs, multiple inheritance, events, callbacks and modern complex machinery I’ve struggled with in the past.

    Nowadays I tend to follow a similar simplistic approach to web programming, and it’s so much better. I don’t think I’m the only one, and I think many of us try to “rediscover” this simplicity through recent projects like HyperScript or Ecto.

    I think we should learn a lot form the past.

    1. 10

      I have taken to writing web “apps” in Ruby using only the standard library. It’s way more than enough. And extremely educational to use: you’ve got to put all the pieces of a web stack together yourself. After building a few personal apps this way I have a few utility classes that cover the abstractions I care about.

      The biggest is a 50 line SimpleController base class that extends WEBrick::Servlet, pre-processes request data, wraps responses with some default headers, and renders ERB templates with a render method like Rails does.

      And I set up WEBrick to authenticate my client TLS certificate. I love having all the security and convenience of ssh public keys for my personal web apps too. Although I wouldn’t bother with that in a million years if MacOS Keychain Access didn’t make it trivial to generate client certificates.

      WEBrick - built in HTTP server

      • multi-threaded
      • access and error logs
      • static file server
      • multipart/form-data (file upload) support
      • cookies support
      • HTTP Basic Auth
        • pluggable UserDB backend
        • comes with Apache-style htpasswd and htdigest backends
      • SSL/TLS, including client-side certificate validation

      ERB - built in HTML template engine

      • did you know this was in the standard library?
      • WEBrick can run .rhtml files as ERB
      • erb cli tool ships with Ruby, great for debugging templates

      YAML::DBM - built in database

      • transparently stores objects as YAML in a key-value store
      • syntax identical to hash map, e.g. db['key'] = obj
      • original DBM was written by Ken Thompson at Bell Labs
      • multi-threaded with just a couple lines of code
        • DB_LOCK = Mutex.new
        • def transaction() DB_LOCK.synchronize { yield DB } end
        • transaction { |db| v = db[k]; v.a = b; db[k] = v }
        • if you think I’m joking then benchmark it
        • literally the same strategy used by MongoDB until 2015
      • for sufficiently simple apps SQL is more trouble than it’s worth
      • for kicks implement the WEBrick::UserDB interface in a 10 line class

      Minitest - built in unit test framework

      • actually a good test framework
      • default test framework for Rails apps

      Kernel.open - default open call is special magic

      • require 'open-uri' makes regular open work on http[s]:// URIs
        • Ruby stdlib vs Python Requests library:
          • content = open('https://google.com').read
          • content = requests.get('https://google.com').text
        • also adds .open method to URI objects
        • handles redirections, etc.
      • calling open on a pipe-prefixed string opens a subprocess
        • e.g. p = open('|cat'); p.write('neat'); p.read() == 'neat'
        • for small projects shelling out is often the easiest way to do certain things

      Thread / Queue / Mutex / ConditionVariable / Monitor

      • I find Ruby’s traditional concurrency classes extremely usable
      • Threads and Queues are just as easy as goroutines and channels
        • it’s 2018, threads are pretty cheap
      1. 9

        I’d argue it’s not about rediscovering something we forgot. Doing things simply is actually really, really hard. And everyone has to learn it by themselves, I don’t believe it’s a teachable technique. And it just takes time. And by the time you’re there you couldn’t care less about hyping up your acquired knowledge and putting it on display in the form of a framework :-) That’s why trending hot stuff is invariably over-complicated.

        1. 3

          I wrote a web app in C++ (long story) and tried to do this. For HTML I made a DSL using variadic templates and user-defined operators so I could write div("class-name"_class, p("Hello there")) etc, found a nice SQL DSL to write queries in a similar fashion, and so on. It was simpler to me than something like Django, but of course I would never use C++ for a public web app.

          1. 3

            OpenResty is pretty nice in that regard. Just a scripting interface to nginx.

          2. 5

            It’s nice of them to release the sourcecode (I remember the kerfuffle when they ported to python), but, wow, the lack of documentation hurts. I remember being in the “lisp is so readable it doesn’t need comments” camp, and I may have been wrong.

            Honestly, though, a place to start might be enough. IIRC, they were using CMUCL and Hunchentoot. Anybody know/remember the build process for those?

            1. 5

              I think that was wrong because understandability often goes down as complexity and power go up. LISP is super-powerful with people applying that power in many complex ways. Especially the difference between what you see and what’s going on underneath macros. So, I’d say it needs more documentation or source control if aiming for easily-approachable or predictable codebases.

              1. 5

                It used ASDF to build (see the .asd file).

                1. 3

                  At the risk of being snarky those are actively maintained projects and you can simply check their respective websites for how to install and use them.

                  Hunchentoot is in quicklisp and installs easily with (ql:quickload :hunchentoot). The SBCL fork of CMUCL is more widely used than CMUCL, and can be installed with “apt-get install sbcl”, or pre-built binaries for 5 or 6 platforms can be downloaded from their website.

                  1. 1

                    The SBCL fork of CMUCL is more widely used than CMUCL

                    Sure, but SBCL forked, like, twenty years ago, and this code is from more like 10-15. That is, I’m sure they were aware of SBCL, but I’m pretty sure they chose CMUCL instead.

                    And, yes, if I’m certain they’re using CMUCL and Hunchentoot, and am familiar with both tools, and am familiar with ASDF, and know I need quicklisp, and am also familiar with that, then I suspect I wouldn’t have too much trouble scrapping together a build method that might work. However, I haven’t been in the lisp ecosystem for years, and don’t know for certain which lisp and which web framework they were using.

                    Looking at the asd file, it seems they were using TBNL, which predates Hunchentoot (in name). Will it build with Hunchentoot? Not sure – how API-compatible is modern Hunchentoot with that old version of TBNL? For that matter, what version of TBNL was used? Are we certain this code can build at all?

                    A note saying “you need the following versions of the following things to build this: x,y,z, …” would be useful if they don’t have the resources to put together a modern README document.

                    Also more useful than the current lack of documentation would be a note saying: “this has not been built in years, we don’t know the needed library versions, and it’s not clear whether this can be built at all, but we wanted to provide the source anyway”.

                    So, I appreciate the fact that some of this is discoverable, but 1- it’s only discoverable if you’re already an up-to-date lisp hacker, 2- even then it might not be fully discoverable, and 3- standards for documentation have changed over the past couple decades, and this doesn’t even meet the standards of many years ago.

                  2. 2

                    eh .. the whole platform use to be open source but they closed it a while back. They claimed it was simply too difficult to run the entire thing and there was no point in keeping it OSS.

                    I dunno .. After Reddit started banning tons of communities, removed their warrant canary and their CEO was caught editing comments, I dismissed the entire platform. I rarely use it; maybe really specific communities.

                  3. 2

                    What I’m most interested in knowing is what is Reddit written in now, and what specific business or technical problems made them switch away from Lisp? Reddit is a very popular website, and if Lisp was not in fact used to get it to where it is today, that says something about how we ought to evaluate Lisp as a language.

                    1. 4

                      what is Reddit written in now,

                      They moved from lisp to python, though I don’t know if it’s still in python.

                      and what specific business or technical problems made them switch away from Lisp?

                      They posted a lengthy blog about why they ported away from lisp at the time. Unfortunately, it looks like the blog post is gone. There’s a bunch of discussions still around, though. Also some other evidence of the lisp community response.

                      Short version: it was technical. Libraries didn’t exist or weren’t sufficient, lisp implementations didn’t work cross-platform, so development was painful, and they continued to have difficult-to-debug slowdowns and site crashes. Stuff like that.

                      Of course, this was over a decade ago, so I strongly suspect the lisp situation has changed.

                      1. 3

                        Of course, this was over a decade ago, so I strongly suspect the lisp situation has changed.

                        It’s currently powering Grammarly (circa 2015) so it sounds like it.

                        One of the common complaints about Lisp that there are no libraries in the ecosystem. As you see, 5 libraries are used just in this example for such things as encoding, compression, getting Unix time, and socket connections.

                        1. 1

                          Looks like they’re not actually using it for a webapp, but instead for a back-end process. That’s a different use case than reddit had.

                          Also, I note that they’re still using two different lisp implementations, one for production, and one for local development. That was a big issue for reddit at the time. I wonder how much energy goes into implementation difference issues.

                      2. 2

                        Lisp still powers Hacker News, afaik.

                        1. 1

                          I thought HN was arc, Paul Graham’s take on scheme?

                          1. 1

                            Indeed, that’s my understanding. I should have been more clear, by “Lisp” I was talking about the Lisp family of languages, not Common Lisp specifically.

                        2. 1

                          Core is still Python, newer components are being written in Node.js. PostgreSQL was historically the main datastore, with Cassandra serving a secondary role, but data is being re-homed to Cassandra due to scale.