Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Common Lisp – Myths and Legends (2002) (lispworks.com)
107 points by susam on Dec 22, 2022 | hide | past | favorite | 67 comments


Personal Edition Limitations

Please note that the LispWorks Personal Edition, distributed free of charge, has the following intentional limitations:

    There is a heap size limit which, if exceeded, causes the image to exit. A warning is provided when the limit is approached.
    There is a time limit of 5 hours for each session, after which LispWorks Personal exits, possibly without saving your work or performing cleanups such as removing temporary files. You are warned after 4 hours of use.
    The functions save-image, deliver, and load-all-patches are not available.
    Initialization files are not loaded."
And it is not popular because ...


You can get SBCL for free with no limitations which actually beats Lispworks on performance AFAIK: https://www.sbcl.org/


Not around the time where it mattered. I loved Lisp, but when our lab moved to an x86 architecture it was Allegro big bucks or nothing.

I was referring to the above pestering of the user base, not that there aren't alternatives.


I used this at work for months. When it quit, I just reloaded and kept going. It was for some local tooling work I was doing. I never ran into any of the limitations save the timeout, which for me was no big deal.

I already owned a version at home for myself (it was, like $249 or something at the time), but this was also a time where folks still paid for software. Not everything was done on Linux with GCC, although Java was free at the time.

A year before this I had my previous company pony up the $$$$ for Delphi's Enterprise edition (whatever it was called). That was a lot more than LW was.

I contemplated getting Franz, but I never wanted to call for a quote, and they didn't publish prices. But I know they were expensive as well.

Smalltalk, Lisp, Delphi, Visual Studio, everything cost money. And though Java was free, lots of folks were selling IDEs for it. I used Emacs back in the day, and we paid silly amounts of $$$$ for WebLogic.


There is a multitude of very effective free CL implementations.


One big deal about Lispworks is that it comes with a nice GUI creation toolkit. If you need to write a program with a GUI, it's easy with Lispworks and difficult with the free implementations.


"Who's Using Lisp?" but today? An ongoing list: https://github.com/azzamsa/awesome-lisp-companies/ (Google (they also contribute to SBCL), quantum computing companies, Intel, millions-LOC CAD systems, chatbots companies, trading services, big data analysis providers, the NASA, banks, cloud backup providers, music composition software… and smaller companies and one-person businesses)


That list is not curated and kept up to date, and so it looks more impressive than it is. Several of those places are defunct or have put the Lisp codebase into maintenance mode or sunsetted it entirely.


(edited) I just removed companies marked as "disappeared"! (10 of them) If you have more info to share, please do.

This list is also not exhaustive.


care to elaborate? the maintainer regularly updates the list


One thing that puts me off about Common Lisp is functions that do multiple different things depending on a flag passed to them. (format nil s) formats a string, whereas (format t s) formats a string and prints it to stdout. This doesn't look like good design.


There is a rhyme and reason to it. There is a stream argument, with the convention that if NIL is used, the stream is an implicit string output stream created for that call, such that the string is returned. And if T is used, then it's a shorthand for standard output. The argument may also be a string with a fill pointer.

This convention isn't just in format. It has a name, stream designator:

http://www.lispworks.com/documentation/lw50/CLHS/Body/26_glo...

Other functions like write support the convention.

Moreover there is a broader designator concept at play: there are other kinds of designators.

http://www.lispworks.com/documentation/lw50/CLHS/Body/26_glo...

A designator is some object that by convention stands for another one, under the semantics of some function.

For instance, functional arguments may be function objects or symbols: (mapcar #'list ...) or (mapcar 'list). The list symbol isn't a function, it's a symbol; the reason you can use it as a function is that it's accepted as a function designator. When you call a symbol as a function, it is resolved to the function via its global function binding.

Another kind of designator is the spreadable argument list designator: http://www.lispworks.com/documentation/lw50/CLHS/Body/26_glo... Some functions use this to take a single object or a list in the same argument position. It makes the functions nicer to use in the case when there is just one object, not having to specify the argument as (list arg).


> (mapcar 'list)

Thank you for sharing that, I didn't know that was possible.

I also tried just doing 'list at the repl, and sure enough it gets recognized as a function.

I thought I could break it by doing this:

(let ((list (list 1 2 3)))

   (mapcar 'list list))
I even tried adding on (funcall 'list list) to that block and it still works the same as if I had used (funcall #'list list) ....

I guess it works because the list I bound in the LET isn't referenced as a symbol so FUNCALL etc can distinguish one as a symbol that has a function and the other as the name of a binding ...

Was not expecting these results, so I'll need to review symbols and namespaces ...


You can't break it with LET because functions are in a separate namespace with variables, and because the function lookup done for 'LIST isn't in the lexical scope; it's done inside the mapcar function in another scope, or maybe in a lower-level function like funcall or apply.

Because of separate namspaces, you can't break this either:

  (let ((list '(1 2 3)))
    (mapcar #'list ...))
But the following will break it:

  (flet ((list (x) 42))) ;; actually this is undefined behavior: see below
    (mapcar #'list ...)) 
#'list is (function list) which is lexically resolved, and so it refers to the local function flet. If we use 'list, that is unaffected; it goes to the global one.

This is a bad example because redefining the standard list function in any scope is not well defined behavior. Implementations can allow it or diagnose it. Because it's undefined behavior, implementations don't have to worry about breakage of list uses which occur in macro expansions. E.g. if the syntax `(,foo ,bar) happens to compile to (list foo bar), and your redefinition of list has taken effect in that scope, then that syntax has broken. Oops!


> the function lookup done for 'LIST isn't in the lexical scope; it's done inside the mapcar function in another scope, or maybe in a lower-level function like funcall or apply

Ah, OK, I think that's the key part I was missing ... that explanation also accounts for what I saw in the REPL ... thanks again! :)


It makes sense when you understand what it's asking you for. That first argument is you specifying an output destination. For example, would you like to write to an open file, to an open port, to whatever you want. Specifying `t` is the current standard output, whereas nil is you saying "no, just give me the string".

Also, `(format t "str")` does not return a string. At least not on SBCL or CCL.


thats right. the spec states that if destination is non-nil then format returns nil. otherwise a string

http://www.lispworks.com/documentation/lw50/CLHS/Body/f_form....


Still, why not have a function that formats a string and another that outputs it somewhere, instead of one that does two unrelated things?


My guess is that it's for efficiency. You have to dynamically allocate a string and then copy it to the destination if you separate "format" and "output". If you combine them, then you can directly output during formatting to your destination. Eliminating this inefficiency while separating "format" and "output" requires some sort of lazy interface or language hack.


Combining formatting and output is quite common - C has it in the printf family of functions (some of which do not output into anything, but return a string). Similarly, Java’s output streams have a format method, which can output to whatever, or fill in an array which you can later convert to a string.


Simply, because they are not unrelated. It would be duplication to have two separate functions to do two tasks that have so much in common.


What does formatting a string and sending a string to a file have in common?


FORMAT does not send a string to a file.

It executes a program in a domain specific language which creates output to a stream.

This does a bunch of operations. The print functions are being executed on an output stream. If the ARG is NIL, then FORMAT creates a string output stream and later returns the generated string.

  (format nil "~a" 3)
is just short for:

  (with-output-to-string (stream)
    (format stream "~a" 3))
~a is then an operation which writes the argument 3 to the output stream.


I was replying to your original post, did not notice you posted something different here. Formatting a string and then either returning it or sending it to stdout (or any other stream) has too much in common. The work is done in the formatting, sending is just an after thought.

In a sense, this is similar to the parentheses and the prefix notation: it can be distracting if you are not used to it, but after a while it becomes very convenient.

And I do not mean to sound snobbish, but you can easily write a couple macros to have different syntax for these two tasks if it really bothers you.


#'format knows nothing about files; it only knows about streams, which is what its first argument designates.

A point I try to stress with new CL programmers is that if you write new I/O functions to expect a stream designator they're much more flexible than if they expect a pathname.


We're talking about I/O here, so we're already outside the domain of functional programming: It's necessary to specify where the output is supposed to go, and that's what format's first argument is for.

If you want purely functional string creation, #'format can handle that by passing it nil as its "where" argument.

In both cases #'format does the same thing; the only difference is where the output goes. If #'format knows it's operating non-functionally it can avoid consing up a string and send its output directly to the destination. So it's not necessarily the case that (format t s) creates a string at all.


format is not just a function. it is a domain specific language. it even has a wikipedia entry, all its own. Like it or not, nothing similar exists in any other language

https://en.m.wikipedia.org/wiki/Format_(Common_Lisp)


> Like it or not, nothing similar exists in any other language

Uh, what? It's not that different from the printf metalanguage (more powerful, sure, but not that different and inspired by printf)


> more powerful, sure, but not that different and inspired by printf

bit of an understatement. it is an almost turing complete version of printf.

https://arcanesentiment.blogspot.com/2009/02/value-of-extens...


> format is not just a function.

The article you linked literally starts with:

> Format is a function in Common Lisp…


"Not just a function" does not mean that it is "not a function."

But I agree with your original point. "format" is not the most descriptive name for something that "formats and maybe prints."


this one is particularly strange but it seems cultural, scheme also works the same

for printf debugging it's one more parameter you don't wanna type :)


> (format t s) formats a string and prints it to stdout

FORMAT runs a domain specific language, which causes various print operations to an output stream.


How old is this? Yahoo has surely revamped its code in the past 20 years (if Yahoo stores even exist any more) and John Mallory left MIT decades ago.


Text from 2002 looks identical: https://web.archive.org/web/20021105131238/http://www.lispwo.... We've put that in the title above.


"Copyright © LispWorks Ltd 2000-10"


> John Mallory left MIT decades ago

Not true, and his name is spelled Mallery. No idea if he reads HN.


He seems to spend most of his time in the mountains


Since Covid MIT has been kind of a ghost town. Lots of people are working remotely.


Yahoo! Store is what Paul Graham's startup Viaweb became after Yahoo acquired them in 1998.


Kind of amazing they are still a going business. I didn't realise any companies really used lisp for anything. I assume whoever is paying them money is doing so for some really niche or legacy?


I am a current LispWorks customer using the product for new product development. I wouldn’t consider my usage niche, but then again, I am not sure what you may consider to be niche or not.


I did some work for a machine translation business that used Common Lisp as their "secret sauce". As they considered it a serious competitive advantage, you wouldn't hear about it anywhere.

I've seen this with quite a few other companies since, but that means that lots of companies could be using lisp and nobody would ever know about it.


Some years ago I read the same "secret weapon" rhetoric on a website dedicated to ... Cobol; I've not taken it seriously since.


A few days ago I noticed that commercial Smalltalk also still exists:

https://www.cincom.com/us/smalltalk

By niche, I assume you mean niche interest rather than niche purpose. They're both general-purpose languages that are usable on the latest OSes, after all.


Isn't grammarly using lisp?


One of the biggest workloads on Google's Borg is the one running the flight-scheduling service that run on CL.


I like how every Common Lisp website doesn't even have an SSL certificate. Just started learning the language recently and it takes two clicks to get anywhere.


common-lisp.net sbcl.org abcl.org all do?


Time to port certbot to CL?


I don't see the relation between the web server and CL. Are you saying these sites are running off CL and would benefit from a certbot port, or were you just joking?


While I wouldn't be too surprised if websites about Common Lisp did the expected dogfooding, it was indeed a joke about certificates being a solved problem.


Not expensive? When the reference cost of not hobbled or otherwise limited development environments for almost every other commercial language out there is $0.00, that the hobbyist entry point for LispWorks is $500 is … more than slightly out of whack. And that LispWorks price is just for the development environment, not for access to a curated store and delivery service or anything else.

Just as well sbcl (Steel Bank Common Lisp) etc exist.


It was not expensive compared to other commercial Lisp implementations. But the world has moved on and compared to other languages, the prices are unfortunately eye-watering for hobbyists/enthusiasts. Whichs is sad, as Lispworks is a nice environment. I was several times close to getting a personal license, but I just cannot justify it. I can understand that they need to make a living and I am very happy that they are still around. But on the other side, they never managed to get any money from me with their pricing scheme.

I would happily pay the 500 - well at least after a deep breath :p - for a non-commercial license without limits and cross platform, as I would like to use it on the Mac and on Linux, but afterall, I would just use one seat at a time. At these prices, a subscription model might make sense too.

But, as you wrote, there is SBCL+Slime, which is a great environment too. SBCL is even the better compiler.


Borland Pascal was $150 in 1983 and considered affordably priced. (Items like linkers used to be sold separately but were integrated into the Borland Pascal development environment, this was seen as a bargain.) Inflation adjusted that’s $456 today.

I’m not saying I’d spend $500 for this but we are spoiled by all the great free tools today and lose sight of the big picture. Software developers in the US routinely make over $200k/yr. What is $500 for a tool if it really did make you more productive?


> What is $500 for a tool if it really did make you more productive?

What is $500 for a tool to you if you make lots of money? Sure, that is one question.

The more relevant question is: what is $500 for the tool, to the tool?

In 2020, what $500 for a tool is a kiss of death. Nobody learns it; no third-party ecosystem, no jobs, ...

OK, you can have some free-with-limitations student or personal editions or whatever. In the FOSS-dominated landscape, that's still a kiss of death. The entire quality and scope depends on the in-house development behind closed doors, which is funded by the $500 licenses.

I think, without the multiple efforts to have free Lisp over the past 3+ decades, Lisp would be history.


Microsoft Office, Microsoft Visual Studio and also Jetbrains wants a word with you.

Personally I honestly prefer

- LibreOffice (much better for getting styling consistent last I checked + not spreadsheet is not as obsessed with mangling everything into an American date

- VS Code (less overhead, more ergonomic and seriously: who develops things that needs old Visual Studio these days who hasn't done so for years?)

- NetBeans (yes, I use Jetbrains but only because I have to use Kotlin. NetBeans just works and the shortcuts makes sense to me.)

but that doesn't prevent the above mentioned products from earning lots of (hopefully) well deserved money.


> Microsoft Office, Microsoft Visual Studio and also Jetbrains wants a word with you.

These days I use LibreOffice on Windows (though very rarely). Microsoft Office isn't free and doesn't come preinstalled, so screw that.

Microsoft Studio has free versions. I have three versions of it on various hard drives; all were free, and with all I was able to produce a program and ship it royalty-free.


But to stay on point, you were arguing against a $500 tool because "nobody" would learn it and there would be "no third-party ecosystem" - that's emphatically not true for the tools above, regardless of your personal preferences.


None of these tools are programming languages or mainly programming languages, except Visual Studio, which you can easily use free.

The point isn't that nobody pays for any kind of software. I mean, we could whip out enterprise software as an example. "Hey, the company I work for pays 700K per year for SAP support; whatddya mean $500 will kill a programming language tool?"


Pycharm and VS both have free / hobby versions that is, arguably, of high quality.


It's in line with what you'd pay for Visual Studio. VS Pro licences are $45 a month and Enterprise licenses are $250/month. It's fair to ask $500 for hobby and $3000 for pro for a perpetual license for LispWorks


Turbo Pascal, Turbo C, Turbo Prolog, all things I got at an age when it was just a hobby in high school. In fact I can still look over at my bookshelf and see turbo prolog books.. some things you cant bring yourself to throw away!

     I use SBCL, just for hobby and it does everything I want but I agree that the price is not a lot for the tool if it offers something you want for that amount.

     We have got used to not paying for things and its not money we don't have, we have just spent it somewhere else because we have not had to spend it on tools but the price is not over the top - only if you have never had to pay for something.


Same here, despite piracy being quite common in 1990's Portugal, I bought student editions of Turbo Pascal and Turbo C++, as high school student.


Another point is that a lot of Common Lisp code seems to implicitly assume SBCL, so I don't know what, if anything, I can get through Quicklisp will run on Lispworks' little interpreter. That might not be a big problem if I were to ignore external libraries in favor of some preexisting codebase.


It would be interesting to find the places where Quicklisp systems depend on some quirk of SBCL that's not required by the standard.

I know of one case here: one depended on string constants having element type CHARACTER, when that is not required by the standard. It's ok for an implementation to cause a string like "abc" to have element type BASE-CHAR, for example.

Another example might be assuming that various standard functoins that return booleans return T for true. Almost all are not required to do that.


I used Lispworks alongside SBCL and other Common Lisps for about 16 years. Once in a while I had a problem with some quicklisp library in Lispworks, but it was infrequent.




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

Search: