10 ms·
Differences with other Lisps
- rawoke083600 5y agoI know there are some very good projects out there, but if I could "wish" any software into existence: It would be nice to have an "enterprise-level" LISP-To-GoLang environment WITH a massive library of course. There is just something nice about the Go-Lang eco-system and compiling to static binary, not too many XML/JVM magic.
- pjmlp 5y agoIt is replaced by //go:generate, interface{} and struct tags magic.
- remontoire 5y ago> There is more to collections than lists. You can have instances of empty collections, some of which have literal support ([], {}, and ()). Thus there can be no sentinel empty collection value. Probably my favorite feature over common lisp. Combined with comma (,) being treated as whitespace (ie, use comma if you want to but you don't have to), makes typing out data structures in clojure a much more enjoyable process than other languages. This ease of typing out data structures also extends to edn (clojure's version of json)
- fiddlerwoaroof 5y agoThis isn’t really a thing, though: Common Lisp has built-in literal syntax for n-dimensional arrays and structs and libraries like fset provide literal syntax for Clojure-style immutable data structures.
- kgwxd 5y agoImmutability by default is a world of difference from library support. I think pretty much every language has a library for it.
- fiddlerwoaroof 5y agoImmutability by default is mostly overrated: I’ve written code in many languages (Haskell, Clojure, JS, CL, etc.), and I’ve found I care more whether a library (Immer, ramda, etc.) provides referentially transparent APIs than whether or not the language’s data-structures provide immutability guarantees. But, additionally, my point was that CL has literal representations for arbitrary data types, not that you can get immutable datastructures from a library.
- deleted 5y ago[deleted]
- remontoire 5y agoI've used fset and cl21. The problem is that once you start using those you no longer are able to use libraries. Data structures have to be built into core. The common lisp community has rejected reader macros for interop reasons the last time I checked (in the case of cl21) Even the docs for fset doesn't show the use of data literals. it does things like (set) and (isetq s2 (set 'c 1 "foo" 'a 'c)) This pretty much proves my point. it's not fun typing (set 'c 1 "foo" 'a 'c) instead of #{'c 1 "foo" 'a 'c}. It's also not possible to put those on the wire (easily) for communication between common lisp processes. Breaking the whole point of homoiconicity.
- fiddlerwoaroof 5y ago> once you start using those you no longer are able to use libraries This isn't true: if the libraries you use are designed to use generic functions for their internals, rather than normal functions. I've written code using custom data structures heavily, with little or no impact on which libraries I could use. > The common lisp community has rejected reader macros cl21 is just confusing matters here. Plenty of code uses named-readtables to use arbitrary reader macros. I don't understand the "interop reasons" you're talking about: as long as you use named-readtables, interop basically Just Works. > It's also not possible to put those on the wire (easily) for communication between common lisp processes. Breaking the whole point of homoiconicity. Using the reader on untrusted input is a bad idea in either Common Lisp or Clojure, because both readers can execute arbitrary code. However, there are packages like safe-read ( https://github.com/phoe/safe-read https://github.com/phoe/safe-read ) and Eclector ( https://github.com/s-expressionists/eclector https://github.com/s-expressionists/eclector ) that let you solve this problem pretty trivially in a safe way. Not to mention projects like my cl-edn ( https://github.com/fiddlerwoaroof/cl-edn https://github.com/fiddlerwoaroof/cl-edn ).
- deleted 5y ago[deleted]
- remontoire 5y agoIt looks like you're right for the most part. Literals are supported if you use https://github.com/vseloved/rutils https://github.com/vseloved/rutils. If your cl-edn actually works then a combo of rutils and cl-edn could bring most of the value I found in clojure to common lisp.
- gumby 5y agoI like this list. I don’t agree with every choice but so what: they are all thoughtful choices (except why do you need `recur`?) that reflect an opinionated position which I appreciate.
- kgwxd 5y agoI believe it was due to limitations of the JVM at the time. Edit: https://www.windley.com/archives/2008/11/tail_optimized_mutual_recursion_in_clojure.shtml https://www.windley.com/archives/2008/11/tail_optimized_mutu...
- erik_seaberg 5y agoI prefer Scala’s solution, where tail calls look like normal calls, and a @tailrec annotation can assert they really are optimized out (or break the build).
- gumby 5y agoSeems like they compiler could generate the trampoline itself and just ignore any recur that occurs.
- the-alchemist 5y agoThe upside of `recur` is that: * just by looking at the code you can tell if it's a tail call or not * easy to debug; no trampoline magic * guaranteed to work on any platform, whether it supports TCO or not * Javascript is a very popular target, via ClojureScript * who wants to test and remember if Chrome or Firefox or Safari implement TCO? or implement it properly? and which version(s) of those browsers implement TCO properly? * if you wanna want a trampoline, you got it! (https://clojuredocs.org/clojure.core/trampoline https://clojuredocs.org/clojure.core/trampoline)
- ngcc_hk 5y agoNever been able to install in macOS is one of the difference.
- NoahTheDuke 5y agoYou mean you struggle to install Clojure on a Mac? Clojure maintains a tap with Homebrew: `brew install clojure/tools/clojure` Leiningen should also have one but I don’t have that link on hand.
- deleted 5y ago[deleted]
- cutler 5y agoThe Linux shell script on the downloads page works fine with a few minor modifications.
- delish 5y agoIs clojure the newest popular-language-you-can-get-a-job-in? It's initial release was 2007. Rust (2010) (edit Kotlin (2011) perhaps), but point being there aren't many newer: https://en.wikipedia.org/wiki/Timeline_of_programming_languages https://en.wikipedia.org/wiki/Timeline_of_programming_langua... That metric is subjective and arbitrary, but it's on my mind because my company is hiring for clojure developers (see my immediate comment history & apologies for the advertisement). And it's on my mind because common lisp and scheme are _old_. One of the nicer things about clojure is relatively frequent mentions of how common lisp did things, then a choice to hew or differ. And common lisp and the lisp family of languages have a long history. I like this as an art-piece of lisp's age: http://kazimirmajorinc.com/Documents/Lisp-code-typography/index.html http://kazimirmajorinc.com/Documents/Lisp-code-typography/in...
- deleted 5y ago[deleted]
- unmole 5y agoGo came out in 2009.
- thurn 5y agoSwift (2014) would be a strong contender
- staplung 5y agoGo (2009), TypeScript (2012), Julia (2012) and Swift (2014) are all contenders
- rawoke083600 5y agoPHP(2005..n) for when you fail the interview for the above "fancy lang" at FAANG :P PHP is like the backup-plan(welder,lawyer etc) your parents wanted you to have before going out on the road with your band and making it big :D /mostly-sarcasm - but a little true ?
- pjmlp 5y ago
- staplung 5y agoIn many ways I feel like Clojure is a better Lisp than Lisp itself. Syntactic niceties like support for vectors/maps/sets are, once you've gotten used to them, hard to do without. And although it's orthogonal to the syntax, I also appreciate its focus on immutability. I just with there was a Lisp like it that didn't run on the JVM.
- subderisorious 5y agoLike ClojureScript?
- naruhodo 5y ago> I just with there was a Lisp like it that didn't run on the JVM. There are a few, with varying degrees of distance from the JVM and varying degrees of similarity to Clojure. - There's ClojureScript, which is Clojure transpiled to JavaScript. - See also Lumo (<https://github.com/anmonteiro/lumo>) and Planck (<https://planck-repl.org/guide-all.html>) - There's Babashka (https://github.com/babashka/babashka https://github.com/babashka/babashka), which is a natively-compiled Clojure interpreter, implemented with the Small Clojure Interpreter (https://github.com/babashka/sci https://github.com/babashka/sci) and GraalVM for native compilation. - There's Joker (https://github.com/candid82/joker https://github.com/candid82/joker) with a similar mission to Babashka, but commonly used as a linter. - There's ClojureCLR (https://groups.google.com/g/clojure-clr https://groups.google.com/g/clojure-clr) on the Common Language Runtime. - There's Cloture (https://github.com/ruricolist/cloture https://github.com/ruricolist/cloture), which is Clojure in Common Lisp. - There's Clojerl (https://www.clojerl.org/ https://www.clojerl.org/), which is Clojure for the Erlang VM. - There's Pixie (https://blog.goodstuff.im/pixie https://blog.goodstuff.im/pixie), with Clojure syntax, but compiling to native. - There's Ferret (<https://github.com/nakkaya/ferret https://github.com/nakkaya/ferret>) which is Clojure transpiled to C++11. - There are some Lisps that have borrowed Clojure's syntax: - Janet <https://janet-lang.org/> - Carp <https://github.com/carp-lang/Carp> There are a variety of other Lisp-like languages listed here: https://github.com/dundalek/awesome-lisp-languages https://github.com/dundalek/awesome-lisp-languages Apologies for the formatting.
- Zababa 5y ago
- User23 5y agoThe main advantage Clojure has over Common Lisp is that it’s considerably easier to sneak into production at BigCorp thanks to being JVM hosted.
- restlessbytes 5y agoReplace "main advantage" with "one major advantage" and I'll 100% agree!
- rawoke083600 5y agoMaybe a more seasoned LISP-`aterian` can answer me ? I'm in the process of learning ClojureScript - real fun so far. I have of course also looked at other LISPs and have noticed that in CJS the use of square brackets[] for vectors, let and `function params` (defn myfunc [] (let [some-var (:some-key some-state)]) (.log js/console some-var) ) I almost never see square brackets in other LISPs (yes I'm truly a beginner and haven't looked too hard), but it stiked me as odd ? The square bracket syntax really helps to differentiate and with reading the syntax. (The syntax is not bad it is just different than what most programmers are use to) Am I wrong or just stupid or is there another reason most other LISP doesn't follow this "convention"? Again I'm super-newbie, just something that jumped out at me.
- linguae 5y agoRacket also optionally supports a square bracket syntax for cons clauses. For example, in traditional Scheme one would write: ; this is in R5RS Scheme (define (length elems) (cond ((null? elems) 0) (else (+ 1 (length (cdr elems)))))) But in Racket one would write: ; this is in Racket (define (length elems) (cond [(empty? elems) 0] [else (+ 1 (length (rest elems)))])) It is also used in let/let*/letrec bindings in Racket; see https://docs.racket-lang.org/guide/syntax-overview.html#%28part._.Conditionals_with_if__and__or__and_cond%29 https://docs.racket-lang.org/guide/syntax-overview.html#%28p.... I don't know the origins of when brackets started appearing in Lisps. I don't remember seeing brackets in the LISP 1.5 Programmers Manual when using S-expressions (though brackets are a core part of M-expression syntax, which LISP 1.5 still supported), and I haven't encountered brackets in Common Lisp.
- rawoke083600 5y agoInteresting ! Thank you for the examples. Yes Racket is also on my someday-soon-list !
- tralarpa 5y ago> It is also used in let/let*/letrec bindings in Racket I suppose this is just a personal choice of the author of the manual, right? Please correct me if I am wrong but I thought Racket doesn't care whether you use brackets, parentheses, or even curly brackets.
- lispm 5y agoThe bigger picture: Clojure was designed with no backwar(d/t)s compatibility. https://clojure.org/about/rationale#_lisp_is_a_good_thing https://clojure.org/about/rationale#_lisp_is_a_good_thing > Clojure is a Lisp not constrained by backwards compatibility Which means that basically no (!) Lisp software from the past ran in Clojure and trying to make it results in a re-implementation and re-architecture of that software.
- kaba0 5y agoSo the 3 lisp programs will be missed.. Sarcasm aside, seeing the resulting popularity of Clojure, I don’t think at all that this tradedoff was not worthy. Depending on Java/Js’s much much richer ecosystem is a win.
- capableweb 5y ago> Clojure was designed with no backwar(d/t)s compatibility Correction: Clojure was designed with no backwards compatibility with previous lisps Clojure puts a huge focus on being backwards compatible within it's own ecosystem. I've used libraries that haven't been updated in ages (think Clojure 1.3) but still works the same way as they did back then. This is also reflected in the community where libraries are very careful of breaking the public API, often creating new libraries under new names if there are breaking changes.
- lispm 5y ago> Clojure puts a huge focus on being backwards compatible within it's own ecosystem Like lots of languages. Incl. Lisp itself. For example the Maxima computer algebra system written in Lisp has been started >50 years ago (as Macsyma) and still is being worked on. https://maxima.sourceforge.io https://maxima.sourceforge.io The current build system ASDF works in Lisp implementations which date back to the mid-70s... https://common-lisp.net/project/asdf/#implementations https://common-lisp.net/project/asdf/#implementations
- capableweb 5y ago> Like lots of languages. Incl. Lisp itself. Sure, I'm just highlighting that your statement about Clojure is correct when it comes to compatibility against other languages while being incorrect if you consider it within the Clojure ecosystem itself.
- slgeorge 5y agoI've been messing with Clojure/ClojureScript for a few years having previously had zero Lisp experience. Overall, I think Clojure does a good job of being both practical and lispy. It's a language that is for building real things. I've been focusing on ClojureScript (https://clojurescript.org/ https://clojurescript.org/) as you get the benefit of interoperating with the Javascript ecosystem. The fact that there's a strong community around both Javascript hosted and Java hosted gives a wealth of library options. Overall, the tooling has been getting a lot closer to the sort of experience that contemporary developers expect. The Calva plugins integration with Visual Studio (https://calva.io/ https://calva.io/) makes it easy to get started - you can even run it online with gitpod (https://github.com/PEZ/rich4clojure https://github.com/PEZ/rich4clojure). That just leaves learning the language - the slight changes in syntax (brackets for different data types) definitely help early on, and for the most part Clojure discourages people going down the path of macros which means reading other peoples code is reasonably accessible. The main struggle is that it's a language used by a lot of advanced or full-time developers, so documentation is pretty dense and it can take a real commitment to understand the detail. It may not be 'correct' enough if you're coming from other Lisps, but coming the other way from C/Python etc I've found it an accessible and practical option.
- sp33der89 5y agoI've read that Clojure(Script) has a great REPL experience. Even when using VSCode, can one use the REPL easily?
- jffry 5y agoYes, it looks like Calva has first-class support for launching REPLs from your project, or for attaching itself to a REPL session that was launched in some other way: https://calva.io/connect/ https://calva.io/connect/
- LandR 5y agoYes, you can. It's all pretty seamless with Calva & VS Code.
- mfru 5y ago
- moomin 5y agoThe difficulty with these lists is they always have huge blind spots. For instance, any scheme user would reasonably want to know if macros were hygienic.
- m45t3r 5y agoThey're not hygienic, but the usage of auto-gemsyms on quasi-quote and the fact that symbols are automatically expanded to their namespaced forms solves most of the problems that unhygienic macros have: http://clojure-doc.org/articles/language/macros.html#macro-hygiene-and-gensym http://clojure-doc.org/articles/language/macros.html#macro-h...
- finder83 5y agoAll of the features mentioned seemed to be in favor of Clojure, like it doesn't mention the lack of CLOS and conditions/restarts, which were both major eye openers for me in learning Common Lisp. Just a personal point, I much prefer macros in CL as well. There are parts of Clojure I like, such as the data structures and de-structuring. Maybe it was primarily the JVM, but I just couldn't get into Clojure...it doesn't give the same feeling as working in CL. I really wanted to like it though. I do wish that someone would take some of the modern data structure ideas and backport them to Common Lisp (as a new lisp obviously). The historical cruft in lisp and lack a strong modern standard library are major reasons I don't play with it day-to-day.
- dmux 5y agoI've only just started learning Common Lisp and never used Clojure, but what are the implications or trade-offs of >Symbols are not storage locations (see Var) I thought the way symbols worked in CL are one of the three big ideas (s-exps and macros being the other two).
- Jach 5y agoThere's two main aspects to the claim. The first is Clojure's general stance against "place-oriented programming" that ties in with its immutable-by-default data structures. A good talk is https://github.com/matthiasn/talk-transcripts/blob/master/Hickey_Rich/ValueOfValues.md https://github.com/matthiasn/talk-transcripts/blob/master/Hi... The second is more specific. In Clojure, symbols are just names. When the compiler encounters a symbol, and it's not a special java kind or a local, it'll try to lookup that symbol in a Namespace map, and return a Var. The Var is where the storage is, the symbol is just a name to find it. Re-def'ing the symbol doesn't change anything about the old Var, it just associates the symbol with a new Var. In CL though, symbols are themselves objects that have attributes (http://www.lispworks.com/documentation/HyperSpec/Body/t_symbol.htm http://www.lispworks.com/documentation/HyperSpec/Body/t_symb...) which store data. If you (inspect 'a) you'll see it has a string name, package, and an empty value, function, and plist. When you (defparameter a 8) and inspect 'a again, you'll see it has a value attribute of 8. You can then (defun a ()) and inspect again, and see both the value and function attributes are set. Of course CL is a Lisp-2. Part of Clojure symbols being just names, means they aren't owned by any namespace. If you have three namespaces with functions that return 'x, they will all be value-equal to each other. Clojure symbols can be namespace-qualified, like 'some-ns/x, but that just restricts the lookup, the namespace doesn't own such a symbol. You can even make such a symbol without having defined the namespace some-ns first. In CL by contrast, if you create three functions in three different packages returning 'x, they will not be value-equal. And if you try to reference a symbol in 'some-package:x when the package doesn't exist, you'll get an error. Clojure symbols are not storage-equal though: (identical? 'x 'x) is false. In CL, in the same package, (eq 'a 'a) is true. Some consequences: another feature is that Clojure's syntax-quote/quasi-quote ` for macros will automatically bring in the symbol's full namespace, e.g. if you (ns a) and quote 'inc or 'a you'll get inc and a back, but if you syntax-quote `inc and `a you'll get back clojure.core/inc and a/a respectively. This helps reduce the chance of name collisions. Another consequence is that since symbols don't belong to namespaces in Clojure, you don't have to worry about a CL behavior of polluting your package's namespace with a bunch of symbols. (i.e. in CL when you switch to package a and type 'a, you just interned the symbol a in that package.) And another consequence is that if you make a function private in Clojure, you can't get at it with the symbol name from outside of the namespace, whereas in CL, if you don't export something from your package (making it "private"), you can still get at it outside with package::symbol.