Common Lisp – Myths and Legends (2002)
lispworks.com
lispworks.com
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 ...I was referring to the above pestering of the user base, not that there aren't alternatives.
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.
This list is also not exhaustive.
The article you linked literally starts with:
> Format is a function in Common Lisp…
But I agree with your original point. "format" is not the most descriptive name for something that "formats and maybe prints."
Uh, what? It's not that different from the printf metalanguage (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...
Also, `(format t "str")` does not return a string. At least not on SBCL or CCL.
http://www.lispworks.com/documentation/lw50/CLHS/Body/f_form....
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.
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.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.
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).
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 ...
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!
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! :)
FORMAT runs a domain specific language, which causes various print operations to an output stream.
for printf debugging it's one more parameter you don't wanna type :)
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.
Not true, and his name is spelled Mallery. No idea if he reads HN.
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.
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.
Just as well sbcl (Steel Bank Common Lisp) etc exist.
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 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.
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.
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.
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?"
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.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 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.