31 ms·
Racket – Lisp beyond Clojure
- noobermin 10y agoI'd think Common Lisp is the Lisp beyond Clojure. Also, I just see slides that have (googleable) terms, is there a recording of this presentation? EDIT: see mkozlows' comment (THANKS!!!)
- duaneb 10y agoWho said there was only one?
- macco 10y agoI think, it is more of a timeline, than what is better/more powerful.
- mkozlows 10y agoUI is weird. Left/right goes between main topics, up/down goes through the slides on that topic. So if you just go right, right, right, you're only seeing the headings.
- daveloyall 10y agoOver here in Firefox 52.0a1, something is cut off the margin of the slides.. all of them. I can briefly see the cut-off part when flipping to the next slide (vertically or horizontally).
- daveloyall 10y agoSwitching to fullscreen fixes it...
- aaronchall 10y agoUse the n and p keys for next and previous respectively. Use the ? key for the help and other useful keybindings.
- JohnStrange 10y agoI tried to get more into CL because of implementations like SBCL and because it's standardized, but modularization/package management turned out to be too verbose and archaic for my taste. In Racket, by default a file creates a module, I import things, export stuff and done. That's really very handy, because I hate fiddling around with package declarations and paths -- these are a pain in the ass in almost every older language.
- lispm 10y agoThat's not very Lisp-like. Personally I really don't like it when files are modules. For me that's orthogonal.
- kazinator 10y agoIn Common Lisp, files are in fact "modules" (or "compilation units") also. To treat multiple files as one unit, you have to use the with-compilation-unit macro: http://clhs.lisp.se/Body/m_w_comp.htm http://clhs.lisp.se/Body/m_w_comp.htm The packaging systems people use nowadays over CL are not a part of CL. The whatever subjective suckage they introduce is their own. If you want racket-style modules, hack them up. The grandparent's observation that "modularization/package management turned out to be too verbose and archaic for my taste" is very ironic --- in particular, the "archaic" part. ASDF is from around the turn of the century (the 21st that is). The big hurdle in CL modularization is something very trivial: the fact that a file cannot refer to neighboring files easily by a short path. There is no (load "foo") which will look for a "foo" in the same directory as the file which is invoking the load form. This steers package management toward the external mode, whereby some definition exists outside of all the files and handles their inter-dependencies and the manner of actually locating the groups of files. I fixed this in TXR Lisp, and so simple modularization is a cinch! You load some main file, and that just does (load "foo") (load "bar") ... to load its related files, no matter where they have been located. I made load a macro, and that macro accesses the source file location at macro-expansion time, imbuing it into the resulting form that actually does the loading when evaluated. If the load path is relative, then the caller's path is used to resolve it, rather than the current working directory.
- imagist 10y agoTBH, almost any Lisp is beyond Clojure. Don't get me wrong, Clojure is an amazing tool. While it addresses a very specific use case (functional programming on the JVM) that use case is common enough that it's a very useful tool. But when compared to other Lisps in a context where non-JVM toolsets are acceptable, Clojure leaves a lot to be desired.
- dasmoth 10y agoCan you be more specific? In particular, about stuff you'd consider to be lacking in Clojure?
- armitron 10y agoConditions and restarts, read macros, interactive debugging, native code compilation, extremely easy interface with C, intrinsics, compiler macros, full control of code generation, built-in disassembler and so on and so forth. Clojure is ok if all you're doing is based on the JVM. If that's not the case, then it simply doesn't exist.
- phyrex 10y agoYou're just saying 'Clojure isn't as good as CL because it's not CL'. When one of the the biggest selling point is "it works seamlessly on the JVM" it's a bit disingenuous to say "it's not as good as CL because it doesn't have a good C interface".
- ska 10y agoThe c interface is a bit silly, but the rest of the points are pretty good. Clojure is a reasonable lisp-on-the-JVM, but lacks some of the really good things about lisps.
- junke 10y agoYou could use JNA (Java Native Access) with Clojure[0], exactly like ABCL does with the CFFI library. [0] https://nakkaya.com/2009/11/16/java-native-access-from-clojure/ https://nakkaya.com/2009/11/16/java-native-access-from-cloju...
- 616c 10y agoI have been trying to get into the whole Lisp paradigm for 1-2 years now. I own Realm of Racket, amongst a collection of Lisp books. Racket is all the promise of developer-centric power tooling that puts Common Lisp to shame. I recommend you watch one of the core devs, Matt Flath, build a a hygenic macro expander. https://www.youtube.com/watch?v=Or_yKiI3Ha4 https://www.youtube.com/watch?v=Or_yKiI3Ha4 Notice how his talk, likely written in its own documentation language Scribble, shows demos of DrRacket. I am more of an emacs guy, but do you see the interactive colorized debugger pointing out variable binding and flow control? That is the only thing that I have seen in the Lisp world that takes SLIME and laughs at its dogged simplicity. Also, as you watch this talk, observe how he takes the complexity of something I am still certain I cannot do, build a macro system (let alone understand macros others write), and boils it down to the essence with the color-coded schematic to match his environment and visualize his thought process. I dare say Rich Hickey et al would be impressed, tipping the hat to the Simple or Easy talk he is famous for. If I have bored you at this point, you will probably not check out Rackjure. Someone basically implemented a language subset in Racket of Clojure. So it is safe to say you can subsume Clojure with Racket. I know we are all smug Lisp weenies, but the whole Brown/NEU PLT group who works on Racket deserve serious praise. I listen to all the core devs and watch their talks, because they push the boundaries of what a good computer scientist is. They just happened to choose Scheme/Lisp to make me feel dumb. Watch them ditch it and go for Haskell. We will all be sorry then.
- pjmlp 10y ago> Racket is all the promise of developer-centric power tooling that puts Common Lisp to shame. Have you ever used a commercial Common Lisp like Allegro ?
- nickpsecurity 10y agoWe cant entirely blame them: those cost significant money while mainstream stuff usually has free IDE's that are good without limitations. Allegro even mentioned royalties last time I looked at them. Royalties!? Only natural hobbyists overlook this. But, yes, LispWorks and Allegro are very powerful environments. Comparing AllegroCache to Hibernate might be fun for newcomers too. Haha.
- chriswarbo 10y agoI've recently started porting some bash scripts over to Racket, using https://docs.racket-lang.org/shell-pipeline https://docs.racket-lang.org/shell-pipeline and it's been pretty straightforward and painless so far!
- jonathonf 10y agoAre there (m)any advantages to doing this? I've seen a number of shell-interop modules for various languages but they all appear to add an extra layer that reduces portability or ease of maintenance.
- jlg23 10y ago> Are there (m)any advantages to doing this? [trigger warning: cynicism distilled from 15+ years of bitter tears] More fun and better job security for the current maintainer. The former because one hacks away in the preferred language, the latter because one cannot be replaced easily by some unix geek unless s/he happens to speak the same language fluently. One can chose from various implementations in various languages (eg: psh and scsh) but hacking your own is easy: * Just re-implement the basic unix tools and shell semantics and invent some nifty convenience syntax and features along the way. * Either don't document at all or document everything with at least 2 pages aimed at people who have never used a computer before. Both ways will prevent the only ones who could replace you from even looking at your "shell in X". * Never ever do this in a typed language, write a ton of unit-, functional- and integration tests to make up for that - of course all of them completely undocumented. * On top of your creation, invent a fragile "shell syntax like" layer to make adoption easier. * Under no circumstances create some new abstraction layer that goes beyond shell semantics that brings something substantial to the table and is well documented. * Enjoy the time saved because you don't have to "man $tool" anymore, it's all your code anway. * Under no circumstances ever write in pure posix sh again - the realization that with all the stuff you've learned along the way posix sh covers 99% of the use-cases in a more expressive way will be crushing.
- SwellJoe 10y ago
- junke 10y agoLet's try with other languages: Rust - C beyond Go See any problem?
- mkozlows 10y agoLisp is a language family. It'd be more like "F#: ML beyond SML" or something.
- imagist 10y agoLisp is a family of languages that includes Racket and Clojure. C is a language, not a family of languages that includes Rust and Go. The Lisp family of languages also contains Common Lisp. In some contexts, it's reasonable to assume "Lisp" means "Common Lisp". This is not one of those contexts.
- junke 10y agoNewcomers are always confused by the distinction, this doesn't help at all to put them in the same big bag. This classification is not wrong, but mostly useless when you see how the different "dialects" evolved (they are grown-up languages, nowadays). > C is a language, not a family of languages that includes Rust and Go. But Rust and Go are constantly compared to C. We always talk about C-like languages. Maybe I should have said "Algol" instead, but there is a family of languages rooted at "C", and we don't call it the C family. Go is "a compiled, statically typed language in the tradition of Algol and C". "The syntax of Rust is similar to C and C++", but "Rust is semantically very different from C and C++.[citation needed]" (wikipedia). Likewise, Scheme is semantically very different from Common Lisp. And Racket is not considered as a Scheme, even though it is related to it. You can't copy-paste any Typed-Racket expression and run it with ChezScheme. So, yes, they all belong to the same proto-language family, but constantly referring to them as a unique family is doing a disservice to each of them. Take Clojure for example: the wikipedia page says that it is inspired by C++, C#, Common Lisp, Erlang, Haskell, Mathematica, ML, Prolog, Scheme, Java, Racket and Ruby. There are plenty of influences that goes into a language, why not talk about the other ones? parentheses?
- 10y ago
- DigitalJack 10y agoI find DSLs to be extraordinarily powerful for writing and working with my own programs. I find them painful when I'm trying to work with other people's programs. Making a DSL lets me construct a language to express my program that meshes with the way I think. Unfortunately, we all think differently, and what is intuitive and friendly for me is hostile and awkward for others. While reading someone else's program that uses a DSL may be superficially easy, but the minute you try to get under the surface, you're left scrambling to understand what a given term or idea meant to the author. There is no language definition to rely on for common understanding. There are exceptions naturally. I know a lot of people will disagree, and that's fine of course. It's opinions all the way down.
- kd0amg 10y agoWhile reading someone else's program that uses a DSL may be superficially easy, but the minute you try to get under the surface, you're left scrambling to understand what a given term or idea meant to the author. There is no language definition to rely on for common understanding. I have generally found that this is the same problem as with user-defined functions, and it has the same solution: programmers need to document their code.
- treehau5 10y agoAlso be consistent with their grammar, naming schemes, and conventions.
- brandonbloom 10y agoAgreed. I have two follow up thoughts: 1. Badly designed functions can do less design damage per-function than badly designed languages per construct, but user-defined functions tend to have much higher volume than both language constructs and their usages. 2. Powerful techniques, including DSLs, lead to denser code. Denser code takes more time to read per unit of code. Total reading time may be either more or less, but the cold start ramp is always much steeper. Combined, this means that people are less sensitive to suffering the complexity caused by user-defined functions vs DSLs/etc because that complexity has lower intensity spread out over a greater area. I'll refrain from any further value judgement on this state of affairs; just wanted to share some more insights in to the tradeoffs.
- dasmoth 10y agoThis is addressing a question I'm interested in, but on first read I'm struggling to see the value that's being presented here. - "parameterize" is great, but seems exactly the same as Clojure's "binding" on a dynamic variable. [Edit: modulo being "sticky" with regard to continuations... but Clojure doesn't have continuations, so it's a pretty subtle difference.] - Reader macros are an interesting feature, but do move away from the syntactic regularity of LISP -- and were, AFAIK, explicitly rejected in Clojure - Custodians are kind-of interesting -- but I ended up having to do some Googling [1] to find out exactly what they do... Is there anywhere else I should be looking for a more systematic Racket/Clojure comparison? [1] - https://docs.racket-lang.org/reference/eval-model.html#%28part._custodian-model%29 https://docs.racket-lang.org/reference/eval-model.html#%28pa...
- shakna 10y agoThe place where I've found Racket to shine is the reader macros. More specifically, a project can be broken up to be expressed in a way that makes sense, using what looks like, on the surface, multiple languages. Most of what I have done in Racket used #lang racket for the core, and lazy or typed everywhere else. Contracts and laziness made debugging a breeze. Edit: My clumsy hand hit reply before I was done.
- pareidolia 10y ago> - Reader macros are an interesting feature, but do move away from the syntactic regularity of LISP -- and were, AFAIK, explicitly rejected in Clojure That does not make sense to me since clojure introduced explicit irregular syntax for things like maps and vectors. In Common Lisp the "we-the-language-developers can introduce special typography but the users cannot" thing, in constrast, doesn't exist .
- weavejester 10y agoThe majority of Clojure's special syntax is for data structures, and while Clojure doesn't have reader macros, it does have data readers.
- technomancy 10y ago
- edem 10y agoHow I am supposed to read the slides? Top to bottom, left to right? It is not intuitive.
- kd0amg 10y agoTop to bottom. The "top row" of slides are section headers. Go down from a section header to see the section. When you get to the bottom of a section, go right, and it will put you at the top of the next section.
- jnordwick 10y agoUnhappy with the current state of functional programming. I know I should't be. I have a lot of options. I went to school at UC Berkeley. My first language was Scheme. Then Elisp. CLOS was in the first few too. I really didn't learn C or C++ until second semester. A few months ago I had to pick up enough Scala to figure out what some code did in a project and I wasn't really happy with the language. I realize it is multi-paradigm, but the functional part just seems a little bolted on at times. The notation was clunky. Maybe it is because I prefer Lisp-ish and APL-ish languages. And the Scala docs aren't very friendly. I actually find it easier to write imperative code in Scala than functional code. Clojure seems nice, but lacks a lot of things that you kind of want in a LISP (proper tail rec). Racket has very little market pen. Maybe I'm just picky, but I don't see anything I really want to put time into.
- DigitalJack 10y agoI guess I don't understand what the big deal is with tail call optimization. Could someone give an example where it really shines and clojure's loop/recur just doesn't? If you are looking to put time into a programming language that is interesting in and of itself, I'd suggest Haskell.
- jnordwick 10y agoLooping is fine for imperative languages. It should be the norm for performance sensitive things since that is how the CPU works. It is just easier than trying to make a smart compiler turn your recursion into looping constructions. However, for functional languages you really want TCO to work properly so you can write your algorithms in a properly functional way. And you don't just want self-calls to work, but full mutual recursion (A calls B that calls A etc) to be properly optimized too.
- optforfon 10y agothe CPU is just doing a jump to an instruction at the end of each iteration. When you do tail call recursion you are doing just that. The assembly jumps to a tag and in recursion you jump to a function name, which is also effectively a tag. So it's not really about mapping better to the CPU instructions or anything like that The added benefit is that with tail call recursion you can have mutually recursive function (function A calls function B at the end and function B calls function A at the end), which isn't possible with a simple iterative loop, so the functional style is actually more powerful than an iterative approach and still maps directly to "the way the CPU works"
- qwertyuiop924 10y agoI'm not a fan of Racket, as I've made clear elsewhere. Its insistance on using as many paradigms as possible frustrates me, and while I like "batteries included" in general, I wish some things like contracts, custodians, OO system, etc. had been moved out to other libraries to make core easier to wrap your head around. I am also not a fan of syntax-case: it violates the macro abstraction, and is overly complex for what it does, IMHO. In essence, I wished that core had picked a paradigm and stuck with it, instead of like 10 of them. Practical or no, I'd take a simpler Scheme over Racket any day. Usually Chicken, which is quite practical, and has a lighting fast call/cc implementation (non-delimited, with delimited implemented in terms of call/cc by an external library, if you want it). But just because I don't like it doesn't mean you won't: objectively, it's powerful, technically competent, and fairly well designed. It's just not to my tastes, any more than CL is, and so it looks like I'll have to wait until R7RS Large before I get a large lisp I like. And yes, I said lisp, not scheme, because Scheme is a lisp, and also to annoy the people who say otherwise.
- mballantyne 10y agoCan you elaborate on how syntax-case "violates the macro abstraction", and maybe what you think is important about the quality it breaks? Not a description I've heard before. I do agree it is complicated!
- qwertyuiop924 10y agoThe macro abstraction is that the AST is exposed as a series of lists, which is what macros process. Instead, syntax-case exposes 'syntax' objects, which are entirely distinct from any other datatype, and kind of complicated. This isn't a horrific sin (new macro abstractions pop up like rabbits, although they rarely change something so fundamental, at least in Lisp mavro systems), but if you're going to replace an abstraction everybody knows and understands with a more complex one, you better have a good reason, and I don't think the benefits outweigh the costs.
- ufo 10y agoI thought that the syntax objects resulted in better error messages, due to keeping track of source code position, lexical bindings for variables and so on. Isn't that worth the complexity?
- avodonosov 10y agoI don't understand - is it just 8 slides? That's all?
- blandflakes 10y agoI don't understand why this slide format is popular, but I believe you go down until the end of that column, then right, then down again, then right, and so on.
- antfarm 10y agoOr just press space to go to the next slide.
- shiro 10y agoA kind of nitpick, but the use of dynamic-wind with custodian in the slides bothers me. Dynamic-wind shouldn't directly be used to ensure cleanup, since a continuation captured in the body may be invoked outside from dynamic-wind and the body restarts, even if resources are gone. In the R5RS age, light users looked for try-catch construct in Scheme and could only find dynamic-wind and used it; but they're not the same. Dynamic-wind is a low-level construct that can be used to implement try-catch idiom and other stuff. Now Scheme has guard, so it's better to use them to write cleanup stuff. It's a bit verbose, though (you have to write cleanup both in the handler and the end of body), so I personally wrote unwind-protect macro on top of it and am using it.
- raspasov 10y agoI really don't get the title of this. Why is it "beyond Clojure"? Maybe if we can see the actual talk it will be more clear.
- smnplk 10y agoClojure ideas are beyond Clojure.
- Ericson2314 10y agoI need types. But Racket has the world's greatest macro system and everybody should imitate it, Period.
- gus_massa 10y agoHave you tried Typed Racket? https://docs.racket-lang.org/ts-guide/ https://docs.racket-lang.org/ts-guide/
- Ericson2314 10y agoSomebody always asks :). 1) I want my libraries to be typed all the way down. 2) Improving the implementation of typed racket is harder/less likely than fixing the macro systems of Rust and Haskell. 3) Network effects of those two languages.