Racket Language
racket-lang.org
racket-lang.org
I don’t care for much of the programming language research parts of the ecosystem - that is the parts that the computer scientist professors who run the project probably care about the most. More power to them!
So I feel like a freeloader on the Racket project, just enjoying the little parts I like and ignoring the rest, and not contributing anything (except maybe the little Racket book I wrote).
edit: I dont reslly understand the downvotes, not trying to be rude or anything. Coming from CL the racket repl is very very barebones, it loses all state everytime you recompile. So I ask him how he deals with that coming from the very nice CL repl
You don't have to use DrRacket to use Racket.
People doing real work with Racket tend to have "workflow" setups that are closer to SLIME.
I personally used a simpler Emacs setup ("https://www.neilvandyke.org/quack/"), and ended up leaning more on modules and embedded unit tests ("https://www.neilvandyke.org/racket/overeasy/"), and less on very dynamic interactive evaluation like I'd done before.
Though, if you want to monkeypatch heavily, CL is famously good at that.
you can have a REPL in nvim/vim/tmux/screen/another terminal/or any other window , and send regions from your vim buffer to that repl
I have heard that this is not possible because Racket needs to make a stricgter separation of compile time and run time... but I am not sure whether this is actually true.
But, though I don't know current Racket internals, I'm not sure those need to be a barrier to monkeypatching that approaches CL.
Other than optimizations that make some debugging info and dynamic changes difficult-to-impossible, if the system had a mode to disable these optimizations (or to maintain some information in parallel that permits a cascading unraveling of optimizations affected by a change), I'm not aware of a fundamental reason the system couldn't support more loose poking at things.
Though, one implementation complication that Schemes do have is first-class continuations.
That said, IMO Clojure has a larger and more robust community, that said it's a bit of a bigger pain to set up (uses JVM) & has some more nuance.
What matters are ecosystems and not languages on their own, so when switching between languages it is a great benefit that I can reuse my Java ecosystem knowledge, instead of adding yet another ecosystem to those I jump around between projects.
However, I really like the almost Lisp Machine like experience from using Raket.
CLOS is way nicer than Racket's class/OO model and how generic functions are handled. Growable/resizable arrays are sometimes nice to have.
I prefer Racket and Scheme for the most part though.
I'd say this counts as a phenomenal contribution. :)
I return to my main calling: figuring out why people use PLT scheme without an academic incentive. There must be an answer here somewhere....
Are there any Schemes which are as "Batteries included" as Clojure with broad and deep library support? (I think Racket has quite good support!)
I'm always a bit skeptical of these statements. How does it define "native"? Does it use gtk/libadwaita on Gnome and Qt on KDE? What about windows, does it use Win32, WPF, WinUI2 or WinUI3, all of which could be considered "native"? What about platform-dependent layouts?
So, industry-grade customer-facing code? Not its focus, maybe not. But incredibly easy internal tools? Sure!
You mean it's easy to build GUI desktop apps with Racket?
I started trying to build a complex enough GUI and just quit. There are bugs and the documentation is extremely terse. You have to rely on blog posts by one developer who has sorted it all out, but it's still really difficult to get an explicit handle on the concepts and functionality. Very, very few people use the pasteboard editor for complex things or even simple things. You'll be forging a path of your own for sure.
The packet management system, the GUI IDE (which includes a step debugger), the ability to write a cross platform IDE (which is maintained by the core Racket team themselves), and the ability to easily produce runnable binaries make Racket my favorite Lisp hands down.
Those features are so incredibly useful and important, I really can't state it enough. I love Lisps, but at work, I will only use a language if it's the best tool for a job. Because of several of those features, Racket has been the only Lisp I've ever been able to justify using.
Because of the community, tooling and learning resources available, Racket is such an easy language for me personally to recommend to people. There are things I really like about CL and Clojure too, both of which I have used quite a bit, but I would never recommend them to people because of some huge drawbacks that come with each.
I also don't jive with the research parts of the language , nor do I care about the "lang" facilities, and I also kind of strongly dislike HtDP. But my perspective on all that is that they are projects I am uninterested in that happened to be made with a language I love, rather than knocks against the language itself, because I never bump up against them.
(Thank you for the book - will be reading)
The only part of the Racket distribution I can see that is specifically 'programming language research' is Redex.
In the language itself there are the metaprogramming capabilities - but all modern languages have metaprogramming.
My experience of the community is it is generally people talking about real problems.
People do use Racket for PL and other research, so a number of PL research papers and conference talks do reference Racket, but it doesn't dominate any of the discussion.
e.g. https://racket.discourse.group/t/levin-tree-search-with-cont...
When I personally want a binary with a native GUI I turn to Racket. It's also pretty nice for parsing stuff, like JSON, XML, some text-file formats.
The companion book How to design programs, https://htdp.org/2023-8-14/Book/index.html , is nice too, while it doesn't exactly teach Racket (it uses a couple of teaching languages implemented in Racket) it has some valuable ideas that are good to be reminded of every now and then.
The macro system might seem weird if one comes from e.g. CL, but once I got used to it I found it relatively easy to stay sane while doing metaprogramming.
A couple of more resources that are useful:
What I've used most over the years is his writing about GUI development.
https://defn.io/2019/06/17/racket-gui-saves/ helped me figure out some patterns I had trouble with and got me stuck in using Racket for this purpose in personal projects.
Later he added observables and threading logic, making it even nicer to build GUI, https://defn.io/2021/08/01/ann-gui-easy/ .
The core web development tools in Racket aren't exactly trivial to get started with until one is rather fluent with continuations so I've gained a lot from http-easy and Koyo, https://www.youtube.com/watch?v=DS_0-lqiSVs.
The docs seem to suggest that the user can explicitly decline to save backup files?
https://docs.racket-lang.org/drracket/drracket-files.html#(p...
Presumably offers can be declined?
"When DrRacket first starts up, itlooks to see if there are any backup files still present and if so, offers to restore the backup files"
https://blog.racket-lang.org/2009/03/the-drscheme-repl-isnt-...
That's a perfectly valid workflow for Racket too. Startup time is pretty comparable to Python in my experience. Slow but not cripplingly so, especially if you compile it ahead of time (useful when you're done working on a file for the moment). Using the racket/base #lang instead of racket makes a big difference too. https://docs.racket-lang.org/style/Language_and_Performance.... has more on that.
>But that means the code you are working on doesn't start with a "clean slate" and instead starts with whatever state the vm is in at the moment.
That sounds more like a Common Lisp style repl than Racket's, where you typically do have to restart Racket when reloading files/modules and thus have a fresh environment. People complain about it but I prefer the clean slate style of Racket over CL.
[I think, there were a snap at some point that had problems.]
In my experience a "Hello world" program with `#lang racket/base` (precompiled) takes around 150 ms on my computer whereas Python takes about 50 ms.
> Using the racket/base #lang instead of racket makes a big difference too.
My experience has been: As soon as I use `#lang racket/base` with `(require racket/match)` for pattern matching, the startup times are as when using `#lang racket`.
When I TAed, a lot of incoming 2nd year students didn’t know how to do for loops yet, which really set them back for basic algorithms.
I had a much deeper appreciation for functional languages after theory of computation classes in my senior / 4th year.
They hadn't done simple recursive functions over lists? What had they been doing?
Been a while since I had to read introductory material for Racket (or any similar language), but as I recall functions with a base case exit and recursion is usually among the first things they teach.
I looked into the Racket Repo to find something, but had a hard time finding the code.
Other Schemes and Common Lisp have similar constructs. Just because a language is a lisp doesn't mean its primitives have to be implemented using cons cells.
https://www.khoury.northeastern.edu/home/lth/larceny/notes/n...
Cons cells are typically used to provide lists with O(n) access time.
Recursing over a list is a way to learn how to implement for, while and friends. If you know this technique understanding for is just understanding a subset of what you are already familiar with. It can be used to iterate over an arrays as well as lists, e.g. with ranges: https://docs.racket-lang.org/reference/pairs.html#%28def._%2...
Racket can also be used to teach object oriented programming and programming with structs, if the aim is to teach patterns used in C-like languages generally it's not a bad fit. Well, except advanced stuff like pointer witchery. Though you could probably implement a teaching language that does it with arrays or the byte code directly if you wanted to. It might be a good way to improve on error messages for pedagogical purposes.
Of course with years of experience it’s easy to interpolate one from the other but these are students who’ve had 4 months of exposure to programming that have to jump from functional languages into operating systems and data structures and algorithms, all of which are taught with imperative languages
This is surely a single point of anecdata, but it makes me suspect that it was more about how teaching was done than a 'functional vs. imperative' thing. I also suspect pointers and memory management to have been bigger hurdles than how to format code for iteration, unless the Racket course introduced techniques like quoting.
Racket serves its purpose well as a simple and fast to learn educational language; it's easy to see and understand recursion. It's also easy to see what the execution order of statements in your program.
I will say though that some problem sets were a bit brutal in terms of time taken to complete them.
I'm surprised anew on the rare occasions I come across statements like this. The first time was when I applied for my first programming elective class. The teacher actively tried to dissuade me from it, saying that by the end of term they'd be lucky if they even got to for-next or do-while loops. I was shocked, having first understood these from BASIC code listings in the back of magazines, with only one or two weeks per year having a few hours of access to an Apple II on which to actually run anything.
I tend to fall into the trap of feeling that loop constructs should be so trivial, that understanding should come from a tiny fraction of one class session plus maybe a few minutes tracing the code by hand. So, I thank you for being my irregularly scheduled reminder that people's first exposures to such things can be very different.
IMO, each chapter of the tutorial just talk about unrelated "language" and then never once show how they all work together. One chapter will talk about web server but not class system, then another chapter will talk about another "language" that support class but then never write web server in it.
Besides the #lang line you can also use 'require to bring in libraries, so a single file could contain GUI as well as web server code. #lang isn't constrained to one language at a time either, if they don't conflict you can just add more to that line.
TL/DR: Just use Racket. If you find that you really wish that you had some other feature or style of programming, you can investigate whether there's a language that already provides that.
All of this is my opinion, of course.
All of the instructors, including Felleisen and Butterick, were nothing but helpful and friendly inside and outside of the classroom.
Even taking that link completely at face value that Felleisen is a Torvalds-type asshole in certain personal interactions... his work including How To Design Programs had such a positive impact on my life and the lives of others that I wouldn't discourage people from taking advantage of it.
In the past several years, I've:
* built & run an e-commerce site written in Racket[1]
* built a native macOS and iOS reminders app, available on the App Store [2, 3, 4]
* built a cross-platform desktop client for Apache Kafka [5, 6, 7]
* built a `#lang` for Lua [8]
Among[9] other[10] things[11]. I think that's all pretty practical stuff!
[1]: https://defn.io/2019/08/20/racket-ecommerce/
[2]: https://defn.io/2020/01/02/ann-remember/
[3]: https://defn.io/2024/04/09/ann-remember-for-ios/
[4]: https://github.com/bogdanp/remember
[5]: https://defn.io/2022/11/20/ann-franz/
[6]: https://defn.io/2023/10/15/ann-franz-for-windows/
[7]: https://defn.io/2023/08/10/ann-franz-source-available/
[8]: https://defn.io/2022/11/12/ann-racket-lua/
[9]: https://docs.racket-lang.org/http-easy/index.html
Bogdan also is extremely helpful and active on the community forums and gives EXTREMELY helpful answers on there.
Definitely an unsung hero of the language - just wanted to give a shout-out - I can report that your libraries are powering code that is making some unsuspecting users lives much easier :)
https://docs.racket-lang.org/http-easy/index.html
I think this is a really important point. I worked intensively with Python for years, but it was a deep disappointment to see how little the core devs and the community care about backwards compatibility in the 2/3 transition, and things have not improved. That might be due to what Python is dominantly used for today (The Numeric/Numpy transition which happened around 2000 was totally different). Breaking things every few years might be OK for unicorn startups or companies that move fast and, well, break things, but there is a lot of valuable programming from people and in organisations which can simply not afford, or do not see it as a priority to re-write mature algorithms every few years.
But a question to people who know it better: What are features of Racket which at first might not seen practical, relevant, or useful, but are surprisingly useful for programming when one gives them a try?
Lots of respect to people who not only get it, but build complex programs with Racket, Common Lisp, Haskell and similar languages.
CL mostly allows you to do whatever you want, at its core it is a compiled, imperative, garbage collected language, with incredible interaction and introspection capabilities and the ability to modify the language in a very straightforward way (take code, modify code). It just has a weird syntax to be able to do macros and reason about macros
But if you dig in to hacking with Racket (or another Scheme!) as a powerful general-purpose language, and to some extent ignore the "pedagogy" stuff, there's a lot of serious programmer stuff.
The CL books I've seen, OTOH, tend to be pretty practical, but also more technical than your average Python/JS just-get-me-a-job books.
A big thing to know about Lisps is that they're nigh-unemployable (other than Clojure, if you want to work in an enterprise Java shop)... so Lisps disproportionately attract the kind of people who would be programming computers even if it weren't a well-paying job.
Give me a decent LISP programmer who is willing to compromise and I can get you a job.
Something like (def-action name ..) and it generates the whole routing handling, response generating code for you in a web application. Kinda like, but more powerful than the decorators you find in Flask.
Still looking forward to the day Python ecosystem fully embraces it, without going through using C and calling it Python, or reaching to implementations that are 80% there and are largely ignored by the community.
Thankfully the whole AI stuff is putting pressure into making JITs part of the standard Python workflow and I am looking forward to that Python 3.13 release.
I have done that a decade ago before React was even popular. Even if only the syntax is different, it was and is much nicer than writing JSX.
Scheme is in a way more minimalist and Schemes are not as large, but this might also be give an erroneous impression because they build on the enormous experience with Common Lisp and have boiled down to the most essential parts - it is not the kind of minimalism "the simplest things that could work" but "what turned out to be indispensable in practice", which is a very different thing.
[1] https://gigamonkeys.com/book/
[2] https://weitz.de/cl-recipes/ or https://www.amazon.com/Common-Lisp-Recipes-Problem-Solution-...
1. Package manager
2. Cross platform Gui
3. Easy to install on all platforms
4. Gradually typed language Typed-Racket that checks types at compile time
5.fast (has moved from middle of the pack to top 3 fastest Schemes)
6. Evolution under the hood as opposed to just syntax and features (chez scheme over C)
7. Simple IDE with Emacs built in which makes getting started if you are afraid of Emacs easier.
8. Documentation languages like Pollen and Scribble make writing documentation better than any other language I have used
9. Zuo, a Make replacement which works like a mini Racket
10. Large active community
11. Modern communication channels (Discord, Discourse Forum, subreddit)
12. Documentation geared towards beginners or experienced programmers (Racket Guide vs Racket Reference)
13. You can turn a Racket program into an executable (it’s far but better than Python’s options that’s for sure)
There are Schemes that I like better for specific things (Gambit-C for C integration, Gerbil as a Racket Successor, Chez as the Fastest Scheme, Guile for its large GNU ecosystem)
But no Scheme has come close to offering even half of what you get with Racket out of the box
For example look at Elisp. It might be the most successful lisp in the modern Era because of Emacs. Emacs alone is like over a million lines of Elisp, and the ecosystem of packages is gigantic. A lot of people do not like Elisp, and there have been many attempts to create Emacs + a better language (Guilemacs, First/Second Climacs). But it has all failed because Emacs proper has a lot of momentum, and you can't build Emacs + a better language. You need Emacs + a better language + a better/bigger ecosystem... Because while lots of people use ELisp in Emacs, more people are just calling use-package on what ever package someone else created.
Take another example, JavaScript. You want to write a dynamic web application, you use JavaScript. There is no shortage of tweets of JavaScript trivia where the person shows JavaScript adding two non nonsensical objects together and getting an even more nonsensical answer. If you don't program in JavaScript (or even if you do) you look on in horror and go "Why would anyone use this awful language!". Then you go use your electron based desktop apps, and run millions of lines of JavaScript in the browser. Are there better languages for the web than JavaScript? Sure lots of languages clear that low bar. But is there any language with a comparable ecosystem that also works as seamlessly in the domains that JavaScript works in? I'd argue no. JavaScript has so much momentum that it even spills over into areas where it shouldn't be used (I.E the desktop and the backend) but it can go anywhere at this point (including custom ARM CPU instructions https://developer.arm.com/documentation/dui0801/h/A64-Floati...)
I'd say the same thing about Python as I did about JavaScript (I am a Python dev). If the official OpenAI Api had been written in Racket there would be millions of Racket users right now and a bunch of new and awesome package, but it's written in Python.
Another example is Zig. I actually think that Zig has a chance to compete in the programming language. I started using Zig not because of any particular feature of the syntax, or the libraries it had, but simply because trying to compile cross platform C/C++ applications using a combination of GCC, LLVM, MSVC, and building for Arm, X86_64, etc is so awful, that using Zig instead is a better solution. This will be the gateway for most people to Zig IMO, and then from there the ecosystem will follow.
There is one edge case and that is Swift. I actually think Swift is a good language, and has a lot going for it. It definitely has the chops to be a good low level compiled language with good C/C++ integration. But a lot of its popularity is due to Apple having the power to make it the de facto language on iOS, just like Google can with Kotlin. But that will only help on the platforms they own (which are admittedly a lot more than most languages), but to gain the viral cross platform adoption, it will require an actual effort on Apple's part to make that happen, along with some dedicated fans of the language. Right now, using Swift without Xcode is hard, even with the VsCode plugin. I know Miguel de Icaza is at least one of those hardcore Swift fans, and is trying to get the Swift Godot project up. That could be the gateway to Swift for people outside of the Apple ecosystem but we will see.
In software development it can take up to a year until someone has turned out to not be a good fit, because the systems are quite large and the first few months will in most cases be spent introducing the basics of them. That's a rather hefty investment for most companies, except the very large ones.
So as a manager, why would you bet on Racket? Unless you understand the peculiarities and power in macros (and eager to teach it over and over again) you won't, because the board will roast you over bringing in the risk that you can't find replacements when core developers inevitably move on.
If there was something unique you could only use if you had Racket developers it would pull in broader industry usage, but as far as I know no such thing exists.
As a single or few developer consulting business/dev boutique things change, you'd only have to convince customers and they like shiny things that solve their problems or make money, and if you and your comrades know Racket well you could very well create such shiny problem-solvers relatively fast. Then you'd only have to resist the attraction of better pay and someone else closing the sales once the business is up and running.
Anyone who learns Racket will have learned ways of deconstructing problems that will make them far superior in problem solving to those who learn only e.g. Java and only know how to do things the OO™ way.
When a Harvard dropout writes a small system in PHP, and needs to call in the big guns to try to unfuck the situation [1], who should he call? Someone who got really good at jQuery at university?
Besides, aren't modern mainstream languages bragging about having nothing to learn? Learn go in just a couple of days, etc.?
[1] https://engineering.fb.com/2014/03/20/developer-tools/hack-a...
At this point, nearly all the code I write is in JScript, Pl/SQL, Python, and T-SQL. I learned none of these while in school: Javascript was not yet invented when I was getting the degree.
I will say that SNOBOL, of all odd languages, was useful to me after school in learning Perl.