IMO a couple of cool aspects of Racket that aren't called out in beginner guides, but I think are really useful in real programs:<p>1. The use of custodians on a per-(green-)thread basis that brings "oh yes, if the thread crashes or is shutdown, racket guarantees that all open files/sockets/resources will be shut down". For example you can use this to ensure that a timed out client doesn't cause unnecessary resource usage. <a href="https://docs.racket-lang.org/more/index.html#%28part._.Terminating_.Connections%29" rel="nofollow noreferrer">https://docs.racket-lang.org/more/index.html#%28part._.Termi...</a><p>2. Events and composable concurrency from Concurrent ML - Unlike Go's channels, concurrent ML events are composable up the stack, and have some nice things built in like "NACK events" (allowing cancellation down the stack). Unfortunately there aren't great primers about using this that I know of apart from the Kill Safe Synchronization Abstractions paper. <a href="https://users.cs.utah.edu/plt/kill-safe/" rel="nofollow noreferrer">https://users.cs.utah.edu/plt/kill-safe/</a><p>3. Sandboxing - <a href="https://docs.racket-lang.org/reference/Sandboxed_Evaluation.html" rel="nofollow noreferrer">https://docs.racket-lang.org/reference/Sandboxed_Evaluation....</a><p>Some of these were added to make it easier for the IDE to manage errant programs that could be written by beginners, but it is also a very "applicable to production" set of tools.
Racket internalizes Extra-linguistic mechanisms <a href="https://felleisen.org/matthias/manifesto/sec_intern.html" rel="nofollow noreferrer">https://felleisen.org/matthias/manifesto/sec_intern.html</a><p>Also the fact that various DSLs can inter-op with each other directly, so that you can use something like a binary parser description, as if it was just another Racket library. For example this description of the format <a href="https://github.com/Bogdanp/racket-binfmt/blob/master/binfmt-test/binfmt/basic.b">https://github.com/Bogdanp/racket-binfmt/blob/master/binfmt-...</a>, is directly included in another file as a regular library <a href="https://github.com/Bogdanp/racket-binfmt/blob/master/binfmt-test/binfmt/basic-test.rkt">https://github.com/Bogdanp/racket-binfmt/blob/master/binfmt-...</a><p>I agree that startup time is not a winning aspect of Racket. My naive understanding is because Racket is not a direct bytecode interpreter like CPython, but actually has to run a compile step to native code, and doing that for programs + their required libraries necessarily takes at least a couple of hundred milliseconds even before anything can start running, while CPython can pretty much start executing from the get go.