Home
[HN Gopher] Hofstadter on Lisp (1983) ___________________________________________________________________ Hofstadter on Lisp (1983) Author : Eric_WVGG Score : 321 points Date : 2024-10-16 13:44 UTC (16 hours ago) HTML web link (gist.github.com) TEXT w3m dump (gist.github.com) | anthk wrote: | >Emacs defalias | | On Common Lisp too, by defining defalias as a macro: | | https://stackoverflow.com/questions/24252539/defining-aliase... | dahart wrote: | > Why is most AI work done in Lisp? | | That's changed, of course, but it remained true for at least | another 15 or 20 years after this article was written and then | changed rather quickly, perhaps cemented with deep neural | networks and GPUs. | | Other than running the emacs ecosystem, what else is Lisp being | used for commonly these days? | volltrottel wrote: | Running hacker news | tombert wrote: | Can't speak for the entire industry obviously, but at a few | jobs I've had [1] Clojure is used pretty liberally for network- | heavy stuff, largely because it's JVM and core.async is pretty | handy for handling concurrency. | | I know a lot of people classify "Clojure" and "Lisp" in | different categories, but I'm not 100% sure why. | | [1] Usual disclaimer: It's not hard to find my job history, I | don't hide it, but I politely ask that you don't post it here. | packetlost wrote: | > I know a lot of people classify "Clojure" and "Lisp" in | different categories, but I'm not 100% sure why | | It mostly boils down to Clojure not having CONS cells. I feel | like this distinction is arbitrary because the interesting | aspect of Lisps is _not_ the fact that linked-lists are the | core data-structure (linked-lists _mostly_ suck on modern | hardware), but rather that the code itself is a tree of lists | that enables the code to be homoiconic. | pfdietz wrote: | I mean, you can have a tree of vectors also, so I don't see | why lists are needed for homoiconicity. | iLemming wrote: | No, not needed. This argumentation can go both ways; some | may even say, "Well, Python is 'Lispy,'" which to me is | obviously not. It boils down to what can you do in the | REPL, right? | https://news.ycombinator.com/item?id=41844611 | vnorilo wrote: | In my mind Clojure is Lispy, Python is not, nor is | Javascript. | | In addition to REPL and macros, I think two other Lispy | features are essential: | | nil is not just the sad path poison value that makes | everything explode: lisp is written so that optionals | compose well. | | Speaking of composing, Lisps tend to be amazing with | regard to composability. This is another line that cuts | between CL, Scheme and Clojure on one side, with Python | and Javascript firmly on the other side in my experience. | | Lisps are as dynamic a languages ever go, | unapologetically. | iLemming wrote: | I just wanted to add that "dynamic" doesn't mean untyped | or weakly typed. Clojure is a strongly-typed dynamicly- | typed PL. Clojurescript compiler for example, in many | cases can produce safer JS code than even Typescript ever | could. | packetlost wrote: | That's mostly my point. A linked-list structure is _not_ | the interesting part. I use the "generic" reading of | list above and don't mean to imply some particular | implementation | iLemming wrote: | Some purist won't consider Clojure a "true" Lisp, but it's a | Lisp dialect. | | > what else is Lisp being used for commonly these days? | | Anything that runs on Clojure - Cisco has their cybersec | platform and tooling running on it; Walmart their receipt | system; Apple - their payments (or something, not sure); | Nubank's entire business runs on it; CircleCI; Embraer - I know | uses Clojure for pipelines, not sure about CL, in general | Common Lisp I think still quite used for aircraft design and | CAD modeling; Grammarly - use both Common Lisp and Clojure; | Many startups use Clojure and Clojurescript. | | Fennel - Clojure-like language that compiles to Lua can handle | anything Lua-based - people build games, use it to configure | their Hammerspoon, AwesomeWM, MPV, Wez terminal and things- | alike, even Neovim - it's almost weird how we're circling back | - decades of arguing Emacs vs. Vim, and now getting Vim to | embrace Lisp. | tombert wrote: | When I was there, Apple used Clojure for a lot of stuff | involving the indexing of iTunes/Apple Music. I used it for | some telemetry stuff on top of the indexer as well. Not sure | what other teams used it for. | SSLy wrote: | Google Flights was built on CL, no? | casta wrote: | The pricing engine for Google Flights (and behind many big | airline websites) is written in Lisp. | mepian wrote: | >what else is Lisp being used for commonly these days? | | It is being used for formal verification in the semiconductor | industry by companies like AMD, Arm, Intel, and IBM: | https://www.cs.utexas.edu/~moore/acl2/ | nextos wrote: | > Why is most AI work done in Lisp? | | Yann LeCun developed Lush, which is a Lisp for neural networks, | during the early days of deep architectures. See | https://yann.lecun.com/ex/downloads/index.html and | https://lush.sourceforge.net. Things moved to Python after a | brief period when Lua was also a serious contender. LeCun is | not pleased with Python. I can't find his comments now, but he | thinks Python is not an ideal solution. Hard to argue with | that, as its mostly a thin wrapper over C/C++/FORTRAN that | poses an obvious two-language problem. | sourcepluck wrote: | Hadn't seen that before, very interesting! | buescher wrote: | A friend used lush as his "secret weapon" for a while. I | didn't quite warm to it and now regret not paying attention. | It's amazing how much is packed in "batteries included." | | Apparently it didn't make the transition to 64-bit machines | well? But I haven't really looked. | shawn_w wrote: | It's just as easy to have thin wrappers over C/etc. number | crunching libraries in Common Lisp as it is Python. And pure | CL code is typically faster than pure Python (though pypy | might be a different story). There's no technical reason it | still couldn't be dominant in AI. | | It's a shame things took the course they did with preferred | languages. | mportela wrote: | My take is that Python won by having a complete ecosystem | centralizing many tools that were dispersed in different | languages: - Numpy/Scipy/Matplotlib enabled scientists to | do data analysis with Panda similar to what was available | in R - PySpark enabled big data scripts in Python instead | of Scala - PyTorch made Torch available for non-Lua users | | Bit by bit, more people got used to doing data analysis and | AI research in Python. Some projects were even written for | Python first (e.g. Tensorflow or Keras). Eventually, Python | had so many high-quality packages that it became the de | facto for modern AI. | | Is it the _best_ language for AI, though? I doubt. However, | it is good enough for most use cases. | sourcepluck wrote: | I think personally that Coalton and the stuff its built on is | crazy cool. Coalton is a little library you add to your Lisp, | but, to quote the third link here: "In terms of its type | system, Coalton's closest cousin is Haskell." So Lisp's | dynamism with all sorts of advanced typing. | | QVM, a Quantum Virtual Machine https://github.com/quil-lang/qvm | | Quilc, an "advanced optimizing compiler" for Quil | https://github.com/quil-lang/quilc | | Coalton, "a statically typed functional programming language | built with Common Lisp." https://coalton- | lang.github.io/20211010-introducing-coalton/ | ryukafalz wrote: | Guix is a Nix-like package manager and distro that is almost | entirely written in Guile Scheme: https://guix.gnu.org/ | | I would guess it's by far the most active Guile project. | jjtheblunt wrote: | Grammarly was famously using it. | | https://www.grammarly.com/blog/engineering/running-lisp-in-p... | vindarel wrote: | Quantum computing and symbolic AI? But also web services, CAD | and 3D software, trading, designing programmable chips, big | data analytics... | | present companies (that we know about): | https://github.com/azzamsa/awesome-lisp-companies/ | tmtvl wrote: | > _what [...] is Lisp being used for [...] these days?_ | | I dunno, there's Nyxt, Google Flights, MediKanren, there's some | German HPC guys doing stuff with SBCL, Kandria,... I believe | there's also a HFT guy using Lisp who's here on HN. LispWorks | and Franz are also still trucking, so they prolly have | clientele. | | There are fewer great big FLOSS Lisp projects than C or Rust, | but that doesn't really tell the whole story. Unfortunately | proprietary and internal projects are less visible. | chromaton wrote: | AutoCAD automation? | fuzztester wrote: | Yes. AutoLisp was available from the early days of AutoCAD. I | didn't use it much myself. I just helped some mechanical | engineers with it in a company where I worked, in small ways, | just tinkering, really. At that time I was quite junior, so I | didn't really grasp the power of it, so I didn't play around | with it much. | AnimalMuppet wrote: | > Every computer language has arbitrary features, and most | languages are in fact overloaded with them. A few, however, such | as Lisp and Algol, are built around a kernel that seems as | natural as a branch of mathematics. | | _Algol?_ The kernel of Algol seems as natural as a branch of | mathematics? Can anyone who has _used_ Algol give their opinion | of this statement? | andyjohnson0 wrote: | I did some Algol programming back in the late 80s - when it had | mostly been obsoleted by Pascal, Modula, and even C for what we | called "structured programming" back then. | | I remember it as a likeable, economical, expressive language, | without significant warts, and which had clearly been | influential by being ahead of its time. | | So my guess is that Hofstadter was just referring to its | practical elegance - rather than the more theoretical elegance | of Lisp. | nxobject wrote: | Out of curiosity: which dialect on Algol, and on what | platform? | gavindean90 wrote: | From what I've studied, Algol wasn't designed for typical | software development--its main purpose was to give computer | scientists a way to describe algorithms with a level of rigor | that mirrors mathematical notation. | retrac wrote: | C is basically Algol with curly braces and pointers. The | sentiment expressed there is probably equally applicable to C, | or maybe Pascal. Those are often held up today as a minimal | example in contrast to Lisp. There is a sort of sparse, warty | elegance to the family. Blocks, arrays, if/then, assignment, | while loops. What more could you need? | AnimalMuppet wrote: | I've used both C and Pascal. The simplicity of C comes | through to me (less so Pascal - the verbosity gets in the | way). I never thought of it as "as natural as a branch of | mathematics", though. | | I mean... I guess you could think of it as having its own set | of self-consistent axioms, and from them you can build | things. It's a lot larger set of axioms than most branches of | mathematics, though. | | I guess, if Hofstadter meant the same level of naturalness, | well, yes, C did feel pretty natural to me, so... maybe? | earthicus wrote: | It was discovered that the procedure mechanism of Algol 60 was | effectively equivalent to the lambda calulus. This insight was | written out in a famous paper by Peter Landin, "Correspondence | between ALGOL 60 and Church's Lambda-notation: part I" | | https://dl.acm.org/doi/10.1145/363744.363749 | aidenn0 wrote: | Hard to say without knowing which version of Algol he is | referring to. Algol 68 was very different from Algol 58. | | Algol 60 was the first language with lexical scope, while Algol | 68 was a kitchen-sink language that (positively) influenced | Python and (negatively) influenced Pascal. | kjellsbells wrote: | Regardless of your opinion on the utility of Lisp, this is an | exemplary piece of writing. Crisp, engaging, informative. | | God I miss old Scientific American. Today's SA isn't especially | terrible, but old SA, like old BYTE, was reliably enlightening. | taeric wrote: | Agreed. It saddens me how I feel I completely slept through a | golden age of magazines out there. With no real clue how I | could help support that coming back. | | I was happy with the section in Wireframe magazines that would | show how to code some game mechanics every issue. Would love | for more stuff like that. | sgustard wrote: | The title of his column and book "Metamagical Themas" is an | anagram of Martin Gardner's previous column "Mathematical | Games". It's clever wordplay turtles all the way down. | madcaptenor wrote: | Other Hofstadter book titles with wordplay: | | - Godel, Escher, Bach: an Eternal Golden Braid (you have | GEB/EGB, and I guarantee you he noticed those notes form a | musical triad) | | - Metamagical Themas (anagram of Mathematical Games) | | - Le Ton beau de Marot (I don't have my copy at hand, but | "ton beau" is surely a pun on "tombeau" meaning "tomb") | | - The Mind's I (editor) (I = eye) | | - That Mad Ache (translation of "La chamade" by Francoise | Sagan; "mad ache" is an anagram of "chamade") | gjm11 wrote: | "tombeau" _literally_ means "tomb", but the term also | sometimes means "piece written as a memorial", like Ravel's | piano suite "Le Tombeau de Couperin". And yes, Hofstadter | explicitly links "ton beau" with "tombeau" (he doesn't | explicitly mention the "memorial" meaning, though when he | mentions the literal "tombeau de Marot" he is talking | specifically about the epitaph on it) and also with "tome | beau", the great book of Marot's life and work. | | I'd find it a cleverer bit of wordplay if "le ton beau de | ..." itself didn't feel clumsy. Surely it would always be | "le beau ton de ..."? | madcaptenor wrote: | This was all somewhere in the back of my head but my copy | of this book is in my parents' basement somewhere. I'll | have to rescue it so I can keep it in my basement. | shrubble wrote: | At least one of the covers of GEB specifically had artwork | that shows GEB/EGB : | https://en.wikipedia.org/wiki/G%C3%B6del,_Escher,_Bach | goldfeld wrote: | The author of GEB is a phenomenal writer, an old-style | researcher who knew his greek, and the book for me is more | interesting in its commentary on literature, and psychology, | approaching themes of say, Foucault. | | I don't know about the work's true impact on AI or tech | languages, but it's a masterpiece of criticism, analysis and | penmanship. | jhbadger wrote: | Old school SA was written assuming a basic level of scientific | and mathematical background. Many people reading it were | professional scientists and engineers who read it to learn | about developments in other fields than their own. Current SA | seems to be written at a level similar to the science coverage | in newspapers, written for the hypothetical "layman" who is | supposedly frightened of mathematics and anything technical. I | couldn't imagine someone like Martin Gardner or Hofstadter | writing in SA today. | fuzztester wrote: | Same with the old National Geographic magazine, before it | became slimmer and more ad-heavy, IIRC. | taeric wrote: | I do think LISP remains the major language that can encompass the | strange loop idea he explored in his work. I know LISP is not the | only homoiconic language, but it is the biggest that people know | how to use where the "eval" function doesn't take in a string | that has to be parsed. | | I hate that people are convinced LISP == functional programming, | writ large. Not that I dislike functional programming, but the | symbolic nature of it is far more interesting to me. And it | amuses me to no end that I can easily make a section of code that | is driven by (go tag) sections, such that I can get GOTO | programming in it very easily. | nine_k wrote: | Another (properly functional) homoiconic language that enjoyed | mainstream adoption briefly in '00s is XSLT. Its | metaprogramming features were rather widely used, that is, | producing an XSLT from XSLT and maybe some more XML, instead of | hand-coding something repetitive, was rather normal. | | The syntax was a bigger problem than Lisp's syntax, though. | | It's not easy to produce a language with a syntax that's good | as daily use syntax, but is also not unwieldy as an AST. Lisp | is one of the few relatively successful examples. | AnimalMuppet wrote: | > The syntax was a bigger problem than Lisp's syntax, though. | | Yeah. XML and S expressions are pretty close to functionally | equivalent. But once you've seen S expressions, XML is | _disgustingly_ clumsy. | nine_k wrote: | SGML was intended for sparse markup in mostly plaintext | files. From it grew HTML that is markup-heavy, and XML | which is often 100% markup. What made sense for rare markup | nodes became... suboptimal when applied in a very different | role. | jll29 wrote: | 1. GML => SGML => XML | | 2. rm * | | 3. JSON | | 4. rm -rf / | pfdietz wrote: | "Any data can be turned into Big Data by encoding it in | XML." | chubot wrote: | They have a different model -- one is better for documents, | and one is better for programs/data | | XML and HTML are attributed text, while S-expressions are | more like a homogeneous tree | | If you have more text than metadata, then they are more | natural than S-expressions | | e.g. The closing </p> may seem redundant, until you have | big paragraphs of free form text, which you generally don't | in programs | apex_sloth wrote: | Thanks for this little flashback to when I had to write XSLT | for apache cocoon as my student job | pmarreck wrote: | I don't know how many other languages use it but I've long | admired Elixir's approach to giving devs access to the AST | using its basic types in order to write macros: | | https://hexdocs.pm/elixir/macros.html | | It is certainly possible to implement this sort of thing in | other languages, I think, depending on the compilation or | preprocessing setup | throwaway19972 wrote: | Not to mention specifically with Scheme and continuation- | oriented programming, the line between functional and non- | functional programming becomes so blurry as to become nearly | meaningless. | brucehoult wrote: | Lambda: the ultimate GOTO | bbor wrote: | I love and relate to any impassioned plea on SWE esoterica, so | this seems like as good of a place as any to ask: What, in | practice, is this deep level of "homoiconic" or "symbolic" | support used for that Python's functools | (https://docs.python.org/3/library/functools.html) doesn't do | well? As someone building a completely LISPless symbolic AGI | (sacrilege, I know), I've always struggled with this and would | love any pointers the experts here have. Is it something to do | with Monads? I never did understand Monads... | | To make this comment more actionable, my understanding of | Python's homoiconic functionality comes down to these methods, | more-or-less: | | 1. Functions that apply other functions to iterables, e.g. | filter(), map(), and reduce(). AKA the bread-n-butter of modern | day JavaScript. | | 2. Functions that wrap a group of functions and routes calls | accordingly, e.g. @singledispatch. | | 3. Functions that provide more general control flow or | performance conveniences for other functions, e.g. @cache and | and partial(). | | 3. Functions that arbitrarily wrap other functions, namely | wraps(). | | Certainly not every language has all these defined in a | standard library, but none of them seem that challenging to | implement by hand when necessary -- in other words, they | basically come down to conviences for calling functions in | weird ways. Certainly none of these live up to the glorious | descriptions of homoiconic languages in essays like this one, | where "self-introspection" is treated as a first class concern. | | What would a programmer in 2024 get from LISP that isn't | implemented above? | taeric wrote: | I'm basically a shill for my one decent blog post from a | while back. :D | | https://taeric.github.io/CodeAsData.html | | The key for me really is in the signature for "eval." In | python, as an example, eval takes in a string. So, to work | with the expression, it has to fully parse it with all of the | danger that takes in. For lisp, eval takes in a form. Still | dangerous to evaluate random code, mind. But you can walk the | code without evaluating it. | bbor wrote: | HackerNews sadly never fails to disappoint. Thanks for | taking the time to share, that was _exactly_ what I was | looking for! Would endorse this link for any lurkers. | | The LISP (elisp?) syntax itself gives me a headache to | parse so I think I'll stay away for now, but I'll | definitely be thinking about how to build similar | functionality into my high level application code -- self | modification is naturally a big part of any decent AGI | project. At the risk of speaking the obvious, the last | sentence was what drove it home for me: | It is not just some opaque string that gets to enjoy all of | the benefits of your language. It is a first class list of | elements that you can inspect and have fun with. | | I'm already working with LLM-centric "grammars" | representing sets of standpoint-specific functions | ("pipelines"), but so far I've only been thinking about how | to construct, modify, and employ them. Intelligently | _composing_ them feels like quite an interesting rabbit | hole... Especially since they mostly consist of prose in | minimally-symbolic wrappers, which are probably a lot | easier for an engineer to mentally model--human or | otherwise. Reminds me of the words of wonderful diehard | LISP-a-holic Marvin Minsky: The future work | of mind design will not be much like what we do today. | ...what we know as programming will change its character | entirely-to an activity that I envision to be more like | sculpturing. To program today, we must describe | things very carefully because nowhere is there any margin | for error. But once we have modules that know how to learn, | we won't have to specify nearly so much-and we'll program | on a grander scale, relying on learning to fill in details. | | In other words: What if the problem with Lisp this whole | time really _was_ the parentheses? ;) | | source is _Logical Versus Analogical or Symbolic Versus | Connectionist or Neat Versus Scruffy_ : https://onlinelibra | ry.wiley.com/doi/full/10.1609/aimag.v12i2... | taeric wrote: | Glad you liked the post. I didn't do any effort to make | the elisp readable, so please don't let that fully put | you off the topic! :D | | I keep meaning to expand on the idea. I keep not doing | so. I have higher hopes that I can get back to the | rubik's cube code. Even there, I have a hard time getting | going. | BoiledCabbage wrote: | > HackerNews sadly never fails to disappoint. | | FYI, that means the opposite of how you used it. | | "Never fails to disappoint" is an idiom that means a | person or thing consistently disappoints. | wk_end wrote: | The _syntax_ of Lisp is made up of the same fundamental data | types as you use when writing Lisp programs. `(+ 1 2 3)` is | _both_ a Lisp expression that evaluates to 6 and also a list | containing four items, the symbol `+` and the numbers 1, 2, | and 3. | | In general, we can say that the Lisp language is very good at | manipulating the same data types that the syntax of Lisp | programs is made from. This makes it very easy to write Lisp | programs that swallow up Lisp programs _as raw syntax_ , | analyze Lisp programs syntactically, and/or spit out new Lisp | programs _as raw syntax_. | waffletower wrote: | I find this article to be quaint -- remember reading it decades | ago and feeling more receptive to its perspective. Ironically, I | prefer using Clojure (though some here challenge its status as a | Lisp lol) to interface with Large Language Models rather than | Python. Clojure in particular is much better suited, for some | reasons that Hofstadter details, and if you can interact with an | LLM over a wire, you are not beholden to Python. But what we use | to interface to these massive digital minds we are building, | including the Bayesian sampling mathematics we use to plumb them, | may have their elegance, but they are orthogonal to the nearly | ineffable chaos of these deeply interconnected neural networks -- | and it is in this chaotic interconnectedness where artificial | intelligence is actually engendered. | iLemming wrote: | > Clojure in particular is much better suited | | Clojure in general is far better suited for manipulating data | than anything else (in my personal experience). It is so lovely | to send a request, get some data, and then interactively go | through that data - sorting, grouping, dicing, slicing, | partitioning, tranforming, etc. | | The other way around is also true - for when you need to | generate a massive amount of randomized data. | troupe wrote: | > when you need to generate a massive amount of randomized | data. | | Even faster than Clojure: Open VIM for a VS Code user and ask | them to exit. | iLemming wrote: | There's no such thing as a "VS Code user", VS Code is the | one that uses you, not the other way around. | | btw. this isn't some kind of an FP joke, there's no 'fun' | in it, only sad truth. | InDubioProRubio wrote: | Lisp aNeeds Braces | paddy_m wrote: | > Lisp needs braces | | You're a troll, but I'll feed you. I adapted Peter Norvig's | excellent lispy2.py [0] to read json. I call it JLisp [1]. | | Lispy2 is a scheme implementation, complete with macros that | executes on top of python. I made it read json, really just | replacing () with []. and defining symbols as {'symbol': | 'symbol_name'}. I built it because it's easier to get a webapp | to emit JSON then paren lisp. I also knew that building an | interpreter on top of lisp meant that I wouldn't back myself | into a corner. There is incredible power in the lisp, | especially the ability to transform code. | | [0] https://norvig.com/lispy2.html | | [1] | https://github.com/paddymul/buckaroo/blob/main/tests/unit/li... | #tests for JLisp | NateEag wrote: | Here, have another approach to Lisp formatting: | | https://readable.sourceforge.io/ | | I looked into porting it to elisp a while back, but the elisp | reader was missing a feature or two sweet-expressions require. | I should see if that's still true... | dunefox wrote: | > I hope you enjoyed Hofstadter's idiosyncratic tour of Lisp. You | can find more like this re-printed in his book Metamagical | Themas. | | This seems like an interesting book. | ceautery wrote: | It was one of my favorites back in the 1980s. It was a followup | to Godel Escher Bach, written in much the same style. | lopatin wrote: | Any Shen people in the house? | corinroyal wrote: | Admirer, not user. So ambitious and gorgeous. Hosted on Common | Lisp with full integration, so useful now. I hope more people | check it out. The new Shen book is awesome. | jll29 wrote: | links? | corinroyal wrote: | Here's a link to their website with the book: | https://shenlanguage.org/TBoS/tbos.html | susam wrote: | _> Attempting to take the car or cdr of nil causes (or should | cause) the Lisp genie to cough out an error message, just as | attempting to divide by zero should evoke an error message._ | | Interestingly, this is no longer the case. Modern Lisps now | evaluate (car nil) and (cdr nil) to nil. In the original Lisp | defined by John McCarthy, indeed CAR and CDR were undefined for | NIL. Quoting from | <https://dl.acm.org/doi/pdf/10.1145/367177.367199>: | | _> Here NIL is an atomic symbol used to terminate lists._ | | _> car [x] is defined if and only if x is not atomic._ | | _> cdr [x] is also defined when x is not atomic._ | | However, both Common Lisp and Emacs Lisp define (car nil) and | (cdr nil) to be nil. Quoting from <https://www.lispworks.com/docu | mentation/HyperSpec/Body/f_car...>: | | _> If x is a cons, car returns the car of that cons. If x is | nil, car returns nil._ | | _> If x is a cons, cdr returns the cdr of that cons. If x is | nil, cdr returns nil._ | | Also, quoting from <https://www.gnu.org/software/emacs/manual/htm | l_node/elisp/Li...>: | | _> Function: car cons-cell ... As a special case, if cons-cell | is nil, this function returns nil. Therefore, any list is a valid | argument. An error is signaled if the argument is not a cons cell | or nil. _ | | _> Function: cdr cons-cell ... As a special case, if cons-cell is | nil, this function returns nil; therefore, any list is a valid | argument. An error is signaled if the argument is not a cons cell | or nil._ | susam wrote: | I was curious what it is like on Maclisp. Here is a complete | telnet session with Lars Brinkhoff's public ITS: | $ telnet its.pdp10.se 10003 Trying 88.99.191.74... | Connected to pdp10.se. Escape character is '^]'. | Connected to the KA-10 simulator MTY device, line 0 | ^Z TT ITS.1652. DDT.1548. TTY 21 3. Lusers, | Fair Share = 99% Welcome to ITS! For brief | information, type ? For a list of colon commands, type :? | and press Enter. For the full info system, type :INFO and | Enter. Happy hacking! :LOGIN SUSAM TT: | SUSAM; SUSAM MAIL - NON-EXISTENT DIRECTORY :LISP | LISP 2156 Alloc? n * (status | lispversion) /2156 (car nil) NIL (cdr | nil) NIL ^Z 50107) XCT 11 :LOGOUT | TT ITS 1652 Console 21 Free. 19:55:07 ^] telnet> | ^D Connection closed. $ | dokyun wrote: | I recall reading that in early versions of Maclisp, taking | the CAR or CDR of NIL worked differently: Taking its CAR | would signal an error as you would expect, however taking its | CDR would return the symbol plist of NIL, as internally the | operation of CDR on the location of a symbol would access its | plist, and that's how it was commonly done before there was a | specific form for it (and it actually still worked that way | into Lisp Machine Lisp, provided you took the CDR of the | locative of a symbol). | | Apparently the behaviour of the CAR and CDR of NIL being NIL | was from Interlisp, and it wasn't until the designers of | Maclisp and Interlisp met to exchange ideas that they decided | to adopt that behaviour (it was also ostensibly one of the | very few things they actually ended up agreeing on). The | reason they chose it was because they figured operations like | CADR and such would be more correct if they simply returned | NIL if that part of the list didn't exist rather than | returning an error, otherwise you had to check each cons of | the list every time. (If somebody can find the source for | this, please link it!) | pfdietz wrote: | But of course cadr still has to check each access, to see | if its of type (or cons null). So I don't see what was | saved. | dokyun wrote: | It would be considered "the right thing" to do something | that's so common you probably want it without asking. I | don't think CADR would check for NIL since it's meant to | be equivalent to (car (cdr x)), so if you wanted a safe | list operation you would have to check it like this: | (I'll use CADADR because it makes the issue more | apparent) (and (car x) (cadr | x) (cadar x) (cadadr x)) | | You would have to write this every time you want to see | if there's a really CADADR, whereas if CAR and CDR can | return NIL then you can just write (cadadr x) and CADADR | can still be defined as (car (cdr (car (cdr x)))) and | have the desired behaviour. | sph wrote: | Sadly this is not the case with Scheme and it makes for very | unergonomic code, especially for a newbie like me. | | Which is a shame, because I prefer (Guile) Scheme to Common | Lisp. | pfdietz wrote: | I'm very tied to Common Lisp, but I'm perfectly fine with the | idea of a lisp in which car and cdr would be undefined on | nil. Also, I'd be fine with a lisp in which () is not a | symbol. I don't think these features of Common Lisp are | essential or all that valuable. | sph wrote: | They are not essential, but they make code that operates in | lisp more compact and pleasant to write. | | In Scheme my code is littered with (if | (null? lst) ;; handle empty case here | ...) | | Simply because otherwise car throws an error. This whole | section is often unnecessary in CL. | tmtvl wrote: | But you need to handle the empty case anyway otherwise | you process nils ad infinitum. | erik_seaberg wrote: | You can say (if lst ...) | | if the empty list is falsy, but Scheme eventually chose | to add #t and #f. Oddly #f is the only false value but #t | is not the only true value. | BoiledCabbage wrote: | > Sadly this is not the case with Scheme and it makes for | very unergonomic code, | | How so? If car of nil returns nil, then how does a caller | distinguish between a value of nil and a container/list | containing nil? | | The only way is they can check to see if it's a cons pair or | not? So if you have to check if it's a cons pair then you're | doing the same thing as in scheme right? | | I may be missing something, but isn't it effectively the same | amount of work just potentially? Need to check for nil and | need to check if it's a pair? | susam wrote: | > How so? If car of nil returns nil, then how does a caller | distinguish between a value of nil and a container/list | containing nil? | | How about this? CL-USER> (null nil) T | CL-USER> (null '(nil)) NIL CL-USER> | BoiledCabbage wrote: | I think that's my point. You still need a separate call | to distinguish the nil rom the list of nil case. | | At that point, if you're making the two calls how is | LISP's behavior any more ergonomic than Scheme. I'm not | saying it's not possible, I just don't see it. | | Can you show code between the two and how one is much | worse than the other? | dkarl wrote: | The use of car and cdr are such a surprisingly concrete | implementation detail in the birth of a language that was | designed to be mathematical. The most basic and famous | operators of "List Processor" were created to operate not on | lists but on conses, an element in a particular machine | representation that Lisp uses to build data structures! Not | only are conses not always interpreted as lists, but a very | very important list, the base case for recursive functions on | lists, is not represented by a cons. | | Sixty years later, most Lisp programs are still full of | operations on conses. A more accurate name for the language | would be "Cons Processor!" It's a reminder that Lisp was born | in an era when a language and its implementation had to fit | hand in glove. I think that makes the achievement of grounding | a computer language in mathematical logic all the more | remarkable. | fuzztester wrote: | maybe related to the need to _cons_ erve CPU registers in | machines of the time? | | https://en.m.wikipedia.org/wiki/CAR_and_CDR | | In any case, _AST_ ute _observation_ | | er, ASTute _;_ ) | lisper wrote: | > Modern Lisps now evaluate (car nil) and (cdr nil) to nil. | | Scheme doesn't. Taking the CAR or CDR of nil is an error. | anthk wrote: | Elisp and CL do. | susam wrote: | Does Scheme even have NIL in the sense that other Lisps like | CL or Elisp have? I mean in Common Lisp, we have: | CL-USER> (symbolp nil) T CL-USER> (atom nil) | T CL-USER> (listp nil) T | | Similar results in Emacs Lisp. But in MIT Scheme, we get: | 1 ]=> nil ;Unbound variable: nil | | Of course, we can use () or (define nil ()) to illustrate | your point. For example: 1 ]=> (car ()) | ;The object (), passed as the first argument to car, is not | the correct type. | | But when I said NIL earlier, I really meant the symbol NIL | that evaluates to NIL and is both a LIST and ATOM. But | otherwise, yes, I understand your point and agree with it. | dokyun wrote: | I don't believe so, standardly. Guile scheme added the | value `#nil' which is equivalent to NIL and distinct from | #f and the empty list, but this was done in order to | support Emacs Lisp. | lisper wrote: | > Does Scheme even have NIL in the sense that other Lisps | like CL or Elisp have? | | No. It has an empty list, which is a singleton atomic value | whose type is not shared with any other object, and it has | a boolean false value, which is distinct from the empty | list. A user can create a symbol named NIL, but that symbol | has no characteristics that distinguish it from any other | symbol. You can, of course, bind NIL to either the empty | list or boolean false (or any other value) but it can only | have one value at a time (per thread). | lisper wrote: | There really should be two different kinds of cons cells, one | for "proper" linked lists and another for general purpose | consing. The difference is that the cdr of the first kind of | cons cell (I'll call it a PL-cons) can only be NIL or another | PL-cons, not anything else. This would eliminate vast | categories of bugs. It would also make the predicate for | determining is something was a proper list run in constant time | rather than O(n). (There would still be edge cases with | circular lists, but those are much less common than non-proper | lists.) | oaktowner wrote: | I just love his writing so much -- he captures what I felt when I | discovered Lisp. As a kid learning programming in the 80s, I had | already done some BASIC, Fortran, Pascal and COBOL in high school | and early college. There were differences, of course, but they | had some fundamental commonality. | | At UC Berkeley, however, the first computer science class was | taught in Scheme (a dialect of Lisp)...and it absolutely blew me | away. Hofstadter is right: it feels the closest to math | (reminding me a _ton_ of my math theory classes). It was the | first _beautiful_ language I discovered. | | (edit: I forgot to paste in the quote I loved!) | | "...Lisp and Algol, are built around a kernel that seems as | natural as a branch of mathematics. The kernel of Lisp has a | crystalline purity that not only appeals to the esthetic sense, | but also makes Lisp a far more flexible language than most | others." | Jeff_Brown wrote: | Have you tried Haskell? It feels much closer to math to me. | Definitions, not procedures. It even _looks_ like math. | oaktowner wrote: | No! After about 10 years of writing software professionally, | I moved over to product management, and my time spent coding | decreased drastically (in the last 15 years, only some Python | to show my kids a thing or two). | | But I'd love to try! Maybe I'll take an online class for fun. | Jeff_Brown wrote: | I can't recommend it highly enough. You're already familiar | with laziness from Lisp, but purity is another head-trip. | It made me a better programmer in any language, and even a | better software architect before I've written a line of | code. | | And algebraic data types make it possible to make your code | conform to reality in ways that classes can't. Once you're | exposed to them, it's very much like learning about | addition after having been able to multiply for your whole | life. (In fact that's more than a metaphor -- it's what's | happening, in a category theoretic sense.) | | Haskell has other cool stuff too -- lenses, effect systems, | recursion schemes, searching for functions based on their | type signatures, really it's a very long list -- but I | think laziness, purity and ADTs are the ones that really | changed my brain for the better. | sourcepluck wrote: | Have you tried Coalton? It's a Common Lisp library that | adds Haskell-esque (or near-Haskell) type wonders, and | which smoothly interoperates with your Common Lisp code. | | Your comment is great though, consider me convinced. I've | done a bit of messing with Lisp, but really would like to | try write something in Haskell, or slog through a book or | two, some day. | chamomeal wrote: | Damn that was a really good pitch. I think I'm too dumb | to learn Haskell though lol. I'm struggling enough with | immutability in clojure!! | tightbookkeeper wrote: | Personal anecdote: I got a lot more out of lisp that stuck | with me than Haskell. Occasionally I say "oh this is a monad" | or think about a type signature, but that's about it. | nxobject wrote: | At the risk of diverging off from the original post, I also | think that calling it "math" might make things a bit murky (and | this is coming from someone who wanted to be algebraic | topologist!) | | It _is_ an elegant and minimal expression of a style of | programming that is ubiquitous among dynamically-typed, | garbage-collected languages. And it's a "theory" in the sense | that it seems complete, and that you can think of ways to solve | problems into Scheme and translate that into other dynamically- | typed languages and still end with an elegant solution. | Emphasis on the elegant (since minimal, wart-free, consistent | and orthogonal, etc.). | | Scheme was a simplification and a "cleaning up" compared to | conventional Lisps of the time (lexical scoping, single shared | namespace for functions and variables etc.) | eigenhombre wrote: | I loved Hofstadter's writing on Lisp in Metamagical Themas and | adapted the code in the last article of the series to Clojure for | a study group at work, written up here[1]. | | [1] http://johnj.com/posts/oodles/ | | edit: clarification | silcoon wrote: | Nice, I wonder if there was a translation on a modern Lisp. | abecedarius wrote: | https://github.com/darius/cant/blob/master/examples/text/ood. | .. though modern is a matter of fashion. | susam wrote: | _> In a testament to the timelessness of Lisp, you can still run | all the examples below in emacs if you install these aliases:_ | | _> (defalias 'plus #'+)_ | | _> (defalias 'quotient #'/)_ | | _> (defalias 'times #'*)* | | _> (defalias 'difference #'-)* | | Looks like we also need a defmacro for def that is used much | further in the article: | | _> > (def rac (lambda (lyst) (car (reverse lyst))))_ | | I mean the above example fails in Emacs: ELISP> | (def rac (lambda (lyst) (car (reverse lyst)))) *** Eval | error *** Symbol's function definition is void: def | | If we want the above example to work, we need to define def like | this: ELISP> (defmacro def (name lambda-def) | `(defalias ',name ,lambda-def)) def | | Now the previous example, as presented in the article, works | fine: ELISP> (def rac (lambda (lyst) (car | (reverse lyst)))) rac ELISP> (rac '(your brains)) | brains | activitypea wrote: | I remember reading GEB and being shocked that he never mentions | Lisp. He _does_ wade into CompSci topics, but it's something | half-hearted about how compilers are programs that read and | generate programs. This really should've been integrated into a | revised edition of the book. | lisper wrote: | Huh? He mentions Lisp all over the place. Check the index. | silcoon wrote: | Give it another go! _The Anatomy of LISP_ is the first entry in | the bibliography. | baruchthescribe wrote: | Nonsense. | | "One of the most important and fascinating of all computer | languages is LISP (standing for "List Processing"), which was | invented by John McCarthy around the time Algol was invented. | Subsequently, LISP has enjoyed great popularity with workers in | Artificial Intelligence." | susam wrote: | In case anyone else is confused by what the functions named | "oval" and "snot" mean in the following example: | > (cond ((eq (oval pi) pie) (oval (snot pie pi))) (t (eval | (snoc (rac pi) pi)))) | | I realised after a few seconds that they are meant to be "eval" | and "snoc" instead. The above code should be written as the | following instead: (cond ((eq (eval pi) pie) | (eval (snoc pie pi))) (t (eval (snoc (rac pi) pi)))) | | This article has been a fascinating read, by the way. Kudos to | the maintainer of the Gist post. I am also sharing these | corrections as comments on the Gist post. | | EDIT #1: Downloaded a copy of the original Scientific American | article from https://www.jstor.org/stable/24968822 and confirmed | that indeed the functions "oval" and "snot" are misspellings of | "eval" and "snoc". | | EDIT #2: Fixed typo in this comment highlighted by @fuzztester | below. | hinkley wrote: | OCR maybe? | fuzztester wrote: | >confirmed that indeed the functions "oval" and "snot" are | misspellings of "eval" and "snot". | | Correction of your correction: | | confirmed that indeed the functions "oval" and "snot" are | misspellings of "eval" and " _snoc_ ". | | And I guess snoc is cons reversed and rac is car reversed. | susam wrote: | > Correction of your correction | | Thanks! Fixed. | | > And I guess snoc is cons reversed and rac is car reversed. | | Indeed! That's exactly how those functions are introduced in | the article. Quoting from the article: | | _> The functions rdc and snoc are analogous to cdr and cons, | only backwards._ | kevindamm wrote: | This article, and the two companion articles it mentions, can be | found in the book "Metamagical Themas" [0] in chapters 17-19, as | well as all of his other articles that appeared in this series of | Scientific American. | | [0]: | https://www.goodreads.com/book/show/181239.Metamagical_Thema... | | (the book's title is the article series, which originated as an | anagram of the article series that Martin Gardner authored, | "Mathematical Games," also published in Scientific American and | which Hofstadter then took over) | antitoi wrote: | I love this book. Highly recommended for all lovers of Godel | Escher Bach (his classic). | analog31 wrote: | I read that article when it came out, as my parents subscribed to | Scientific American. Even though I had learned BASIC and Pascal, | the concepts in the article were just way over my head. Also, I | had no access (that I was aware of at least) to a machine where I | could try my hand at Lisp programming. Alas, I wish I had taken | it more seriously. | | At least Hofstadter was successful at getting me interested in | math beyond high school. | bsder wrote: | This article simply reinforces that the primary problem with the | popularity of Lisp was people _explaining Lisp_. | | This article, like every other Lisp article, tells pre-teen me | _nothing that he could use_. Nobody ever demonstrated how much | easier task X is in Lisp over asm /C/Pascal/etc. | | By contrast, current me could have told pre-teen me "Hey, that | spell checker that took you 7 months to write in assembly? Yeah, | it's damn near trivial in Lisp on a microcomputer with bank | switched memory that nobody every knew how to utilize (it makes | garbage collection completely deterministic even on a woefully | underpowered CPU). Watch." | | I want to weep over the time I wasted doing programming with the | equivalent of tweezers, rice grains and glue because every Lisp | article and textbook repeated the same worn out lists, recursion | and AI crap without ever demonstrating how to do anything | _useful_. | lispm wrote: | Practical Common Lisp https://gigamonkeys.com/book/ | bsder wrote: | Didn't exist back then. Likewise SICP first edition was 1996. | | I did have a copy of "LISP: A Gentle Introduction to Symbolic | Computation" by Touretzky in 1986. It wasn't really that much | better than any of the articles. It never explained _why_ | using Lisp would be so much easier than anything else even | for simple programming tasks. | | Had some of the Lisp hackers deigned to do stuff on the | piddly little micros and _write it up_ , things would look a | whole lot different today. | | Maybe there was a magazine somewhere doing cool stuff with | Lisp on micros in the 1980-1988 time frame, but I never found | it. | keithwinstein wrote: | The first edition of SICP came out in the fall of 1984 (a | year after these Hofstadter columns). This fall is the 40th | anniversary! | bsder wrote: | I stand corrected on that. Thanks. | troupe wrote: | Common Lisp: A Gentle Introduction to Symbolic Computation | might be useful for the context you are describing. | https://www.cs.cmu.edu/~dst/LispBook/ | abecedarius wrote: | Hofstadter's followup article had a more interesting example. | | When I first got a Byte magazine as a pre-teen, one of the | articles was Lisp code for symbolic differentiation and | algebraic simplification. I _really_ couldn 't follow it but | felt there was something intriguing there. Certainly it | wouldn't have been easier in Basic. | | (Byte September 1981, AI theme issue. Later I was able to tell | the code was not so hot...) | | I didn't really get into Lisp until the late 80s with XLisp on | a PC, and SICP. Worth the wait! | timonoko wrote: | Maclisp goodness: (compress (reverse (explode | x))) | | Elisp much improved: (defun explode (x) | (if (symbolp x) (setq x (symbol-name x))) (string-to-list | x)) (defun compress (x) (concat x)) | UniverseHacker wrote: | (upgrade (mail (change (trash (fix (break (use (buy it)))))))) | timonoko wrote: | I was wrong: It was "implode" in Maclisp. | (compress (reverse (explode 'ABC))) ;COMPRESS UNDEFINED | FUNCTION OBJECT (implode (reverse (explode 'ABC))) | CBA | | The point being that I never learn any fancy string-processing | commands. I just implement explode and compress. | smrq wrote: | I certainly know the Lisp information in this article already, | but it's still a fun read. Hofstadter just has a charming way | with words. | | I found this bit extra amusing: | | >It would be nice as well as useful if we could create an inverse | operation to readers-digest-condensed-version called rejoyce | that, given any two words, would create a novel beginning and | ending with them, respectively - and such that James Joyce would | have written it (had he thought of it). Thus execution of the | Lisp statement (rejoyce 'Stately 'Yes) would result in the Lisp | genie generating from scratch the entire novel Ulysses. Writing | this function is left as an exercise for the reader. | | It took a while, but we got there. I don't think 2024's AI is | quite what he had in mind in 1983, but you have to admit that | reproducing text given a little seeding is a task that quite | suits the AI of today. ___________________________________________________________________ (page generated 2024-10-17 06:00 UTC)