13 ms·
Between two Lisps
- jolux 6y agoNitpick: the latest standard is R7RS-small (https://small.r7rs.org https://small.r7rs.org), which is (expectedly) smaller than R6RS. I believe it was supposed to be accompanied by something like R7RS-large, covering the rest of what is expected in a Scheme standard to succeed R6RS.
- dleslie 6y agoYes, large is on its way. https://github.com/johnwcowan/r7rs-work https://github.com/johnwcowan/r7rs-work
- abhinav22 6y agoI prefer the syntax of CL over Scheme, but the latter is definitely a wonderful language and goes hand in hand with the wizard book, SICP. At the end of the day, language choice, much like choice of editors or mechanical keyboards, is not that important — what is important is actually coding and building useful software. This can be done in any language, although I do not want to sound ignorant, as certain languages are better suited for certain tasks (eg swift for iOS dev). As a Mac/Windows user, I’d be keen to know how popular Guile is for GNU Projects? For those who want to learn Common Lisp quickly, this is a great guide: https://github.com/ashok-khanna/common-lisp-by-example https://github.com/ashok-khanna/common-lisp-by-example
- frutiger 6y agoGNU Guile is the expression language for Guix (perhaps its major distinguishing feature, when compared to Nix, which uses its own bespoke language).
- abhinav22 6y agoThanks! Guix sounds pretty cool, I just did a cursory read of Wikipedia after your post.
- dleslie 6y agoI love Scheme, but it _badly_ needs call/cc replaced with delimited continuations.
- mst 6y agoThe ease of implementing call/cc early on when you have a trivial interpreter is dangerous - it becomes far too easy to end up not realising you've made a rod for your own back until way too late. A spec entry for delimited continuations with call/cc as an -optional- feature would definitely seem like an improvement in terms of leading implementors down a saner path.
- svieira 6y agoWhat is the difference between call/cc and delimited continuations?
- mst 6y agoMy main interest: delimited continuations are only valid within a specific stack extent so they're much for viable for extensive use - one could argue that async/await is kinda the simplest (and most limited) possible delimited continuation implementation. For a better understanding, https://en.wikipedia.org/wiki/Delimited_continuation https://en.wikipedia.org/wiki/Delimited_continuation didn't feel like a terrible start and I'm far from an expert here.
- dreamcompiler 6y agoThe fully-general continuations that call/cc creates require copying chunks of the stack to the heap for storage and back again when they're used. (Or pointing the stack pointer at the heap, which I find even more cringe-inducing.) They're memory hogs whose lifetimes are hard to reason about and they provide relatively little benefit to most programs, which is why Common Lisp doesn't provide them.
- michaelsbradley 6y agoDelimited continuations, a.k.a composable continuations, are. a generalization of control operators such as call/cc. https://en.wikipedia.org/wiki/Delimited_continuation https://en.wikipedia.org/wiki/Delimited_continuation
- pmoriarty 6y ago"I prefer the syntax of CL over Scheme" Can you elaborate on what it is about CL syntax that you prefer over Scheme, and why?
- pfdietz 6y ago> Then again, in Common Lisp it’s somewhat rarer to have C extensions, so I don’t know how ASDF handles that. CFFI https://common-lisp.net/project/cffi/ https://common-lisp.net/project/cffi/
- lisper 6y agoYeah, this. I call C code from CL all the time. Also Objective C if I'm working with Clozure CL on a Mac.
- jlarocco 6y agoBesides CFFI there's also cl-autowrap and claw. I haven't used claw myself, but I know cl-autowrap makes wrapping C libraries really easy. It took me about 4 hours and <200 lines of code to have a complete, usable binding for GDAL, and most of that was in convenience functions. I'm curious to see what happens with the C++ support in claw. They're working on it, but I'm skeptical. I haven't had much luck using arbitrary C++ libraries from any language other than C++. And I don't know what the author means by "somewhat rarer" in this context, but I personally use C libraries from CL all the time. Almost every CL project I work on, now that I think about it.
- borodust 6y ago:claw author reporting in. At first, I was semi-skeptical too, but not anymore. I've managed to wrap a few C++ libraries (GLM, Filament, PhysX). Not without a manual intervention (claw is still evolving and adapting to C++ edge cases), but those libraries pretty much work now. I'm not sure I would be able to cover all C++ idiosyncrasies, but huge parts are already in. That said, claw's C++ support is still in the works and I don't recommend diving into that mess yet. Stay tuned for Q1 2021 semi-usable alpha release. Or not. C++ is such a pile of shinies, I'm pretty sure I lost a few screws during :claw development.
- jlarocco 6y agoI'll have to take another look! Very surprised to see GLM in that list!
- deleted 6y ago[deleted]
- nabla9 6y agoIf CL had only two namespaces, it would be odd and random, but not unique. It's like writing `./foo` vs `foo` in shell. Common Lisp is naturally more like operating system than programming language anyway. But once you realize that CL has more than two namespaces (I think it has at least nine in the language itself, unlimited in user programs) it's easier to understand how it can be more than historical accident. People are used to thinking words in context. I do mostly numerical programming today. Common Lisp would have been my preference and IMHO much better than Python I have no time to rewrite numpy or R libraries in CL.
- phoe-krk 6y agoThe standard Common Lisp namespaces I can count off the top of my head are variables/symbol macros, functions/macros, compiler macros, types/classes/condition types, class slots, TAGBODY tags, BLOCK names, THROW tags, restarts, documentation types. Users can easily define new ones.
- dreamcompiler 6y agoAnd types and classes are subtly different namespaces BTW. Try specializing a method on KEYWORD. In pure ANSI implementations you can't because KEYWORD is a type but not a class, and method specializers have to be classes.
- phoe-krk 6y agoYes, but defining a class always defines a matching type - hence they share a namespace in a way.
- deleted 6y ago[deleted]
- dan-robertson 6y agoI’m not sure I’d count compiler macros as a separate namespace to functions or macros. It feels like they’re the same to me. I think I also wouldn’t count throw tags as a namespace as they can be objects rather than symbols (but then again lists like (setf foo) are valid function names). I think method combinations and packages are other namespaces.
- azhenley 6y agoTime to make a new Lisp!
- GeorgeTirebiter 6y agoHave you tried newLISP ? http://www.newlisp.org/ http://www.newlisp.org/ I am having a lot of fun with it. I'd call it a 'practical' LISP.
- azhenley 6y agoI am often wishing I knew of an easier way to compare Lisps. I haven't used any dialect enough to fully grasp the subtleties. For example, the differences between Racket and Clojure.
- mumblemumble 6y agoProbably the main difference between Clojure and all the rest, from a purely lispy perspective, is that it's not list-oriented. Maps are its preferred data structure. I'm not even sure it has cons cells - at the very least, I've never seen them being used. Probably the main thing that distinguishes Racket is that it's meant to be a playground for experimenting with programming language design.
- fiddlerwoaroof 6y agoClojure is really designed around the sequence abstraction, which is list-like but not a list: Clojure’s various concrete datastructures all implement this abstraction and, consequently, much of clojure.core is more generic than the equivalent functions in the CL package: maps present as sequences of pairs; vectors, sets and lazy sequences all present as sequences of items, etc.
- oalae5niMiel7qu 6y agoClojure is oriented towards functional programming, hence no loops, but because it's also a thin abstraction over the JVM, it doesn't provide tail-call elimination, so you can't write traditional functional code the way you would in SML or Scheme. Instead, you have to use the clumsy "recur" construct to work around the JVM's limitations. It's also less consistent than proper Lisps. For example, it's possible to produce a Java OverflowException using Clojure math operators. Some operations will gracefully upgrade to bignums, but others don't.
- pfdietz 6y agoThe piece has the usual complaining about CL being a Lisp-2. When I ask to have the advantage of a Lisp-1 explained to me, I get some handwaving about "elegance", rather than a specific explanation for why someone would want that. Personally, I find a Lisp-2 (or a Lisp-N) to be more convenient and more understandable. And I don't have to have lexical variables named "lst".
- mumblemumble 6y agoSaying that it's weird (which it is - I have a really hard time thinking of other languages that do this) and then pointing out that there are good reasons why it's that way, and linking an article explaining them, and then explicitly saying, "this isn't a fault, my comfort zones are a product of what I already know," isn't exactly complaining. It's possibly the most measured, non-partisan response to the whole lisp-1 vs lisp-2 thing I've ever seen.
- fiddlerwoaroof 6y agoJava is a Lisp-2; method names exist in a separate namespace from values (although, there may be semi-arbitrary restriction of name collisions): foo.toString doesn’t give you a “function object”.
- lispm 6y ago> I have a really hard time thinking of other languages that do this Ruby, PERL, R, Shell languages, Elixir.
- rtpg 6y agoThe most basic reason for wanting a Lisp-1 would be to make code more context-free. "foo" refers to "foo", and you don't have to be aware of whatever special underlying context is there. The closest parallel I can think of is Scala implicits. You give me a fragment of Scala code using implicits it might be hard to know _what_ is going to happen. Similarly, having a bunch of namespaces (or, perhaps more importantly, leaning into them and having many name overlaps) just means that it's harder to read a single code fragment and know what it's going to do. Though I'm pretty partial to the argument that, like..... yeah you're going to call a function so the name refers to a function. But without extra symbols around this concept to help the reader, in this age it seems like a concept that is hard to take advantage of.
- banjomet 6y agoI was expecting Clojure vs Common Lisp. I love scheme but it's not fair to include considering how few libraries there are (I don't even know if there is a package manager).
- mbakke 6y agoThe article mentions GNU Guix as "the" package manager for Guile Scheme. Now, Guix includes some 15000 non-Scheme packages, so it is somewhat "overkill". OTOH you can also install/run/dockerize a world of Common Lisp packages with Guix. :-)
- banjomet 6y agoGuix is a package manager written in scheme, but as the article states they are considering how to use it for guile if they do.
- uncletaco 6y agoThe article mentioned at least two scheme package managers: chicken-install and GNU Guix.
- sigzero 6y agoRacket has tons of packages and I believe it has everything he talked about (keyword arguments, etc.).
- banjomet 6y agoI also managed to completely forget about Racket. I was thinking only of Guile like an idiot.
- rscho 6y agoMaybe typing "scheme package manager" on google and clicking the very first link would help?
- banjomet 6y ago
- MH15 6y agoAny good guides on how to get started in Lisps, from a programming languages theory perspective?
- DonaldFisk 6y agoThere's Lisp In Small Pieces by Christian Queinnec (https://www.amazon.co.uk/Lisp-Small-Pieces-Christian-Queinnec/dp/0521545668 https://www.amazon.co.uk/Lisp-Small-Pieces-Christian-Queinne...), and if you want to look into CLOS in depth, there's The Art of the Metaobject Protocol by Kiczales, des Rivieres, and Bobrow (https://www.amazon.co.uk/Art-Metaobject-Protocol-MIT-Press/dp/0262610744/ https://www.amazon.co.uk/Art-Metaobject-Protocol-MIT-Press/d...). There's also a good older text, Anatomy of Lisp by John Allen (https://www.amazon.co.uk/Anatomy-LISP-McGraw-Hill-computer-science/dp/007001115X https://www.amazon.co.uk/Anatomy-LISP-McGraw-Hill-computer-s...).
- fiddlerwoaroof 6y agoI really liked Practical Common Lisp by Peter Seibel ( https://gigamonkeys.com/book/ https://gigamonkeys.com/book/ ) however, ignore the environment setup: the recommendations it makes are no longer maintained, these days Portacle is the best way to get started. One thing I really like about this book is it assumes you know basic programming ideas, so it gets into distinctively “lispy” features relatively quickly. The chapters on exception handling and Common Lisp’s object system, in particular, really sort of blew my mind and had a fairly profound influence on the way I think about programming languages.
- fiddlerwoaroof 6y agoHmm, maybe this isn’t the best for PLT: for that, I’d recommend the Art of the Metaobject Protocol which is a really interesting case study in the design of the implementation of a fairly complex part of the CL standard.
- susam 6y ago> I really liked Practical Common Lisp by Peter Seibel ( https://gigamonkeys.com/book/ https://gigamonkeys.com/book/ ) however, ignore the environment setup: the recommendations it makes are no longer maintained, these days Portacle is the best way to get started. A bunch of us from Freenode IRC have formed Common Lisp Programming Challenge (CLPC) at https://github.com/spxy/clpc https://github.com/spxy/clpc in order to help beginners get started with Common Lisp (CL) while learning the language from Practical Common Lisp by Peter Seibel. The outdated environment setup in the book can indeed be a genuine hurdle for a beginner. Portacle is a great way to get started. In the CLPC repository though, we are documenting the steps to set up Emacs, SLIME, etc. from scratch, so that a beginner to the CL ecosystem can try out and understand the traditional way of installing and setting up these tools. If anyone here comes across this comment and is already reading or about to start reading the book Practical Common Lisp, or is eager to learn Common Lisp, you are welcome to visit https://github.com/spxy/clpc https://github.com/spxy/clpc and join the Common Lisp Programming Challenge.
- ashton314 6y agoI'm curious as to why they didn't mention Racket—perhaps they've just never heard of it. My first programming language was Perl. After Perl came a little bit of C, but then I soon switched to Common Lisp. I wrote a lot of Common Lisp: I programed a text-based adventure game engine ala Zork entirely in CL! After reading Paul Graham's On Lisp and learning about Scheme, I took a look. My dad got me a PDF of SICP; I learned to prefer the Lisp-1 style of Scheme to the Lisp-2 style of CL. I've done a bit of Clojure—I feel like Clojure does a better job of making data structures more ergonomic than either Scheme or CL. I've recently started working more in Racket and I am loving it. It feels like a Scheme with a more visible, vibrant ecosystem. (Could just be me not being aware of the Scheme ecosystem—I was only 15 or so at the time I started writing Scheme.) Racket is definitely optimized for building DSLs. But I feel like the standard library is a bit better documented and easier to work with. Just my experience though. I could be totally missing out on some great Scheme libs. At the end of the day, Lisp in all its flavors is great, and I want to write as much of it as I can in my career.
- mumblemumble 6y agoFWIW, my first lisp was one called PLT Scheme. Most people know it as Racket nowadays. There's been a couple decades' worth of divergent evolution since then, so that it's not actually compatible with any Scheme standard anymore. At least not by default -- there's still "#lang r5rs". In any case, one could be forgiven for thinking Racket is still just another flavor of Scheme.
- peatmoss 6y agoI agree about Racket. While various lisps occupy specific niches, I feel like Racket is the lisp that checks the most boxes—especially for someone getting started and shopping around for the “right” lisp.
- submeta 6y agoThat was a wonderful comparison. Thank you. - I had some contact with Scheme twenty years ago, while working through SICP. As I recently made a deep dive into Emacs and Emacs Lisp, I started looking into Common Lisp as well. - I absolutely love programming in Lisp. And like you, Scheme‘s clean naming convention (`set!` for destructive operations, `foo->bar` for conversions and `string?`) were something I missed in other languages in the years to come (when I started learning Python was irritated that `data.sort()` was a destructive operation). Scheme‘s spec is so short, I could keep it all in my head. Lambda calculus, list manipulation, list operations, closures, these are concepts I learned twenty years ago learning Scheme, and I‘ve seen these concepts slowly be adopted in other popular languages decades later. Thank you for catching my interest in Scheme again! Will look into that in more detail. Was an old love of mine anyway. :)
- iainctduncan 6y agoIf you're looking for a Scheme with a very active community these days a and production oriented packages, Chicken is a strong choice.
- submeta 6y agoMy (not well researched) understanding was that Racket is a popular Scheme variant. But thanks for pointing towards Chicken Scheme.
- iainctduncan 6y agoRacket is great, and is now able to run on Chez Scheme as the backend. But as far as using it for production code, it's a bit problematic as the folks in charge are focused on it as a research and education tool first and foremost, meaning they are not shy about changing things a lot. Chicken compiles down to C and has a really friendly community with great docs and examples for "real world cases"
- lenkite 6y agoI tried scheme, but I couldn't live without a hashmap in the language. Thankfully, clojure specifies one as well as a uniform `seq` interface for collections. The big problem is Clojure is a language without a published standard.
- greenkey 6y ago> That said, Common Lisp is weird. What I find particularly jarring is that functions and variables live in different namespaces: if you put a function into a variable, you can’t just use it like a function, you have to funcall it. Unless I’m misunderstanding, the author sounds like a developer that’s primarily used JS. It’s really not abnormal to have to include parens after a method name in a language, which indicating that you are calling a function.
- blockmeifyoucan 6y agoI think you are misunderstanding. In common Lisp you can call a regular function defined with defun as (foo "something"), but if bar is a variable containing a fuction you have to use (funcall bar " something"). I agree that this is weird and confusing.
- kame3d 6y agoIsn't that the same thing as using function pointers in C? You need the * to access the function the variable points to.
- eigenspace 6y agoSure, this isn't that rare of a thing for languages, but it is increasingly rare to find people who think this is a good idea.
- oalae5niMiel7qu 6y agoNo you don't. You call the pointer itself. It points to the first instruction in the function. It's more like Ruby's method(:foo) and .call().
- shakow 6y ago> It’s really not abnormal to have to include parens after a method name in a language That's not what he means. Assuming some pseudocode with a more common syntax to prune the parentheses question, Common lisp is doing this: function f(x) { print(x) } let a = f funcall(a)(27) # prints 27 Whereas Scheme is doing this: function f(x) { print(x) } let a = f a(27) # also prints 27 This is the fundamental difference between so-called Lisp-1 and Lisp-2 families, depending on whether functions and variable share the same namespace or if they have to be “lifted” from one to another through funcall.
- dunefox 6y ago> Clojure isn’t a true Lisp, or well, it is part of the Lisp family, but its extra syntax. Its ability to interface with the JVM makes it easy to leverage the thousands of JVM libraries out there. Doesn't ABCL let you do the same?