Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I mean, let's be real: if you have SBCL and QuickLisp most newer S-expression based languages don't have much to offer.



no

I readily admit, though, that not all software development needs to be flexible and big-application focused. To that end there are many things Common Lisp is not so good at. Common Lisp is not good at being pretty out-of-the-box, it's not good at minimalism, and it's not good at prescriptive or dogmatic programming styles. I've personally not been convinced of the various approaches to using Common Lisp as a scripting language (especially because of standard multi-stage execution). Common Lisp also has an unusual learning curve: there's an initial hump of learning Lisp's oddities (DEFVAR/DEFPARAMETER, CAR/FIRST, no hash table syntax, lots of EQ[UA]L-ity functions, systems vs packages, LOOP/DO/DOTIMES/DOLIST, "Neo, there are no lists in Lisp", ...), followed by a longer path of soaking in the extensive facilities offered by the language. There's just... a lot of content. And in part because of its idiosyncratic nature, no singular approach to learning it works for everyone.

Common Lisp is pretty anemic when it comes to extreme use of functional programming. It's wholly capable and serviceable, but most library writers don't go whole-hog with FP, and Common Lisp by default makes FP a little stuffy (it requires functions bound to variables to be called with FUNCALL, and it requires defined functions to be referenced with #' syntax). There is very little support for functional data structures; the FSET library seems to be what most people suggest.

https://old.reddit.com/r/lisp/comments/123edgv/im_considerin...


> Common Lisp is not good at being pretty out-of-the-box, it's not good at minimalism, and it's not good at prescriptive or dogmatic programming styles

These things help you learn to program, but they do not help you program.

At some point the box is open, at some point your problems are big and nobody else has done them before. It is in this moment that CL is good, and perhaps better than anything else.

> There's just... a lot of content.

That's some of the stuff that helps you program, because if you didn't have it and you needed it, you'd have to write it.

> no singular approach to learning it works for everyone.

So what? "Everyone" is your competition. Why do you care what works for them?


I’m relatively unfamiliar with lisps. Are all S-expression languages not created relatively equal? What is the difference between a “good” S-expression language and a “poor” one?


Well, tastes in programming languages differ from person to person of course; you may as well ask what makes Ada better or worse than Pascal or Algol68 and Rust.

I personally am very fond of the strong support SBCL has for type checking, which is something I find many Lisp-inspired languages just don't seem to care about.

Every programming language has its strengths and weaknesses, S-expression based languages are no exception, though what I consider a weakness in a language someone else may consider a strength. Things that come to mind immediately are CL's case insensitivity (Ricardo Signes' talk A Million Billion Squiggly Characters touches on the problems with case insensitiveness), Clojure's decision to randomly use square brackets for expressions that have no need for them (this is one thing I know that other people are fans of), and Bel's streams operating on bits (as in 1/8th of a byte).

Though what got me to try CL in the first place was someone mentioning that SBCL is fast, and given that it is still a GCed language, it really is. With Scheme I was bouncing back and forth between Scheme and C because I was unsatisfied with the performance, but with CL I don't feel a need to use C as it is fast enough.


Many Common Lisp users unfortunately have this tendency to refer to other Lisp dialects as "not real Lisp" and often don't bother to explore the value propositions of the newer dialects, particularly Clojure-inspired dialects such as Janet. At least, this has been my experience as a Clojure user for several years now.


I would think that there are many dialects, but they share a common core. Common Lisp is just one. Others would be Emacs Lisp, Visual Lisp, Interlisp, Standard Lisp, ISLisp (which is an ISO standardized Lisp). Something like Janet is further away, given that it is not a 'List Processor' - it does not use linked lists as a core data structure. It would be more a 'Maps Processor'. Rounded parentheses are neither sufficient nor necessary to be a 'real Lisp'. In a wider definition JavaScript is a Lisp. Maybe, but IMHO it is not very helpful to and it's not the most important categorisation for it. Personally I would also think that a language is not less useful/interesting when not labelled as core Lisp. A label does not make a language 'better' or 'worse', it just makes clear what to expect.

> often don't bother to explore the value propositions of the newer dialects

There are a lot of languages I would find interesting, besides those that one might or might not label as 'Lisp': Prolog, Erlang, Julia, Rust, OCAML, ...


There is endless variety in lisps and lisp-like languages. It's one of this language family's greatest strengths, and greatest weaknesses.


Apologies for the question, but to clarify you’re saying that you much prefer the libraries that QuickLisp provides and find Lisp languages lacking.

I’m debating whether to dive into Common Lisp for a new project. I’ve been a fan of Lisp for a while, much prefer parentheses over other notation, and have dabbled over the years by doing things like SICP and writing my own toy Lisp.

Common Lisp comes across as one heck of a battle-tested language and libraries. But I’m debating how much of a learning curve I’ll have on the front end just getting used to SBCL/Emacs/Slime and the various libraries. And I’m not sure that I “get” the interactive workflow yet but def would love to.


I can't speak for parent but I'm currently writing a one-man SaaS using common lisp on the backend and vanilla js on the frontend, and it's been great so far. SBCL's compiler produces very performant code and I find I can be very productive in lisp. The library ecosystem isn't quite as rich as, say, python's but it's still good.

My chief complaint is that if you stray too far off the "happy path" of well-known libraries the quality (or even presence of) the documentation tends to decrease dramatically.


Oh, cool. I’m thinking about something similar with SBCL plus vanilla JS. I’m not worried about libraries and these days try to be a library/framework free as possible. The web dev basics of an application server, access to an RDBMS, and possibly help spitting out HTML/CSS/JS are all I need. And it seems like Common Lisp checks those boxes. I’ll give quicklisp props too as everything I’ve tried to install ran on one go. That’s unfortunately not always my experience elsewhere.

Out of curiosity, have you done Lisp before? I’m curious if productivity gains would be lost in me ramping up.


I've dabbled in lisp on and off for a number of years but have never written it professionally.

Back in the early aughts I learned a much more orthodox way of programming with C++ in first year university and fiddled with a bunch of scripting languages making game mods and stuff in my teens and early 20s. C# is probably what I have written the greatest number of LOC in, so I'm very much an ALGOL normie.

Lisp isn't as weird as people like to pretend it is. Once I wrapped my head around the syntax (which takes maybe an hour) the biggest things I wrestled with were

- the type system (variables don't have types unlike C# and friends, they're just named registers where you can shove anything)

- CLOS (in my opinion it's kind of a leaky abstraction, not as good at encapsulating/hiding the underlying complexity as, say, C# or Java, but CLOS definitely has its strengths)

- the language-adjacent concept and nomenclature like Systems. What Lisp calls Packages are pretty close to what most other languages would call namespaces, and what lisp calls Systems are what other languages call Packages, or maybe libraries.

My experience has been that it's a very expressive language and easy to write once you get into the flow of things.


> (variables don't have types unlike C# and friends, they're just named registers where you can shove anything)

This depends on the implementation one uses: SBCL does type checking:

  * (defvar *a-number* 0)
  *A-NUMBER*
  * (declaim (type (integer 0 100) *a-number*))
  (*A-NUMBER*)
  * (setf *a-number* 10)
  10
  * (setf   *a-number* "ten")
  ; in: SETF *A-NUMBER*
  ;     (SETF *A-NUMBER* "ten")
  ; ==>
  ;   (THE (MOD 101) "ten")
  ; 
  ; caught WARNING:
  ;   Constant "ten" conflicts with its asserted type (MOD 101).
  ;   See also:
  ;     The SBCL Manual, Node "Handling of Types"
  ; 
  ; compilation unit finished
  ;   caught 1 WARNING condition
SBCL does that a compile time, too.

> - the language-adjacent concept and nomenclature like Systems. What Lisp calls Packages are pretty close to what most other languages would call namespaces, and what lisp calls Systems are what other languages call Packages, or maybe libraries.

Lisp is old, these names are from end 70s ("package") and ~1981 ("system") - at that time they were used in the MIT Lisp Machine system software.


>SBCL does type checking

It does, and values have types but variables don't. Without the DECLAIM facility you can do the following:

    (defvar *foo* nil)
    (setf *foo* 123)
    (setf *foo* "dank memes")
Whereas in C# you cannot do the following:

    int i = 123;
    i = "dank memes";
Thats all I meant.


No, the differences is that in Common Lisp / SBCL type declarations are optional (note though: there is also type inference in SBCL), type declaration are more verbose, type declarations are sometimes a separate expression and a variable by default has the type T, unless the compiler can infer another type.

  (declaim (type (integer 0 100) *a-number*))
Above does not declare the type of a value, it declares the type of a variable to be an integer in the range of 0 to 100.

In SBCL we can also query for the type of that variable:

  * (defvar *a-number* 0)
  *A-NUMBER*
  * (declaim (type (integer 0 100) *a-number*))
  (*A-NUMBER*)
  * (SB-CLTL2:VARIABLE-INFORMATION '*a-number*)
  :SPECIAL
  NIL
  ((TYPE MOD 101))
The third returned value is the declared type.

Another example: a function with two local variables. One variable is declared to be of type INTEGER and the other of type STRING. We then try to set one variable to the value of the other:

  * (defun foo (a b)
      (declare (type integer a)
               (type string b))
      (setf a b))

  ; in: DEFUN FOO
  ;     (SETF A B)
  ; ==>
  ;   (THE INTEGER B)
  ; 
  ; caught WARNING:
  ;   Derived type of COMMON-LISP-USER::B is
  ;     (VALUES STRING &OPTIONAL),
  ;   conflicting with its asserted type
  ;     INTEGER.
  ;   See also:
  ;     The SBCL Manual, Node "Handling of Types"
  ;
What you see above is that the SBCL compiler a compile time detects a type error and warns. There are no values involved.

See https://en.wikipedia.org/wiki/Gradual_typing


Strongly disagree. SBCL is not embeddable. It produces huge binaries. Managing and versioning dependencies is very difficult.

Newer dialects like Janet and Fennel address these deficiencies.


> It produces huge binaries.

My binary with dozens of dependencies (the compiler, the debugger, a web server and all that's required for a web app) is ±30MB, it starts up in 0.40s. The non-compressed binary weighs 120MB and starts in 0.02s.

> Managing and versioning dependencies is very difficult.

You can use Qlot and CLPM these days.

Alexander of 40ants made a demo: https://www.youtube.com/watch?v=jLkqYVTqM38 (with english subs)


Thankfully SBCL is just an implementation and not the language ;)

There are alternative implementations, like ECL, which is capable of transpiling to C and producing small binaries and dylibs. Then there are implementations like CCL, which have low memory footprint (a freshly booted image consumes ~6.8 MB RAM on my Mac). Lastly, there are commercial implementations like LispWorks and Allegro CL which offer tree-shaking, unlike all other implementations.


That's why Common Lisp is a standard and has different implementations.

ECL for example is called "Embeddable Common Lisp". https://ecl.common-lisp.dev/

ABCL is embeddable into Java.

LispWorks and Allegro CL can compile to shared libraries, which are embeddable.

SBCL, OTOH was not developed with the goal to be embeddable.


see ulisp [0] for a lisp with small memory footprint

there are also many other subsets of common lisp you can use for various things that require a small memory footprint

i also want to know what does Janet bring to the table that a Scheme like a Gerbil [1] does not?

[0] https://ulisp.com

[1] https://cons.io


Does Gerbil run on Windows?


given that Gambit does, i would say it is possible


Thanks! I had only looked at the Gerbil docs and couldn’t find anything about Windows.


Ah Fennel i love that language




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

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

Search: