Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Ultralisp: A fast-moving Common Lisp software distribution (ultralisp.org)
164 points by lerax on June 16, 2019 | hide | past | favorite | 65 comments


Slightly tangential, but I wish some Lisp would make a serious comeback and challenge mainstream languages. For this purpose, libraries are essential. So better tooling would help, and that's why Ultralisp and Quicklisp are interesting.

Clojure is very nice. I have used it for several projects. But sometimes I would prefer not to rely on Java libraries so much, and cleaner stack traces.

Racket may get some critical momentum now, with the whole merge with Chez.

I don't have high hopes for a Common Lisp implementation, as the ecosystem has become too fragmented and stagnant. But I wish I could be surprised here. Shen introduced some great ideas to make a powerful static typing an option in Lisp [1].

[1] http://www.shenlanguage.org/


Re statically typed Lisp, I’m keeping an eye on Carp [1] which seems to be a quite active project.

[1] https://github.com/carp-lang/Carp


Common lisp meets Rust, I'm intrigued.

All these new exciting programming languages over the past ~5 years or so are quit exciting. I'm starting to believe that in the not so far future we'll look back on that time period between the late 90s up to the mid 2010s as some kind of a dark age for programming, where we kept using those inelegant, inefficient, hacky languages carried by Moore's law and an incredible demand for new software being written in huge quantity extremely fast, quality be damned.

Now that the gold rush starts to cool down there seem to be a lot of very interesting work to take a few steps back and do it right.


I think your dark age and gold rush theory has some truth to it. The whole industry culture and practices changed during that period, but we're starting to see things like people interested in Rust, even though it's not pitched as a faster way to make slicker generic Web sites and phone apps.

I'm also hoping that Racket (which is is like a secret oasis community) will get more attention, and someone will dust off some old Paul Graham writings about startups and Lisp, and some startups (probably ones who're not just doing another cookie-cutter madlibs startup) will decide to use Racket initially. (Disclosure: I have an interest in promoting Racket, because I'd love to help build startups in Racket, and also recruit top programmers with Racket as a carrot.)


I am planning to kick off a biotech startup this Fall around a great idea / discovery, and it will be done in Lisp. Probably in Racket.

I already received some cool VC funding offers. I'm evaluating them, and planning stuff.

For my use case, Racket is perfect, so it has big chances.


As you're looking for co-founders and/or early hires or consultants, definitely post to the `racket-users` email list (currently also a Google Group), which is the most canonical forum for Racket.

And feel encouraged to email me directly. I might be available then myself, and, if I can get some understanding of your needs, I might also know some other good candidates.


I will do both things, thanks for the tips!


What do you think are good learning resources for learning racket for an experienced (functional) programmer? Is there a book that isn’t focused on learning to program?


For an FP person, you might want to instead start with skimming, for half an hour, the R5RS or R7RS Scheme paper, for the base language from which Racket grew (don't worry about the first-class continuations unless you want to). Then go to the Racket Guide or Racket Reference table of contents, to look for things that you might be looking for from your past FP experience, like `match` (though it's maybe not used as much as you're familiar with). Then look into some of the strengths of Racket, like syntax extension and `#lang`. (If you want additional treatment of syntax extension and `#lang`, see things like Hendershott's "Fear of Macros", and Butterick's book.) Also skim the large list of add-on packages, to get a sense of what's there. Eventually read through the Guide and Reference at your leisure.

There's an imposing wall of manuals at: https://docs.racket-lang.org/

Racket isn't purely FP, but it can be used that way, even with the base language. There's also at least one lazy `#lang`, and you can make more.


Oh, you might like another difference between Racket and R5RS Scheme: Racket has changed some basic Scheme types, like pairs/lists, to be immutable by default. And various additional Racket types, like `struct`s, also have both immutable and mutable variants and parts.


Thanks! Just adding a link to Butterick’s book, “Beautiful Racket”: https://beautifulracket.com/


Are you experienced in Common Lisp? Racket is multiparadigm too.

As such, many good multiparadigm books will be of great help. E.g. SICP, but also the much less known yet equally fantastic CTM. None are written in Racket, although SICP with Scheme is close, but many concepts can be ported.

There's also excellent Lisp literature like Lisp in Small Pieces or PAIP, that are always worth to consider.

Racket also implements most of http://www.eopl3.com/, which is a great textbook.


For working through SICP, you can actually use the Racket tools, like the DrRacket IDE. We rigged up a simple `#lang sicp` that emulates the version of MIT Scheme used for SICP problem sets: https://docs.racket-lang.org/sicp-manual/


Thanks. I don’t know Common Lisp, but I guess the knowledge will be transferable.



What development tooling do you use for Racket? I tried Dr. Racket and it felt pretty janky compared to SLIME for CL.



After working a lot with statically typed languages, I’ve been doing some work recently with a dynamic language, and it feels refreshingly fun...

Granted, I’ve been using elixir and erlang, where the use of pattern matching matching and immutability give you a lot of the benefits that modern static languages have, but I wouldn’t mind a new wave of modern dynamic languages, or at least static ones that feel more dynamic (Carp may fit in that spot).


If you haven't looked at it, then (lisp (flavoured (Erlang))) will appeal to you. [1]

[1] http://lfe.io


Research languages like Mesa/Cedar or Modula-3.

We had a dark age of too much VM and scripting languages, and only now getting back how computing could have looked like.

For example, given Anders background imagine how .NET would have been if it was fully AOT compiled and the same low level features from Delphi since version 1.0.

Or if C++ Builder wasn't the only surviving example to RAD development with C++, before others started to build on top of LLVM toolchain.


There’s also Coalton — a typed implementation within Common Lisp https://github.com/stylewarning/coalton/


Another is clasp https://github.com/clasp-developers/clasp

There are a few interesting talks on yt: https://www.youtube.com/watch?v=mbdXeRBbgDM


Oh man this is going to be a fun naming conflict to resolve... https://github.com/google/clasp


I really wish someone would put together a new standardization of Common Lisp. The language could be much better with a few minor tweaks: for example, (function +) should be a generic function --- that it is isn't is a silly oversight. Compiler macros should have access to type inference information so that they can do a better job: right now, they're purely syntactic and give up lots of optimization potential as a result.


We already have all of the above in the form of libraries.

Common Lisp is extensible.


We don't have any of those. #'+ is part of the core and can't be extended. There's also no facility for type propagation in library form.


To extend #'+, equality functions and much more, see https://github.com/alex-gutev/generic-cl/. See also https://github.com/pnathan/generic-comparability


You can shadow + and use your own implementation in your code, falling back to cl:+ when appropriate. Changing the existing language may be difficult, but building a modified language on top of it is possible: see Shen.


The best tooling still survives on Allegro and LispWorks implementations, but without a major backer pushing it down dev throats like the OS vendors do with their SDKs, there is little hope for such uptake.

We are better off hoping for Lisp inspired languages like Julia or Clojure to win wider market adoption.

Maybe what is really missing is having a Lisp for WebAssembly, being advertised as the best implementation available everywhere and such.


There is a thread on Reddit, discussing different possibilities to build webasm from Common Lisp:

https://www.reddit.com/r/lisp/comments/7z7wuq/has_anyone_con...


Thanks, looks interesting.


I spend most of my time now in Chicken Scheme http://call-cc.org/ and it's very productive, has a ton of libraries ("eggs"), and makes nice, fast native binaries. Scheme's right on the edge of ascetic discipline and productive tooling, where so many languages are much too far either way.

Racket's weird, not quite a Scheme anymore, tons of libraries but they're often hard to use, and the object system infected too much of it. And performance is poor even with Chez underneath, there's just too much stuff on top. It's a better teaching tool with the tutorial sub-languages than a production language.

I can't work in CLISP, it's like scavenging a junkyard for parts where some work, some haven't for 30 years. Some people love that experience.

Strong typing (also in Typed Racket) isn't going to improve anything, but it's good for marketing to enterprise people.


I suggest you take a look at Gerbil Scheme, based on Gambit-C.

https://cons.io


>I don't have high hopes for a Common Lisp implementation, as the ecosystem has become too fragmented and stagnant.

I work on CL everyday and don't think it's fragmented. Stagnant, maybe, when comparing it to the mainstream languages.


Racket in particular has one of the easiest ways to use an SMT solver via Rosette (also super easy to install).


I'm not sure this is a great idea.

I have a couple projects in QuickLisp, and more than once I've broken them after I pushed incremental or non-working changes to my repo, didn't go back and fix them in time, and QL pulled the broken code.

Developing in branches would solve the problem, but not everybody does that on smaller informal projects.

On the other hand, I've also been annoyed waiting for bug fixes to trickle through to Quicklisp, so it's not an entirely bad idea...


The bleeding edge isn't for everyone.

But then again, neither are monthly releases.


Pinning libraries using Qlot solve the issue of being on the bleeding edge.


Monthly releases + a few bleeding edge libs strategically cloned into /local-projects is the best strategy.


I don't understand what problem this solves.


In the contemporary Common Lisp ecosystem, software is distributed via Quicklisp[1], which is a centralized software repository, where, once a month, a new software distribution is created, encompassing the most recent releases of all software included in the dist. This means that changes in software can take up to a month to be reflected in Quicklisp.

Ultralisp is a Quicklisp-compatible distribution, except it's a bleeding-edge one. Each time a piece of software included in it releases a new version/release/commit, a new dist is created, and the modified software is available in Ultralisp within minutes.

[1] https://www.quicklisp.org/


Ah. Understood. I solve this problem by forking every Quicklisp repo I use, and telling ASDF to look in my local clones first. This also solves the problem of making it easy to submit a pull request when I fix a bug in a Quicklisp library.

Also -- and this is very important to me -- it means I'm in control of which version of every library I use. I've been burned too many times by Quicklisp "updating" a library that was previously working which doesn't any more. Now I have direct git control over my version coherency and I'm a happy camper.


Have you looked at Qlot (https://github.com/fukamachi/qlot)? It solves the problem of reproducible builds.


Thank you,that is a really good idea.


Is this as easy to do as it sounds? Any chance you have documented any curves along the way?


I have been doing this for a while by following a pattern found here[0]. I typically follow this and copy every asdf package dependency into the working directory of whatever project I'm working on [setting the subdir-search-registry to (list (truename "./asdf-systems/")) and placing the files into a subdirectory of that name] .This way I have the option to make changes in them without affecting anything else on the system depending on the same package. In general this means I use Quicklisp as a (huge) convenience in finding packages when programming interactively in the REPL, but not in deployment. I think this setup is also nice because it is dead simple to drop in copies of asdf packages from the web that aren't found in the Quicklisp library.

[0] https://en.wikibooks.org/wiki/Common_Lisp/External_libraries...


I do it like this because the asdf central-registry variable (which I can't write here because of asterisk problems) is supposedly deprecated:

  (asdf:initialize-source-registry
    (:SOURCE-REGISTRY
     (:EXCLUDE "exclusion-string1" "exclusion-string2")
     (:TREE #P"/Users/me/Lisp/my-repos/")
     (:TREE #P"/Users/me/Lisp/quicklisp-repos/")
     (:TREE #P"/Users/me/main-project/src/")
     :IGNORE-INHERITED-CONFIGURATION))


It's all manual now but not that hard. Buried in Quicklisp are the locations of all its repos. The reason I haven't automated it is I don't know if there's a Github API for "Please fork this URI into my account if that's not already done." (Plus not every repo is on Github, and not every QL repo is a proper repo.) I haven't bothered to look into automating it because I don't use that many QL libraries, so manual operation is fine for me. Happy to work with you if you want to try to automate the process.


About 90% libraries from Quicklisp are hosted on the GitHub.


Not everything needs to solve a problem. Sometimes it's just fun to work on stuff.


Are there any kind of Semantic-Versioning like controls?


Quicklisp and ASDF do not support semver. But you can use Qlot to pin some libraries to a particular version.


Url changed from https://github.com/ultralisp/ultralisp to the project page.


uses:

- docker

- mailgun

- s3

facepalm


"Please don't post shallow dismissals, especially of other people's work. A good critical comment teaches us something."

"Don't be snarky."

https://news.ycombinator.com/newsguidelines.html


S3 is a protocol with a myriad of compatible providers. I wish the mailer was SMTP instead of an API. I don’t fully understand the issue with Docker; it’s widely accepted for software distribution and has a multitude of alternative runtimes that require very little config modification.


S3 is defacto proprietary protocol subject to AWS whims, such as recent v4 update of signing algorithm.

Docker, while not proprietary, still subject to moving fast and breaking things, which was amply criticised here on HN.

Common Lisp should stay a refuge from all the rug pulling around. While it's true that quicklisp is far from bedrock, adding volatile APIs into the mix won't help.


From my experience, Docker helps quite a bit with CL stuff in many cases. When you use some shared libs via CFFI, things can get fragile quick, start depending on a particular shared library version on the host system etc. So your app, for instance, works fine on Debian jessie, then you have to upgrade your host system to stretch and oops, it broke here and there. You update your quicklisp dist to fix shared lib incompatibility problem and oops again, you need a week to fix stuff that broke (this reflects some problems with CL library management, too), but you need to have your app up and running on the new system yesterday. If you wrap your CL app in a Docker image, you can continue running it on the prev distro version till you fix it to be compatible with the newer one. And that's just one example.


Right, CFFI is another can of worms. It is sometimes questionable whether the time saved by reusing C code isn't lost by debugging and integration issues. For example I ended up avoiding cl-async (a wrapper over a C library) due to these.

In my mind reimplementing in CL is better bet than pulling Docker.


Well, I did write quite a bit of CL code for money, but it's hard to get paid for reimplementing every library that one may need in CL ;(


I have not meant it in such extreme way at all :(

Just this: if something interferes badly with a basic CL feature such as SLIME (cl-async does), toss it.


cl-async works pretty well with SLIME if you use its SLIME REPL integration feature that I contributed several years ago. https://github.com/orthecreedence/cl-async/blob/master/src/r...

It basically starts an event loop in a separate thread and then wraps all of the SLIME's evals so they're executed from within that event loop.


> I ended up avoiding cl-async

What do you use instead?


I reimplemented the parts I needed using threads+usockets. There's no fundamental reason it can't be built directly on OS async interfaces, even without threading, instead of C library.


> If you wrap your CL app in a Docker image, you can continue running it on the prev distro version till you fix it to be compatible with the newer one. And that's just one example.

That is perfect match for guix channels too.

What I do is maintain a repository of package definitions (that possibly inherit from guix master package definitions) and only change a few hashes here and there when I need.




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

Search: