While it is definitely true that “image-based development” in Racket is far different than many Lisp systems, I think it’s worth noting that there is a non-zero amount of support.
Thank you for the links, these seem useful for when I do have to work with Racket. Thus far my Racket experience is on the command line side since I mainly ran experiments to better understand code in papers.
safety (?)—students probably don't need to mistakenly break DrRacket because they redefined something in its core.
I can see the need for this use-case, as with students their freedom to use their own problem-solving approaches genuinely isn't worth the costs complexity poses on their ability to learn.
On the other hand, as I understand it Schemes (including Racket) are already used in restricted forms when educating students, rather than providing access to the full language. Restricting access to image-orientation by e.g. forcing whole-file compilation when compiling any form in files with a specific #lang
doesn't seem impossible, or even difficult if the image-oriented features themselves were well-designed in the context of Racket as a whole.
Neat. Sorry to hear it's not for you. If you'll excuse that this might
sound snarky (I'm at least 50% genuinely curious): why jump into a
thread with this much text, then?
"My" isn't really the important point there, just a data-source identifier
More relevant is that it excludes some existing development styles and domains of interest.
In terms of motivation, while I'm not particularly attached to any Lisp in particular (or even Lisp for that matter), I am interested in the problem of "design a general-purpose language for both research and production purposes", both for personal use and for better solving some gaps in the overall software ecosystem. The above-mentioned points are among the constraints against Racket specifically solving that problem (through impairing its ability to morph itself into whatever a particular problem/developer needs), and unlike any other such constraints are ones I personally can reliably speak to.
If some aspect of "reasonably ergonomic generality (or mutability into the same) for all human programming problems" explicitly contradicts one of Racket's goals, that would be a clear reason to exclude it from consideration for changes towards fulfilling that goal. Barring such a fundamental contradiction, there's little reason not to engage and see if the community/maintainers are aligned to either my own proposals or to other solutions which would move it closer to the above generality.
On a separate note, opening conversation on somewhat contentious topics from a perspective of genuinely trying to understand whichever viewpoints you aren't already familiar with (in this case, "why does Racket not support image-oriented programming without rolling your own runtime") is a good way to improve both your own understanding and the publicly available documentation for others researching the same topic.
Specifically, I'm imagining putting together a PR when I discover a problem with a piece of software: if I'm going to tell you about a problem that I'm having with your code, it seems to me vital to be able to say that we're talking about a single piece of code with specific dependencies, not a (forgive me) monkey-patched intertangled updated version of it.
I view "code" in general (i.e. the below isn't specifically talking about Racket) as being on an axis between two different categories of use-cases, which I will label arbitrarily below for the sake of having short names to refer to them by.
One class of use-case is static runtimes, which have a specific known behavior that they should execute and then exit (or loop). These should indeed be approached the way you describe, with static code that resolves to a specific and predictable set of steady-states with specific and predictable transitions. Not only does this help the PR use-case, but it also improves predictability in actual usage of the program.
The other class of use-case is dynamic runtimes. From an academic perspective I've only seen this approach used in AI, specifically in "online learning" systems, but outside academia this viewpoint on programs is applicable to a variety of real-world application domains.
Dynamic runtimes are very useful when you want to put an application somewhere in a real-world process, don't know exactly what behavior it should have, and want to maintain availability of its intermediate versions even as you improve it (or as it improves itself) towards better fulfilling its role in that process.
I've mentioned above that some development styles require support for this use-case, meaning that supporting it in turn supports those specific development styles, and the programmers and problems for which they particularly shine.
In practice, it also seems that sufficiently large software applications naturally transition to the dynamic runtime format, with e.g. "microservices" and "continuous deployment" systems providing a very clunky approach to segregated redefinition of portions of the larger system, without compromising the functionality of the other components or the system as a whole. Better support for dynamic runtimes on the language level both improves the expected quality of solutions for this "large application" use-case, and allows smaller teams or individual developers to better scale their software development by using the language's in-built functionalities for what would otherwise require significant additional infrastructure and coding-discipline.
The discussion of benefits from image-based programming above is from the implicit position that supporting use-cases for dynamic runtimes doesn't mean you have to use the language that way; i.e. you can have either static, or static+dynamic, but the only-dynamic case (where the runtime's dynamicity inherently prohibits implementing static programs with predictable behaviors) is avoidable without sacrificing either dynamicity or orthogonal features. Given this position, supporting the dynamic use-case has no bearing on the static use-case you present.
The above position could be disproved if there's meaningful constraints on what features dynamic runtimes can support. I wouldn't expect such constraints, however, since even e.g. proof assistants are implemented mostly-interactively despite effectively requiring whole-program proof-search to maintain the accuracy of their domain-models. Most likely the worst-case cost is higher compile times for certain features (like complex type systems), which can always be ameliorated with optional file-level batch-compilation without sacrificing dynamicity.
Taking the above and applying it to Racket, for Racket to fulfill the "generality" goal mentioned in a different reply above, it ideally should be modifiable into a language supporting dynamic runtime behavior in both the final application and the development of said language itself. Currently this requires reimplementing significant parts of Racket in a compatible manner and redoing that work for every language-creation problem in this category, which is cumbersome and an effective blocker to such usage.
That is, the ability to edit parts of your own code, but not other existing libraries?
Or (still spitballing), what if the major change was the ability to freeze and reconstitute large pieces of data?
I'm not certain exactly what you have in mind in terms of limits on this freezing/reconstitution process?
In terms of clarifying the specific points you seem to be engaging with, image-based programming aims towards erasing the line between "static code" and "running code" (Smalltalk is a good example and the origin of the concept, as @ShalokShalom notes). This barrier can be added back afterwards if the developer wants it, but having the runtime enforce it (barring specific code/compilation options to toggle that enforcement) is a decision with costs to programmer dev-X and breadth-of-language-application, with apparently no benefits that cannot be achieved through other means.
This last point implies that Racket is not a vehicle for exploring all possible points in the design space of languages.
Thank you, given this fact many of my points regarding Racket's conformance to its own goals are indeed irrelevant; though I still feel Racket's 'meta-goal' of supporting PL research could benefit from it becoming a vehicle for exploring all possible points in this design space instead of just some of them.
hygenic macros or the #lang
reader system
Apologies, my statement was meant to imply that both of these features seemingly can be implemented in e.g. CL, albeit with some difficulty and with constraints on generality-of-application which would not be meaningfully harmful to their usability. Please see just below for a more nuanced take on the topic.
My days with Common Lisp (few, granted) didn't show me anything like what
Racket routinely does with language-oriented programming…
While I suspect there isn't a way to implement Racket's specific macro system globally in e.g. a CL environment without a fragile parser for environment-related data to attach to the raw s-expr, from what I've read of the docs I haven't found any apparent end goals of Racket's features which on-the-surface seem unimplementable in a language with both s-expr- and reader- macros, especially if you relax the globality constraint to "this property is global within the scope of this library's usage".
I suspect the lower prevalence of such activities in the CL ecosystem is mainly a factor of different community interests; the CL community leans heavily towards either production software or solo hobby projects, rather than PL researchers.
Building off of the above, there's also the point that CL users haven't invested in libraries constraining CL's redefinition or dynamic binding capabilities, since from an application perspective there's very little benefit to this. On the other hand, I suspect (as not-a-professional-PL-researcher) there are few domains of modern PL research where you could easily write papers about languages utilizing image-oriented features, given the incentive to make your results legible via (preferably-mathematical) guarantees to readers/reviewers, and that in fact they would make it harder to derive such static guarantees. As such, if you lack libraries constraining against use of these features, there's a (weak) incentive for PL researchers to move to languages constraining against them instead.
The only case I can imagine where a group has economic incentives specifically to research programming languages in CL's runtime instead of Racket's (rather than being indifferent, library ecosystem and standard-library PL-research-support notwithstanding) is when they're also application developers, where the runtime's dynamicity is an advantage for the language they're developing. Coalton's development by Rigetti computing (a CL child-language with HM typing and a relatively-fluid interface with the host Common Lisp runtime) is one example of this circumstance.
However, unless I get the bandwidth and muse-interest to read through the papers and actually attempt a port, I'm admittedly not qualified to speak further on whether non-image-orientation has a "moat" here.
While the specific implementations were clearly based on how Racket is designed, perhaps the maintainers could chime in if there's some inherent technical barriers to solving the use-cases hygenic macros / #lang parsers address in an image-oriented runtime?