Racket: Lisp for the modern day
deusinmachina.net
deusinmachina.net
But as I've progressed in my career, I've come to appreciate how it helped me develop a strong foundation for reasoning about programs and their underlying logic (in any language) that continues to serve me to this day.
If I was approaching this outside of a structured curriculum, it would be hard for me to justify this long-term intangible benefit relative to being able to move quickly to write something interesting and useful. And I think writing interesting and useful programs is the best way to motivate oneself to keep programming. So I can't strongly advocate for this approach. But I do think there are some worthwhile benefits.
When MIT switched from scheme to python for their undergrad classes there was a big debate here aboutit. I think the argument was that python won't make learning the concepts any harder but is less of an issue for students to learn and has some long term value professionally so win-win. I don't fully agree but I can see the logic.
"Costanza asked Sussman why MIT had switched away from Scheme for their introductory programming course, 6.001. This was a gem. He said that the reason that happened was because engineering in 1980 was not what it was in the mid-90s or in 2000. In 1980, good programmers spent a lot of time thinking, and then produced spare code that they thought should work. Code ran close to the metal, even Scheme — it was understandable all the way down. Like a resistor, where you could read the bands and know the power rating and the tolerance and the resistance and V=IR and that’s all there was to know. 6.001 had been conceived to teach engineers how to take small parts that they understood entirely and use simple techniques to compose them into larger things that do what you want. But programming now isn’t so much like that, said Sussman. Nowadays you muck around with incomprehensible or nonexistent man pages for software you don’t know who wrote. You have to do basic science on your libraries to see how they work, trying out different inputs and seeing how the code reacts. This is a fundamentally different job, and it needed a different course. So the good thing about the new 6.001 was that it was robot-centered — you had to program a little robot to move around. And robots are not like resistors, behaving according to ideal functions. Wheels slip, the environment changes, etc — you have to build in robustness to the system, in a different way than the one SICP discusses. And why Python, then? Well, said Sussman, it probably just had a library already implemented for the robotics interface, that was all."
https://www.wisdomandwonder.com/link/2110/why-mit-switched-f...
Of course, it's often pointed out, "Well, if you write in Scheme (or C or Java or whatever) then you're not writing in assembly language, much less machine language, so you already don't understand everything." There's certainly truth there, but, to me, going from, expertise writing code in a high-level programming language to, gluing together libraries that you kinda-sorta understand, feels like a bigger leap in what you do or do not understand than going from assembly language to Python.
It's interesting that Sussman kind of lumps together "uncertain software libraries" into the same category as machine control robustness (e.g. hysteresis). I never thought of it that way but I guess in practice it's all just "stuff", those libraries are just another piece of your program's environment like any other.
Ability to deal / reflect with unknowns for engineering is of great value, but so far I've never seen that in office.
A lot of texts will use pseudo-code and it is (from my experience) easier for beginner programmers to see the relation between pseudo-code and Python than for many other languages.
(?)
(?)
One of the challenges with an approach which doesn't concern itself with "industrial grade" or "production ready" languages is getting buy in from student. Even if there were a perfect language for teaching, if students don't see the applicability of that language they aren't going to learn enough of the concepts to move to such a language later.
I think it's very easy for us (and other technically competent folks) to see value in learning how computers work for the sake of that knowledge; however, students, as an over generalization, don't. The fact that relevance and motivation are some of the hardest hurdles to overcome in early computing classes is a perfect example of this. Using languages with a professional pedigree is important because it increases student buy in to what they're being taught.
An analogy I like is that you wouldn't give someone new to woodworking a toy hammer and hand saw because they need to learn fundamentals like striking and cutting before they can start using "real" tools, you would provide them with capable, but beginner friendly, tools that allow them to build those skills as they learn.
You WILL get very interesting ideas and concepts, it's fun, basically, that's it.
+ You won't solve problem faster than your colleges with solid competitive programming background;
+ you won't be able to optimize the code and cut 30% of your company's server cost,
+ you won't feel comfortable to read real-world complex project code,
+ you won't get some domain-specific knowledge to solve problems you previously can't solve.
+ .....
It won't make you a better problem solver; at least its impact is way smaller than pick up go/rust/cpp/java and carefully try implement challenge like: https://github.com/codecrafters-io/build-your-own-x
GIS is certainly interesting in its own ways, and it taught me some visualization and design skills, but I wish it would have been possible for me to learn more of what's going on under the hood of the massive libraries and high-level languages I use every day as a professional "software engineer"
So I decided to learn SICP on my own. I already have the book, so I'll watch the MIT lectures of the original authors available online, and try to make progress.
I'm not in any hurry to complete it anytime soon.
None of this has anything to do with academic computer science. I think I'm just unusually bad at memorizing syntax.
There is a "JavaScript Edition" of SICP. The preface says ECMAScript 2015 enabled a close match by adding lambda expressions, tail recursion, and block-scoped variables and constants.
It doesn't mention much downside except that JavaScript's "rigid syntactic structure complicated the implementation" of some programming language design book material.
In order to get that tough question, you could carefully read the book, read his assignment solutions, and pay close attention to his caveat warnings in lectures... One of the three would typically contain the tough question.
Or, you could just read the book, do the assignments, and accept ~95% on the final exam as a maximum grade.
A ~95% cap, for a lot less work, is a good deal. Taking the deal is probably the right call for most people.
That being said, the thing I wish someone explained well is how amazing lambdas can be. I understood the benefits of list/array/stream processing on first glance, but it took a few years before I really understood the practical application of lambdas.
> …it helped me develop a strong foundation for reasoning about programs and their underlying logic (in any language) that continues to serve me to this day.
I went on to use Clojure and ClojureScript for several years. Now I primarily work in JavaScript and (preferably) TypeScript, but I can’t say a day has gone by where what I learned working in Clojure hasn’t been applicable and valuable.
Just one more anecdata point, but I would advocate learning a lisp—maybe even any lisp. In fact, it’s usually one of my first recommendations when juniors/mentees ask me for advice in any kind of broad strokes.
Lately I've been using Racket to prototype the interaction design for a game, and I had written some placeholder text. I had put fake interpolation in for {player-name} and things like that, and then I realized that #lang at-exp would let me just ... do that, as described in the original article.
I had to laugh, because I maintain a bunch of Python code, and if Python has batteries included, Racket comes with a retrofittable fusion battery pack.
One other little anecdote, is that I've been porting an old plt-scheme codebase to Racket CS. In the second phase I have started replacing an ancient C++ rendering layer with the racket gui canvas functionality. During the process I moved hundreds of runtime type checks in the C/C++ layer to the Racket contract system. It was as if the Racket team had somehow secretly obtained access to the codebase I was working on and had designed the perfect abstractions to solve the problem.
With regard to prototyping GUI's I'd suggest taking a look at https://github.com/mfelleisen/7GUI. https://github.com/Bogdanp/racket-gui-easy could also be a good place to start.
With regard to Racket more generally, I'm probably not the best person to ask since I had a very high friction start where I just banged my head against the wall until things made sense.
I have one kid using scratch now, and one older graduated to godot, roblox/lua, some javascript/web.
I would love to get them into lisp (already done a bit of Janet along with me), but it really needs to be something they can write their game ideas in, and share/show-off to friends.
Here is a library for making retro games: https://r-cade.io/
Ask on Discourse or Discord, for more game options.
From my own experience, it is absolutely possible to get good interaction with low latency in Racket, but of course as with any language you have to have enough experience to know how to avoid performance pitfalls.
For some of the gui work I've done I needed to mix threads and semaphores to get things to be really responsive when there could be a long running process triggered by a UI interaction, but in Racket it has been vastly easier and safer than in other languages.
For anyone who has worked through HTDP: is there any benefit to sticking with DrRacket vs using VSCode? The friction involved in moving around in DrRacket really dampens my enjoyment of the material in HTDP.
Note that you can change the default settings to be more Emacs-like.
How big a desire of the average neophyte is to make themselves another language?
If you deal with the same problem space a lot, having a Domain-Specific Language (DSL) can let you execute that vocabulary and work at the level of the terms that fit the problem space best.
This is a lot smaller in scope than designing a whole programming language, think of it like a unique vocabulary for solving specific problems and automating specific kinds of work you do!
In most mainstream languages you have a large syntax, lots of idiosyncracies, and limited ability to hack with the innards of your tool. Scheme is small, regular and freeing.
Now personally, after my first year of college, I asked why on earth can't we access the methods in an object (java4 at the time) to generate a UI to dispatch / interact with it. Teacher rapidly walked me off the room while mumbling "but that would be metaprogramming!". I left confused about his annoyed tone.
Not until year 4 we had the chance to see reflection/intercession, lisps, macros.. I wish someone showed that to me when I was 12.
ps: it might not be obvious, and maybe I'm wrong but I see adhoc DSL's everywhere I work. ORM, build tools, they're all pseudolanguages.. and people keep reinventing them. Scheme/lisp offers it on a silver plater for you.
I've not watched a relative neophyte try and actually -do- that so I can't comment on how far they've got with it, but making "creating DSLs" approachable seems like a really interesting thing to be aiming for.
The answer seems to be in the title: this of particular interest for those already interested in Lisp or Scheme.
Rust because it’s the other language I see most often see coders learn to build their own apps. It has a good reputation for developer experience, security and speed.
I’ve heard enthusiasm for lisp-based languages for a couple decades and don’t doubt the merits of Racket.
If you’re picking just one language to learn, and limiting your learning to only that one language for a significant period of time, you’ll probably want to learn Rust. You won’t get all of the benefits of also learning a lisp, but you’ll get a lot of the ones which generalize well.
If you’re open to learning 1+N and otherwise lean towards TS, I would say you’re better off learning Racket (or any lisp really) in tandem than learning TS alone.
Familiarity with the core concepts and idioms of FP are broadly beneficial in any language, and lisps tend to be a good balance of those with low incidental mental overhead, and reasonable escape hatches to do imperative stuff where it makes sense. Racket is probably a particularly good candidate because its optional typing is another overlapping story between the two.
I haven’t written in any lisp for close to a decade now, but I still find that prior experience beneficial every day since. I sometimes miss the simplicity and flexibility of the parentheses. But I can take what I learned—how to reason about state, data flow, data-driven abstractions—anywhere. And those abstractions are particularly useful in a structural type system like TS.
Which one ? Rust and lisp in general are quite different beast...
For example being able to make good use of recursion, being able to write programs more elegantly.
Racket, in contrast to JS or TS, comes with lots of batteries included, therefore not requiring so many third party dependencies. Time and time again I see the Racket docs and think: "Ah Racket has got something for that/got you covered." Also it is rich in programming language concepts. You can write your programm in any of the languages that come with Racket, or you can write it with function contracts or you can use Typed Racket.
At its core, it is a much cleaner and better designed language than TS will ever be due to TS' JS legacy.
Racket (the language) itself is no longer a Scheme, strictly speaking, but still feels generally "schemey" in the broad scheme of lisps. However, Racket (the software package) does ship with a Scheme or two, namely R5RS and R6RS.
CPAN made Perl the best choice for many tasks and the same can be said of NPM for choosing TypeScript now, regardless of the elegance of the language.
But I’m also a fan of “language tourism”. Even if one language is more practical, visiting other language cultures can make us better developers overall.
I studied Haskell for a bit which gave new ideas for how I use Perl. Culturally, Haskell was using a lot of functional programming concepts and recursion. Those were possible in Perl but not popular.
I’m sure there is value in studying Lisp languages for those who end working mostly in TypeScript or Rust
> Racket excels as a programming language for young learners and beginners.
I honestly think Racket could do more to be beginner-friendly. The documentation is excellent, but difficult to understand as a newcomer. There are some great little tutorials that are easy to work through, but the ramp from there to writing your own Racket programs is steep imo.
I don't know of any other language with so many batteries included. Racket deserves to see community growth, and hopefully with that will come more resources for folks to get started
Its fine, and its pretty good for Racket code (and its variants, like typed racket) but when I'm working on a real project I have other things I need to write too, like CSS, HTML, TypeScript, bash scripts etc.
Its more ecosystem to be more adoptable IMO.
I love it for learning though, but turning racket into a production level language w/ proper ecosystem has a way to go
I think they should fix this quite obvious bug before writing more articles.
I hope I don't get kicked out of HN altogether for this comment :)
Luckily all of them can coexist, so we do not need to choose.
You compile code, which is text (data), all the time, don’t you?
It looks like that wasn't the case even in 1996:
In SBCL, any evaluation of an expression is done by first compiling it. Compiled functions that are no longer accessible (including not having any frames on the stack) are garbage collected.
The really interesting question is not whether users can mutate existing compiled code, but whether it's useful for the Common Lisp implementation to do so. This is because Common Lisp is a dynamic language, where generic functions and classes can be redefined on the fly. If you want to implement such things efficiently, it would be useful to be able to change existing compiled functions to reflect that (for example) this slot of this object is at this offset rather than that offset.
A scheme has been proposed to do that that puts such code off to the side in little chunks accessed with unconditional branches. When a redefinition occurs the branch is redirected to a newly created chunk; the old one is GCed when no longer referenced from the stack. You have to pay for the unconditional branches, but those are typically quite fast.
But if you mean "compile a new function called X and replace the old X at runtime", that's easy in Common Lisp. It's not commonly done unless you're explicitly writing some kind of compiler.
What is commonly done is to create a lexical closure at compile time and change its bound values at runtime. IOW changing the private data of a function at runtime is more generally useful than changing its instructions.
What's most common is to write lisp programs that emit lisp source code and compile it at compile time (but usually not run time). Such programs are called macros.
These days, a page of memory can be set to
Read Write Execute
The exploit mitigation you refer to is having the program typically set pages of memory to never have both write and execute set at the same time.
However, this is ultimately controlled by the program. On Linux, the program can invoke the os call 'mprotect' to change the permissions on a page (though a program can also voluntarily use seccmp routines to forego ever invoking this ever again)
And this is basically what browsers do. They compile the code into memory that has been set to 'write' (but not execute) and proceed to then set it to execute (but not write).
The effectiveness of this mitigation is mitigated by the existence of ROP techniques, which is why Intel started introducing Control-flow Enhancemnent Technology (CET), which is intended to ensure you can only branch to certain locations in memory.
(compiled-function-p #'f) ; T
(disassemble 'f)
; disassembly for F
; Size: 58 bytes. Origin: #x5350CD14 ; F
; 14: 498B4510 MOV RAX, [R13+16] ; thread.binding-stack-pointer
; 18: 488945F8 MOV [RBP-8], RAX
; 1C: 4883EC10 SUB RSP, 16
; [...]
$ pmap $PID --range 5350CD14
442331: /usr/bin/sbcl
0000000053498000 122272K rwx-- [ anon ]
total 122272KMy relative use of Lisp languages: Common Lisp 60%, Racket 20%, Haskell 5%, Clojure 5%, and various other Schemes 10%. Unfortunately since most of my work in the last 8 years has been deep learning, LLMs, LLM chains, etc., I spend a little over half my time now using Python. So it goes...
I don't think it's a particularly unique or interesting quality, that some old code still runs. After all, I can go to archive.org right now and run all of that ancient DOS, Amiga, whatever code in a 100% exact (or close to) emulator in my browser.
It’s too bad, because itself is really terrific.
The usual "expect all for free, give nothing back" attitude.
Stability is extremely valuable. A lack of change to the core language over extended periods of time can be a very good thing, especially if certain changes would break existing code. Rich has made it clear that he is indeed targeting this kind of stability.
Again, I would be very interested to hear what specific changes you think need to be made to 'Clojure "the language"'.
So... you meant 'ossified' in a good way?? If so, I guess I would have used a different term that didn't have such a negative connotation.
Comparing to other languages I think the stability of the language has served the user community really well and been an enabler of the ecosystem. I guess the continuous language additions and resulting complexity & library/framework chuirn in some otherlanguages can also be seen as vitality and growth, but for many of us it's the wrong kind of growth.
(And yes there are also disadvantages to the centralised development model of the core language)
edit: there's a good summary of the discourse surrounding this post in the reddit comments at the time: https://www.reddit.com/r/Clojure/comments/a0pjq9/rich_hickey...
unfortunately running on JVM actually really means running on Java same for .net it mean running on C#
i dont mind learning two languages, its expected from most developers to know more than one, but context switching in a single function between two language is not fun
However F# suffers from a bigger issue, that clojure doesn't, belonging to the platform owner, that behaves as if it was an error to make it part of VS 2010.
And I dont think F# failed, I just think it needs to find a way to hide C# and OOP better
But the language is doing fairly well, tons of educational resources, tons of videos on youtube , several nice projects on github, solid vs code mode, it is part of .net , but still a lot can be improved, and microsoft is far from abandoning, C# is one of MS flagship products , F# is not a flagship product
And I also think that Don Syme is a lot more active working for F# and promoting it, than Rich Hickey is currently working for Clojure
> microsoft is far from abandoning
Might has well. When you look at the resources actually being deployed for F#, it's clear that MSFT either don't care or don't really have plan for F#. Most of the work is done by the community. The number of actual paid/full time MSFT dev on F# is very limited. The tooling is extremely limited, there is no official F# libraries for pretty much any MSFT and azure services (have to relie on C# libs.) In leetcode where the have C# (so already have the infra to run .net stuff, and language like elixir and racket (so they do have more niche language), they still don't have F#.
The salvation for F# would come from finding a killer app, something akin to pytorch/numbpy or rails.
In my opinion, and I mean this in the broadest way possible, the average C# developer is probably less motivated to learn a new language than the average Java developer. That's because C# developers are prescribed by Microsoft what to do, and Microsoft could deliver a productive-enough experience with C# + .NET Framework + Visual Studio for a long long time.
Java's fractured IDE story and runtime (OpenJDK vs. HotSpot) I think lead to a higher concentration of programming language people looking at the JVM as a viable target to build a better experience on top of, so we got Groovy, Scala, Kotlin, (anyone remember Xtend?), IDEA, Eclipse, etc...
The bazaar produced and embraced a functional programming language whereas the cathedral treats F# as thunderdome for new C# features.
F# can do OOP just as well if not better than C#, and F# is anywhere from 2-10 times more concise than C#.
That being said, the mistake of Microsoft was viewing F# as a competitor to and research lab for C# and the community for viewing and selling it as a replacement for C#.
What Microsoft and the community should have done is treated F# as a competitor and replacement for Python from the start.
Also see the development effort Microsoft spends on Python across all their IDEs and what F# gets.
Every language lives under the iron fist of libc and the C ABI.
I know F# quite well at this point but only barely know C#. I know C# maybe only mildly better than C++ or Java in terms of being able to read it and guess what it's doing. I certainly can't write in it without looking up a bunch of stuff.
As an anecdote, I used to host a computationally expensive web app written in Racket (even before Chez version) serving large amount of requests at peak times on a single $10 DigitalOcean droplet. It was pretty fast and didn't crash. No need for awkward modern web scale thingies.
λ most of the way down.
You can write a Racket application even with a GUI and whatever lib you need and then cross build it as a native executable (that is, an executable that embeds the interpreter, the necessary libs, and your application's code) for yours and other platform for easy distributions.
See https://docs.racket-lang.org/raco-cross/index.html and https://docs.racket-lang.org/raco/exe.html for more information.
But the authors states that Racket is "the finest example of a modern day lisp bar none". In the modern day energy efficiency and climate change are major issues, the German government, for example, has set up the Blue Angel Ecolabel program: <https://www.blauer-engel.de/en>. Using modern day to mean VSCode and Discord is a worthless use of the phrase.
However, Racket is also a modern language in that it has many new and fancy programming language research-grade features since it is also a programming language theory research platform. From that point of view, "modern day" is a valid description :).
Racket ranks far ahead of languages like TypeScript, Python, and Erlang in terms of energy usage, but trails languages like C, Rust, Ada, Java and Common Lisp.
I think, however, there are probably other factors in your computing solution that has a bigger energy impact, like what processors you run on, the architecture of your program, etc.
The list places JavaScript at a score of 4.45 and TypeScript worse at 21.5. For reference, C, the most energy efficient it 1.0
The point is that TypeScript is JavaScript with typing syntax added on top. There is a transpile step into JS. That's how TypeScript works. The runtimes are exactly the same. Unless we're also measuring the build step? Which seems silly.
The difference should be near zero. And it's not. They clearly do not understand exactly what they are measuring.
I think the takeaway, however is the theme of a spectrum of energy efficiency, with compiled languages being more efficient than those that are not.
But I still maintain that the overall efficiency of a system is more a function of other factors.
But the argument that TypeScript generates a JavaScript, so it must have similar speed doesn't hold in general.
If the compiler in question is a whole-program compiler, it can make optimizations that a normal person couldn't do.
As an anecdote in [1] a raytracing program were implemented in both Scheme and C. The Stalin compiler (a whole-program Scheme compiler) produced an executable 45% faster than the one produced by g++. The Stalin compiler produced the excecuable by compiling Scheme to C, and then used a C compiler to produce the final executable.
The price of a whole-program compiler? Well, the compile time are huge.
[1] Scroll to Siskind's comment. https://groups.google.com/g/comp.lang.scheme/c/NJxRsdMNKz4
For those curious about the actual programs and results: https://web.archive.org/web/20071011073406/http://www.ffcons...
Programs that didn't type check were excluded.
https://github.com/greensoftwarelab/Energy-Languages/issues/...
Using the Geometric Mean or the Median with the time measurements from that table would have highlighted the middle value, like this:
JS 7.25
TS 7.80
https://benchmarksgame-team.pages.debian.net/benchmarksgame/...You can confirm it via archive.org too: the TypeScript[2] page shows both less implementations and the implementations that are shown are often slower than those in the JavaScript[3] page.
As for if that makes sense, well, IMO using the benchmark game for judging how good a language is at optimizations is flawed in the first place as not only there is a bias towards the more popular languages but also a lot of the top entries use approaches that in practice you wouldn't find in real projects.
[0] https://greenlab.di.uminho.pt/wp-content/uploads/2017/10/sle...
[1] https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
[2] http://web.archive.org/web/20170425064751/https://benchmarks...
[3] http://web.archive.org/web/20170425114504/https://benchmarks...
Didn't submit it though because they make it difficult.
https://news.ycombinator.com/item?id=24826453
(the whole thread is worth a read)
spectralnorm.typescript-6.ts(115,29): error TS2794: Expected 1 arguments, but got 0. Did you forget to include 'void' in your type argument to 'Promise'?
Something like that is probably what stopped the authors of "Energy Efficiency across Programming Languages".I don't know what you mean with your last sentence. That's the same paper...
--alwaysStrict
So when the JavaScript doesn't type check, the authors measured a different program that does type check.Even so, that only messes up the results because the mean is used rather than the median, and the data tables published with that 2017 paper, show a 15x difference between the measured times for a single outlier the selected JS and TS fannkuch-redux programs.
That single outlier is enough to distort TS and JS "mean" Time difference.
https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
[0] http://web.archive.org/web/20170715120019/http://benchmarksg...
Like you, most readers haven't seen the paper.
Like you, most readers have only seen "Table 4. Normalized global results for Energy, Time, and Memory" taken out-of-context (often without any way to find the original source).
Most readers notice the too-large differences C/C++ and JS/TS and start speculating about how those differences were caused (because that's fun).
I went back to the time measurements the authors provided and calculated the Mean, Geometric Mean and Median. Simply using a more appropriate summary statistic would have presented average values which readers would have found acceptable:
JS 7.25 times slower than C
TS 7.8 times slower than C
:even though they were based on different programs and included an outlier. (Similar story with C/C++.)Simple: start with the same data, make the same calculations, see the same results.
When we make assumptions about how measurements were made and analyzed, our assumptions may be wrong.
https://docs.racket-lang.org/reference/implementations.html
"The CS implementation is the default implementation as of Racket version 8.0. This variant is called “CS” because it uses Chez Scheme as its core compiler and runtime system.
The CS implementation typically provides the best performance for Racket programs. Compiled Racket CS code in a ".zo" file normally contains machine code that is specific to an operating system and architecture."
> when they switched focus to the Rhombus project, which killed a lot of interest and personal momentum I had going for Racket
The language has been "complete" for a long time. If you're actively trying to get something done, I think it's unlikely that some core language work is going to stop you.
It isn't clear what domain the parent wanted to work in; I won't say it's impossible they had problems but ... details are everything at this point.
The academic part of Racket gave rise to `syntax-parse`, a truely fabulous improvement over the standard Lisp/Scheme/whatever you used to work with way to write macros.
> The academic part of Racket gave rise to `syntax-parse`, a truly fabulous improvement over the standard Lisp/Scheme/whatever you used to work with way to write macros.
That's not the academic part I am referring to. My comment is about who the maintainers and users are and how their profession or studies affect how Racket is interacted with. (This is not a complaint or judgement. It's an observation.)
> The language has been "complete" for a long time.
There are a fair number of bugs in Racket's libraries, including core ones. They aren't discovered because academic users are not touching bits that more industrial-oriented users would find. In particular, I am thinking of the GUI toolkit, and in my experience, only one person is capable of fixing those.
It's not. There are several nice and unique things about Racket, but it's a pretty poor example of a lisp, to the extent that if you want to understand what's good about lisp you'd probably be better off learning emacs lisp than racket.
Racket is, in my probably slightly biased opinion, a vehicle for doing firmly within-the-box CS research and teaching. It comes with a lot of batteries included and there are some cool an innovative things about it (it has sophisticated support for syntactic abstractions with acceptable error reporting, contracts, non-textual data etc).
It's run by people with very respectable academic output, but to the best of my knowledge none of them are particularly appreciative of interactive and malleable computing (even python is much better here), or ever wrote any code that's reallly pushing the state-of-the-art. I'd also say that the racket IDE (despite also having some nice features) is ugly, clunky, sluggish and not something that I can see appealing to very good programmers.
I'm also not aware of any impressive industry project done in Racket (although, in fairness I should add that Carmack has said nice things about racket).
The people you mention in your first paragraph likely all belong to this category, incidentally.
Iteractivity is not required for solving cutting-edge problems and certainly not by people of that caliber.
Lisp programming, as such, does not require very smart people; languages in the Lisp family provide a user-friendly experience suitable for the average person who has some aptitude and curiosity for programming.
You need very smart people to solve cutting-edge problems in fragile low-level languages, in which a mistake will destabilize the machine. Those people have to be experts in the problem domain, and in coding (or a team which includes such).
Interactivity actually makes things easier for the bumblers who massage code into working and believe that trying functions at the REPL is a viable test plan.
+ almost everything related with LISP is fun
+ but they have VERY limited use in industry, for very good reason;
+ you should try spend at least same amount time (as on LISP topic) to learn something like leetcode(or even higher level of competitive programming, which improve your skill of converting your idea to code fast and basic math thinking; useful in interview), job-oriented CS book. You'll be a better problem-solver and more ready in job market.
+ If you're very sure you will be financially OK, just learn anything you like and ignore this message.
Personally I've spent many hours on LISP related topic; I enjoyed the time; I recommend it as a low priority interesting topic.
Things like develop a working distributed KV store(MIT 6.824), solid 1000+hours on competitive programming, those skill&knowledge are not only beautiful&interesting, but also make a person a better practical problem solver.
I learned LISP in college, way back when expert systems were the future of AI.
The worst thing that I could probaby do professionally is to write something in LISP that needs to be adopted and maintained by somebody else in the future.
And what would these very good reasons be? inb4 "only for single programmers", brackets are difficult for normal programmers, macros can't be understood by mortals, and other non-issues that have been discussed to death.
(https://github.com/azzamsa/awesome-lisp-companies/
https://lisp-lang.org/success/
http://www.lispworks.com/success-stories/index.html
such as
https://www.cs.utexas.edu/users/moore/acl2/ (theorem prover used by big corp©)
https://allegrograph.com/press_room/barefoot-networks-uses-f... (Intel programmable chip)
quantum compilers https://news.ycombinator.com/item?id=32741928
etc, etc, etc)
Thoughts or advice?
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. https://docs.racket-lang.org/more/index.html#%28part._.Termi...
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. https://users.cs.utah.edu/plt/kill-safe/
3. Sandboxing - https://docs.racket-lang.org/reference/Sandboxed_Evaluation....
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 https://felleisen.org/matthias/manifesto/sec_intern.html
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 https://github.com/Bogdanp/racket-binfmt/blob/master/binfmt-..., is directly included in another file as a regular library https://github.com/Bogdanp/racket-binfmt/blob/master/binfmt-...
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.