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."
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.
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.
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:
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).
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.
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.
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.
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
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.
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.
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.
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?"
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.
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.
Please note that the LispWorks Personal Edition, distributed free of charge, has the following intentional limitations:
And it is not popular because ...