Earlier quoted context omitted.
longjmp simply restores the machine registers (including PC and SP) and thus doesn’t respect any sort of unwind-protect, a concept unknown in C. unwind-protect is a more general form of the c++ raii (in fact c++ got raii from Common Lisp).
>> in fact c++ got raii from Common Lisp I know and understand this is true. Can you point to any sources (projects, papers) that further substantiate this?
Common Lisp's block / return-from and unwind-protect
31–40 of 63 posts
Re: Common Lisp's block / return-from and unwind-protect
#32Earlier quoted context omitted.
longjmp simply restores the machine registers (including PC and SP) and thus doesn’t respect any sort of unwind-protect, a concept unknown in C. unwind-protect is a more general form of the c++ raii (in fact c++ got raii from Common Lisp).
Implementing exception handling (with cleanup on unwind) on top of setjmp was not uncommon. GCC still does on some targets. But I'm sure you know this more than I do. I think that RAII is different from unwind-protect and other scope based cleanup (finally, defer, with) as it is tied to object lifetimes. The fact that automatic objects lifetimes are tied to scope is a nice feature, but RAII goes beyond that.
I wouldn’t say RAII is “tied to object lifetime” except in its name; at least I think of it as every {} pair defining an unwind-protect with object creation/destruction being how it is effected by the programmer. Perhaps that is the same thing as you said, simply viewed from opposite sides.
I do like the automatic nature of RAII, though implementing a whole class for it always feels clumsy to me even after doing it for decades.
Re: Common Lisp's block / return-from and unwind-protect
#33Earlier quoted context omitted.
longjmp simply restores the machine registers (including PC and SP) and thus doesn’t respect any sort of unwind-protect, a concept unknown in C. unwind-protect is a more general form of the c++ raii (in fact c++ got raii from Common Lisp).
>> in fact c++ got raii from Common Lisp I know and understand this is true. Can you point to any sources (projects, papers) that further substantiate this?
The concepts of constructors and destructors have been introduced by C.A.R. Hoare in November 1965, in "Record Handling", a proposal for the extension of Algol.
At that time, Hoare was using the Cobol terms, i.e. "record" for what later was named "object" and "record class" for what later, in Simula 67, was abbreviated to "class". All the "records" discussed by Hoare were allocated dynamically, in the heap.
Constructor (Hoare, 1965-11): "In order to bring records into existence in the first place, the record class identifier should be used as if it were a function designator"
Destructor (Hoare, 1965-11): "a standard procedure "destroy" is proposed, which takes as parameter a reference to a record, and which reverses the effect of having created that record"
The next step towards RAII has been done by Bjarne Stroustrup in "C with Classes" in April 1980, when he made the invocation of the destructors implicit at the exit from a block, by introducing the special member function "delete" for this purpose. Despite the name, the 1980 "delete" member functions corresponded to what later, in C++, were renamed as destructors.
So in 1980, RAII was complete, but it was not yet promoted as a universal strategy for managing resources.
In 1980, Common Lisp did not exist.
Most older Lisps did not have any concept similar with the Algol block, so it would have been impossible for them to invoke implicitly some cleanup functions at block exits. They relied only on the garbage collector, where there is no RAII in the Stroustrup sense, even if GC and RAII are alternative methods for avoiding the explicit invocations of "free", "close" and the like.
Re: Common Lisp's block / return-from and unwind-protect
#34Earlier quoted context omitted.
>> in fact c++ got raii from Common Lisp I know and understand this is true. Can you point to any sources (projects, papers) that further substantiate this?
The concept of RAII has emerged gradually and it would be hard to pinpoint a moment for its appearance. I am not aware of any specific feature of RAII that has appeared in Common Lisp before other languages. The concepts of constructors and destructors have been introduced by C.A.R. Hoare in November 1965, in "Record Handling", a proposal for the extension of Algol. At that time, Hoare was using the Cobol terms, i.e.…
In the Lisp Machine OS there is a concept called RESOURCE for manual memory management. For example the CHAOS network stack has to deal with network packets. There is a macro USING-RESOURCE, which allocates/gets an object and on exit frees it. The macro expands into a form using also UNWIND-PROTECT to ensure freeing a resource on non-local exit. I would think that this is from around 1980, for the MIT CADR machine.
Re: Common Lisp's block / return-from and unwind-protect
#35Gah, another Lisp post to tempt me to add yet another mini project to my plate...I always am curious about trying more Lisp because I keep seeing commentary about how powerful it is to actually build applications once you get moving on building things. Anyone here have any recent practical experience in this direction who would confirm this in Lisp vs in other programming languages? Does effort in Lisp really compoun…
We have a choice of libraries, but no big batteries-included web framework, so you must be ready to assemble pieces (or simply, to know web development). Ex: a login system? There are examples to look at, not a use-and-forget library.
A CL webserver coupled with a client library like HTMX is great. I don't recommend Reblocks (weblocks) or CLOG yet for serious stuff.
resources: the Cookbook, my lisp-journey #web content, my last youtube video (@vindarel channel).
Re: Common Lisp's block / return-from and unwind-protect
#36Gah, another Lisp post to tempt me to add yet another mini project to my plate...I always am curious about trying more Lisp because I keep seeing commentary about how powerful it is to actually build applications once you get moving on building things. Anyone here have any recent practical experience in this direction who would confirm this in Lisp vs in other programming languages? Does effort in Lisp really compoun…
I'm learning programming at age fifty-four and have chosen Common Lisp as my one language for life. If you want something easy to learn with a ton of support pick Python, Elixir, and/or JS. CL sucks for mini-projects since the learning curve requires serious commitment and is SO different from what people are used to. CL requires a long-term commitment and demands the programmer challenge pop programming trends and d…
So far the language I've experienced the most power with is Python, and your description of Lisp's power and tooling are very intriguing. I will take note of your recommendations and play around with the tools you described. It is worth the investment if it means unlocking something even more powerful than Pythonic thinking and code.
Do you find that one needs to be well-versed in Emacs to fully appreciate the CL stack you described and the capabilities of the language itself? Would you learn Emacs separately/after spending time building things with CL, or is building things with CL in Emacs part of the entire experience?
Re: Common Lisp's block / return-from and unwind-protect
#37Earlier quoted context omitted.
The concept of RAII has emerged gradually and it would be hard to pinpoint a moment for its appearance. I am not aware of any specific feature of RAII that has appeared in Common Lisp before other languages. The concepts of constructors and destructors have been introduced by C.A.R. Hoare in November 1965, in "Record Handling", a proposal for the extension of Algol. At that time, Hoare was using the Cobol terms, i.e.…
MDL had UNWIND in 1977 and Maclisp added UNWIND-PROTECT in 1978. I'll guess that Lisp Machine Lisp then got it, too. Common Lisp emerged 1981 onwards, largely based on the latter. In the Lisp Machine OS there is a concept called RESOURCE for manual memory management. For example the CHAOS network stack has to deal with network packets. There is a macro USING-RESOURCE, which allocates/gets an object and on exit frees…
http://www.ifarchive.org/if-archive/infocom/info/MDL_Primer_...
Nevertheless, the MDL UNWIND and the later UNWIND-PROTECT are more limited in applications and they require much more work from the programmer than the mechanism introduced by Stroustrup in 1980.
With implicitly-invoked destructors, the destructor body is written once for each type of data, and normally there is no need to ever invoke it explicitly.
After writing correctly the constructors and destructors, the programmer's work becomes identical with using a garbage collector, because the objects are allocated explicitly, but they are never deallocated explicitly.
On the other hand, UNWIND is intended for handling exceptions. It can also be used as a normal cleanup strategy, but it still must be written every time for handling the exit from a block or from a hierarchy of nested blocks. In the latter variant, there is some economy in code writing, but the lazy deallocation is less efficient.
The UNWIND of MDL has little resemblance to RAII, but it resembles the UNWIND of Mesa (programming language used at Xerox, starting with 1976, which has introduced many innovations that have been included only much later in most programming languages).
It would be difficult to determine whether UNWIND has appeared first in MDL or in Mesa, or if both have taken it from another language, because experiments with exception handling were fashionable during those years and there were many places where various variants were tried.
Re: Common Lisp's block / return-from and unwind-protect
#38Earlier quoted context omitted.
> Are you indicating that Lisp has already introduced many of the concepts and features that are now found in modern programming languages, implying that contemporary languages have largely assimilated Lisp's ideas and paradigms? Yes. See effect handlers for an example, which are making rounds around the programming world as of late. They are equivalent to the Lisp condition system, except formalized to work in stron…
> They are equivalent to the Lisp condition system Not exactly correct due to the lack of higher order effects ( https://news.ycombinator.com/item?id=20513370 ), but the condition system is "good enough" for a lot of use cases
Re: Common Lisp's block / return-from and unwind-protect
#39Gah, another Lisp post to tempt me to add yet another mini project to my plate...I always am curious about trying more Lisp because I keep seeing commentary about how powerful it is to actually build applications once you get moving on building things. Anyone here have any recent practical experience in this direction who would confirm this in Lisp vs in other programming languages? Does effort in Lisp really compoun…
I use a couple web apps in production©. The development experience is awesome, deployment is easy, the runtime is fast, the language and the ecosystem are stable. CL being CL, you get many errors, including type errors, at compile time (hitting C-c C-c, the feedback is instantaneous). You have less needs for stupid unit tests. My Sentry dashboard is empty :) Coming from Python I appreciate all that. We have a choice…
Re: Common Lisp's block / return-from and unwind-protect
#40Earlier quoted context omitted.
MDL had UNWIND in 1977 and Maclisp added UNWIND-PROTECT in 1978. I'll guess that Lisp Machine Lisp then got it, too. Common Lisp emerged 1981 onwards, largely based on the latter. In the Lisp Machine OS there is a concept called RESOURCE for manual memory management. For example the CHAOS network stack has to deal with network packets. There is a macro USING-RESOURCE, which allocates/gets an object and on exit frees…
Thanks for pointing to MDL: http://www.ifarchive.org/if-archive/infocom/info/MDL_Primer_... Nevertheless, the MDL UNWIND and the later UNWIND-PROTECT are more limited in applications and they require much more work from the programmer than the mechanism introduced by Stroustrup in 1980. With implicitly-invoked destructors, the destructor body is written once for each type of data, and normally there is no need to eve…
Resource management in the MIT Lisp OS ca. 1980, approximate example.
One would define a resource of arrays, where arrays can be allocated and deallocated. They will be managed via a pool.
(defresource 2d-array (rows columns)
:constructor (make-array (list rows columns)))
Now user code would use the USING-RESOURCE macro, where it spans a dynamic scope. Entering the scope allocates the resource. Inside the scope the resource is allocated. Leaving the scope will automatically deallocate the resource and put it back into the pool. A deinitializer may free memory as needed. (using-resource (my-array 2d-array 100 100) ; get me a 100x100 array from a pool
(setf (aref my-array 42 42) 'the-answer) ; setting the array
(print (aref my-array 42 42))) ; reading the array
To make sure that the resource gets deallocated, the above macro form will expand to something using UNWIND-PROTECT: ...
(unwind-protect
(progn ; protected form
(setf my-array (allocate-resource '2d-array 100 100)) ; allocate the array
(setf (aref my-array 42 42) 'the-answer) ; setting the array
(print (aref my-array 42 42))) ; reading the array
(when my-array ; exit form
(deallocate-resource '2d-array my-array))) ; deallocate the array
...
This is an example of manual memory management using a pool of resources, where the DEALLOCATE is done always via UNWIND-PROTECT.Thus the user will not explicitly use UNWIND-PROTECT, but some macros which use it in their expansion...