[HN Gopher] Common Lisp's block / return-from and unwind-protect
       ___________________________________________________________________
        
       Common Lisp's block / return-from and unwind-protect
        
       Author : bshanks
       Score  : 105 points
       Date   : 2024-01-21 01:37 UTC (21 hours ago)
        
 (HTM) web link (axisofeval.blogspot.com)
 (TXT) w3m dump (axisofeval.blogspot.com)
        
       | wait_a_minute wrote:
       | Gah, 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 compound/produce great code
       | and great applications that much faster than other languages?
       | (For web development primarily)
        
         | rokkitmensch wrote:
         | Yes, building anything non-trivial in CL will show the
         | discerning programmer that there is nothing new under the sun.
        
           | waynesonfire wrote:
           | Could you clarify what you mean by 'there is nothing new
           | under the sun' when referring to programming with Common
           | Lisp? 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?
           | 
           | Your comment left me with a strange sentiment. I'm somewhat
           | disheartening because it implies that learning Lisp might be
           | redundant given that contemporary languages have already
           | incorporated its best aspects.
        
             | phoe-krk wrote:
             | _> 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 strongly statically typed programming
             | environments.
             | 
             |  _> I 'm somewhat disheartening because it implies that
             | learning Lisp might be redundant given that contemporary
             | languages have already incorporated its best aspects._
             | 
             | Sort of, lots of things have thankfully trickled from Lisps
             | to other languages (including whole languages like Julia).
             | The pleasant feeling of conversing with the language and
             | programming bit by bit in it is hard to replicate with
             | things like LSPs, though, since the implementation is
             | always running in the background and programming in it is
             | based on mutating it until it contains the program you
             | seek.
        
               | valcron1000 wrote:
               | > 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
        
               | phoe-krk wrote:
               | TIL. The way I understand it, that's because CL is not
               | required to perform CPS on its code and no CL
               | implementation exists that does it on its own.
        
             | corinroyal wrote:
             | > I'm somewhat disheartening because it implies that
             | learning Lisp might be redundant given that contemporary
             | languages have already incorporated its best aspects.
             | 
             | Indeed, Lisp is no longer as revelatory as it once was,
             | since many innovations have been adopted, even surpassed in
             | specific cases. Still, no other language gives you the
             | total package. The environment is far more than the sum of
             | its features list. CL just gets out of your way and allows
             | you to think about problems not programming.
        
           | pjmlp wrote:
           | Except the little detail that JIT/AOT toolchains still aren't
           | as widespread as they should be, with several languages
           | offering only one variant, and there as still quite a few
           | Lisp tricks either left behind in modern IDEs, or with
           | various kinds of support depending on the language, like
           | accessing everything across language and runtime, hot code
           | reloading, time travel debugging.
           | 
           | Ah, and most relevant, many folks still believe that writing
           | OSes in what was once a macro Assember for PDP-11 is the only
           | way.
        
         | tiberius_p wrote:
         | Lisp is great for creating your own domain specific languages.
         | S-expressions are basically abstract syntax trees written as
         | code. Thus you can take any code written in any language and
         | "lispify" it into an S-expression. Then you can apply various
         | transformations/analyses on this expression to achieve various
         | goals:linting, semantic modeling, compiling to machine
         | code/bytecode, transpiling to another laguage, interpreting,
         | optimizing, etc. Common Lisp also has the possibility of on-
         | the-fly recompilation of classes and methods/functions which
         | can be useful for debug and incremental development.I don't
         | have much experience in the web development area but I would
         | incline to think that you won't get much added value from using
         | CL compared to other languages/frameworks. It can be useful if
         | you want to develop your own framework with custom language
         | constructs and features. But if you want to fast prototype a
         | webapp idea you're better off trying the more popular
         | solutions.
        
         | corinroyal wrote:
         | 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
         | deeply entrenched styles. You have to think beyond today to
         | what could be and what once was. But if you're willing to do
         | that, there is no better language. Not Haskell, not OCamel, not
         | Rust/Go/Julia/Clojure/Scheme, or the current lang du jour.
         | Whatever limitations Common Lisp had in the past are long gone.
         | 
         | SBCL is blazingly fast, CL abstractions are profound yet
         | practical. The type system gives you power without pettiness.
         | Language-oriented programming is a superpower in a world of cut
         | and paste library-oriented programming. Image-based computing
         | often allows one to skip the impedance mismatch with DBs. In
         | many cases and you can just persist the data structures as they
         | are or serialize them where needed. The tooling with Roswell,
         | Quicklisp, Qlot, Doom Emacs, and Sly make prototyping and
         | exploratory programming wiz by. CLOG, Reblocks and Hunchentoot
         | provide powerful abstractions for web programming, but Phoenix
         | with Liveview is probably better for most. The debugging
         | experience is so insanely powerful it freaks me out and makes
         | other systems look rudimentary. CLOS, the object system, is
         | best of breed and makes most of the standard criticisms of OO
         | programming moot. The homoiconic list-based syntax and prefix
         | notation are beautiful and never get in your way. Parentheses
         | are invisible. The condition system makes flow control and
         | error handling in other systems seem rigid and convoluted.
         | Aspect-oriented programming is just what we do, not a thing
         | tacked on. Macros and the meta-object protocol allow you to
         | build a language on top of Lisp that allows users to
         | conceptualize problems using nouns and verbs they already know.
         | 
         | Drop into Coalton or Shen for strong, static typing where
         | necessary, or April (hosted APL) for array wizardry that makes
         | NumPy look like data-flow programming in Basic on a Timex
         | Sinclair with a cassette drive. You can slice and dice whole
         | datasets in a few characters of code. Bundle existing C libs
         | with CFFI when you find a good one you need. Lisp-based systems
         | are alive and grow and change as requirements do. It's harder
         | to program yourself into a corner. Refactoring is continuous
         | and mundane. In-source documentation is the right place for it,
         | but Lispers tend to be shamefully lax in providing it. Shaaame!
         | Newer Lispers tend to be better about docs--the culture is
         | changing. Often you ask a question and get no response. Other
         | times you get a detailed response from a legendary mind and
         | just sit there in awe working your way through their thinking
         | and feeling your inadequacy. The code is about as succinct as
         | it can be to maintain readability. There are two camps on
         | readability, some experienced Lispers find it harder, and most
         | find it much easier to parse than ALGOL-derived syntax.
         | 
         | Once mastered, quick things are quick, hard things are
         | straightforward, and impossible things are doable. This is a
         | system for people who need, not want, to change the world. It
         | gives single programmers and small teams the power to take on
         | armies of bureaucratic programmers. But you have to be willing
         | to break the mold, handle charges of elitism, not be required
         | to justify your choice to managers, tolerate a small hiring
         | pool, train newbies hard and long, not get freaked out using
         | some libs that are stable and haven't been updated in years,
         | deal with the pace of development of a small community, have
         | the patience and joy in problem-solving to handle frequent
         | bafflement, read a ton of source code rather than search the
         | forums, and be willing to roll your own when needed. If you can
         | handle all the idiosyncrasies and have a burning need for
         | elegance and power, then CL will reward and surprise into until
         | dementia takes you.
         | 
         | In short, all the good things you've heard are true, many of
         | the standard critiques are uninformed, and problems people talk
         | about that apply to most languages often don't apply.
        
           | pjmlp wrote:
           | Additionally jump into LispWorks or Allegro Common Lisp, to
           | enjoy how the survivors from Common Lisp days with a full
           | blown IDE feels like.
        
           | tome wrote:
           | You have an extremely deep understanding of the discipline of
           | computer programming for someone who has only just started to
           | learn!
        
             | corinroyal wrote:
             | How kind of you to say. I held off on learning programming
             | for so long due to my visceral disgust with C/UNIX and
             | ALGOL syntax. I just knew it was the wrong set of
             | abstractions that have trapped us all in a grey hellscape
             | of mediocrity and wasted potential. When I was a kid I
             | turned turtles into a spirograph in Logo on an Apple II. It
             | ruined me. I didn't know Logo was functional or Lisp-
             | inspired.
             | 
             | When I found functional programming in Erlang I got SO
             | excited. When I found Common Lisp, decades of pent-up
             | frustration melted away and I knew I'd come home. I guess
             | my Unix Hating led to some intuitive thinking over the
             | years and I've been making up for lost time over the past
             | couple of years and mapping what I knew I wanted to what
             | has been there in CL all along.
        
           | massysett wrote:
           | "not get freaked out using some libs that are stable and
           | haven't been updated in years"
           | 
           | In this vein, it's great that decades-old Common Lisp books
           | are still current. The paucity of Web content is not as bad
           | as it seems: you can get a real book.
        
           | mark_l_watson wrote:
           | +1 nice summary! I have been using Common Lisp since the
           | early 1980s and I also love the language. For my own Lisp
           | hacking pleasure, I add a few Schemes to the mix, but that is
           | often a (fun) distraction for me, and I would be better off
           | sticking with CL (or Python for deep learning projects).
           | 
           | Do you have a blog where you share your learning experiences?
        
             | corinroyal wrote:
             | OMG! This is what I'm talking about with Common Lisp. One
             | minute you're a washed-up slacker, the next Mark L. Watson
             | speaks to you. I'm winding my way through "Loving Common
             | Lisp, or the Savvy Programmer's Secret Weapon" as we speak
             | and loving it. Thank you!
             | 
             | I don't have a blog and haven't gotten far enough in my
             | learning to make anything useful, but I do plan to produce
             | a newbie's guide to help people get started quickly. My
             | perspective as an older person for whom CL is my first
             | language could be valuable since my sticking points are
             | different and I don't yet have bad habits to break.
        
           | wait_a_minute wrote:
           | Hello my friend, I am very pleased to make your acquaintance
           | and I am very excited about your journey. I am also very
           | impressed that for someone who is newly learning the field,
           | you already are so well-spoken and knowledgeable about the
           | language and the tools. Thank you so much for your response.
           | I also appreciate that you are only a little older than my
           | parents, and if you are learning so well and so quickly then
           | that fills me with much inspiration and excitement for the
           | prospects of continued enjoyment of programming and software
           | development for more decades to come. It's really exciting to
           | know that anyone can learn at any age, and I wish you much
           | enjoyment and success on your journey. If you were to create
           | a developer blog, I'd read it!
           | 
           | 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?
        
         | f1shy wrote:
         | Not so recent, about 6 years ago, I had to communicate with
         | many instruments (PS, Oscilloscope, SMU, etc) to test a new
         | ASIC we developed. There where hundreds of tests to be done. We
         | wanted to automate the measurement and evaluation of results,
         | because they were so many. Also there where 5 fabs and 2
         | suppliers with different design, but "pin compatible". I did
         | the whole framework in emacs lisp, I had to implement ONC RPC
         | and LXI on top to speak to the instruments... The whole thing
         | took me 2 weeks. At the time I had no idea of Elisp; only a
         | little vit of scheme. I was proficient in C, and I would say it
         | had taken me at least 6 Months to do the same
        
         | worthless-trash wrote:
         | I've written a few small CL web applications( with about 100
         | users active a day), along with a few terminal applications
         | (with only ~10 users). Other languages I know is C , Erlang,
         | Elixir and a bit of python. This will end up sounding a bit
         | evangelical but so be it.
         | 
         | I feel that the lisp code was easier to write and reason about,
         | the being able to hot reload code from the repl significantly
         | decreased the time to completion. I also 'connect' to a
         | networked repl when sentry reports an unhandled error to figure
         | out what has gone wrong.
         | 
         | You might be tempted to believe that CL repl is "similar
         | enough" to python's repl, however this is NOT the case. Being
         | able to redefine functions, variables and macros while working
         | on the code (without a restart) allows you to deal with errors.
         | 
         | The syntax is a 'no brainer', Extreme consistency in function
         | calls means that you don't need to think about it. Other
         | languages which SOMETIMES use infix, sometimes require
         | brackets, that is just crazy.
         | 
         | Lisp libraries have less churn than 'modern languages', some
         | libraries have not been touched for some time, unlike
         | python/ruby/js. The code does not seem to rot and old lisp code
         | runs on modern implementations.
         | 
         | I work in emacs, lem, I know people who use vscode and alive,
         | and vim. There is no 'hard' requirement to use emacs, you will
         | get by as long as you have 'emacs like' repl integration.
         | 
         | All in all, I do not regret working in lisp. It doesn't have
         | the cult of the other languages and I'm fine with that.
        
           | msk-lywenn wrote:
           | I'd rather say there is a definite cult over lisp. But it's
           | very different from the other languages which I'd qualify as
           | rather hardcore. Lisp's cult is a magical cult. No other
           | language as such amazing stories as the space probe remotely
           | debugged from earth with a repl, the extreme hot reload and
           | mystical intertwining of assembly on PS2 of Jak & Daxter's
           | GOAL, the MIT course with a Fantasia level of teaching, The
           | symbolic machines, etc.
           | 
           | The only other language like that I can think of is
           | smalltalk.
        
         | vindarel wrote:
         | I use a couple web apps in production(c). 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 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).
        
           | wait_a_minute wrote:
           | Thank you very much for referencing your latest video, I'm
           | watching it and glad to have such a timely example of what
           | the development process can actually look like for CL web
           | applications. Really cool stuff, will subscribe. :)
        
       | pfdietz wrote:
       | Block/return-from is a lexical transfer of control that can be
       | non-local (you can transfer out of a lambda or defun to an
       | enclosing scope). For the dynamic equivalent there's catch/throw.
       | Both transfers activate unwind-protect if they unwind the stack
       | through it.
        
         | brabel wrote:
         | One of the only languages where I saw this non-local returns is
         | Kotlin.
         | 
         | You can return from a function from within a lambda (and I
         | believe this works on any number of levels), for example:
         | fun go(list: List<String>): Boolean {             list.forEach
         | { if (it.isEmpty()) return@go true }             return false
         | }
        
           | gpderetta wrote:
           | Longjmp in standard C, swapcontext in POSIX C. I think GCC
           | allows gotos to the containing function from a local function
           | (but I never used GCC local functions).
           | 
           | Smalltalk, and I believe ruby, allow non local return from
           | blocks.
        
             | gumby wrote:
             | 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).
        
               | Findecanor wrote:
               | `longjmp` does not restore the machine registers on all
               | platforms. The C standard guarantees only the contents of
               | variables marked `volatile`: anything above that is
               | implementation-dependent.
               | 
               | I think that MSVC++ longjmp actually does proper
               | unwinding, calling destructors in C++ functions on the
               | stack, but don't quote me on that. I think it is also
               | dependent on the compiler flags.
        
               | gpderetta wrote:
               | 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.
        
               | gumby wrote:
               | Well lisps don't really have destructors in the sense C++
               | does; objects go out of scope and become unreachable. So
               | unwind-protect makes cleanup (closing a file, for
               | example) explicit, which it has to be.
               | 
               | 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.
        
               | gpderetta wrote:
               | What I mean is that if I add an instance of a class with
               | a non trivial destructor from a container and later
               | remove it, the destructor is automatically invoked. This
               | is different from an unwind protect.
        
               | lispm wrote:
               | Lisp uses UNWIND-PROTECT to implement that.
               | 
               | For example WITH-OPEN-FILE closes the file automatically
               | when leaving its scope.                    (with-open-
               | file (stream "hello.world")            (read stream))
               | 
               | WITH-OPEN-FILE is a macro and expands into OPEN and CLOSE
               | operations, protected by an UNWIND-PROTECT.
               | 
               | Thus anything where a destructor would automatically
               | clean things up is done in Lisp behind the scenes
               | automatically using an UNWIND-PROTECT form.
        
               | gpderetta wrote:
               | That's again an example of cleanup associated with scope.
               | I understand what you can do it with unwind-protect and
               | friends.
               | 
               | But the essence of RAII is more than that.
               | 
               | In c++ if I add an opened file object to some collection
               | and later remove it or destroy the collection, it is
               | implicitly cleaned up.
               | 
               | For example let's say you are implementing an n-way out
               | of core merge: in c++ you would create a priority queue
               | of files objects ordered by the front current from item.
               | You pop the front file object read the item and, if the
               | file is not empty, push it back into the queue. Cleanup
               | is implicit by removing the file from the queue and not
               | explicitly adding it back. On early exit (because of an
               | error or exception) the queue is automatically destroyed
               | and recursively all the file objects.
               | 
               | There might be a way to implement this recursively with
               | unwind-protect, but I think it is less natural.
               | 
               | For example python has ExitStack, which in practice is an
               | ad-hoc container that supports recursive cleanup of
               | contained objects, but is still not as convenient as
               | having all containers do proper cleanup.
        
               | kazinator wrote:
               | The object is not exactly removed from the container. It
               | is removed from existence. The object in that situation
               | resides in the container physically. It is constructed
               | there and destroyed. It does not exist outside of the
               | container afterwards, or at any other time.
               | 
               | This is a low-level memory management strategy being
               | conflated with object-orientation, that is alien to
               | higher level languages.
        
               | gpderetta wrote:
               | Well yes, it works well in c++ because the language has a
               | strong distinction between value semantics and reference
               | semantics, so when you remove a value from a container it
               | must clearly be destroyed. A GC'd language with aliased
               | references can't call destructors in this case. At best
               | can do it when the object is collected.
               | 
               | Yet I think an high level language could have the same
               | value/reference distinction. Or you could do it with
               | linear types.
        
               | oumua_don17 wrote:
               | >> 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?
        
               | gumby wrote:
               | No, but Tiemann might remember as I remember introducing
               | him to unwind-protect (not that he invented RAII afaik,
               | nor would claim to have)
        
               | adrian_b wrote:
               | 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.
               | "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.
        
               | lispm wrote:
               | 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 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.
        
               | adrian_b wrote:
               | 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 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.
        
               | lispm wrote:
               | UNWIND-PROTECT is a building block.
               | 
               | 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...
        
               | adrian_b wrote:
               | Thanks for the explanation.
               | 
               | I agree that this is pretty much equivalent to RAII.
               | 
               | Nevertheless, it is also obvious that this was not a
               | source of inspiration for Bjarne Stroustrup.
               | 
               | He has started directly from the constructors and
               | destructors of C.A.R. Hoare (1965-11) and Simula 67
               | (1968-05, Kristen Nygaard & Ole-Johan Dahl).
               | 
               | The only change is that in 1980 he has enhanced his
               | compiler for "C with Classes" to generate automatically
               | all the invocations to the appropriate destructors in all
               | the block and function epilogues, relieving the
               | programmer from this task.
        
             | EdwardCoffin wrote:
             | Smalltalk only allows the return from the block's lexically
             | enclosing method, not an arbitrarily specifiable context
             | like Common Lisp does. It's discussed a bit on c2.com [1]
             | 
             | [1] https://wiki.c2.com/?SmalltalkBlockReturn
        
               | xkriva11 wrote:
               | In Pharo or Squeak, you can just send the "return:"
               | message to any context (except contexts that have nowhere
               | to return).
        
       | formerly_proven wrote:
       | Is Common Lisp the first kitchen sink language (ala C++)? It
       | always seems to me like there's a lot of "Oh yeah, Common Lisp
       | has a feature for this, too"-type blog posts, though very little
       | about actual usage of it.
        
         | pjmlp wrote:
         | Common Lisp is the uniformization of what Lisp Machines across
         | Genera, TI, and Xerox PARC (although Interlisp-D was a
         | different species) were offering for a full graphics
         | workstation, alongside other systems.
         | 
         | It was as kitchen sink as having POSIX (basically a full blown
         | UNIX specification), to be expected to fill in the stuff
         | missing from ISO C standard library.
        
         | int_19h wrote:
         | It's a rather subjective assessment. ALGOL 68 and PL/I were
         | apparently considered rather "kitchen sink" by the standards of
         | their time.
        
       ___________________________________________________________________
       (page generated 2024-01-21 23:02 UTC)