My resignation letter as R7RS-large chair(groups.google.com) |
My resignation letter as R7RS-large chair(groups.google.com) |
[1]: https://codeberg.org/scheme/r7rs/issues/126 [2]: https://groups.google.com/g/scheme-reports-wg2/c/TUbmlPY9lR0
> The establishment of the central issue tracker is, I reckon, more to blame for the current disputes. The old model of periodic ballots provided the community with focus; the issue tracker has the problem that, since all currently outstanding problems are listed in one place, any such problem can become a focus of attention at any time, and then arguments about the details of that problem erupt. John has observed in #scheme that the more into detail we get, the more we seem to argue, which seems accurate. It has also, in practice, become a place where issues related to the Foundations only are discussed, and work on the Batteries has mostly stalled. Mea culpa!
Much of the process that was started in r6rs led to racket. Kent Dybvig was the head of the standards body and the racket folks were also active in the mailing lists. I think a big part of the disagreement was about correctness. r6rs guarantees some things about a running program that is difficult to do for many small hobby projects. There was also a discussion started about things like immutable data (pairs and strings, mostly) which got people all hot and bothered.
The problem with r7rs-large is that it will have to solve many of the problems solved by r6rs (low level macro system, how to handle unicode etc...) which means redoing the r6rs work.
Someday, I'd be interested in what were the process difficulties overcome, and how, and what are the remaining problems or costs.
(Disclosure: I was involved in the working groups, briefly and in a much lesser capacity.)
What forces are keeping the various implementations aligned and moving in the same direction? What is driving them apart? What does the future look like?
People who want to write real-world Scheme code have a strong incentive for a single definition of the language so that their code will reliably run on multiple implementations. They want one language and are probably willing to deal with some breakage in places where implementations are alreaday incompatible in order to get there.
People who maintain Scheme implementations want backwards compatibility so that they aren't forced to rewrite a bunch of already working implementation code or try to support multiple different languages at the same time. They don't want to make breaking changes to their implementations and break all of their users in order to converge towards some other implementations' behavior they may not care about.
Teachers want a language that is maximally elegant and minimal. They are perfectly happy to make tweaks to the language to make it incrementally cleaner even if it breaks tons of existing code because most of their code is short-lived anyway.
Reconciling these very different incentives does not sound fun.
On one project, we had a horrible integration test system that required a human to read and interpret the output. The guy who wrote it made his own DSL. As we struggled with it, he noped out and left the project. The next guy had partly the right idea. He figured out how to translate the whole thing into Python with a couple of macros. So at least you could step through it. Then he noped out. Since I do a lot of CI/CD work and my primary goal on the project had already been fulfilled, I took over. What a mess. I made it better but I still couldn't nail down pass/fail statuses reliably. Pointless system.
I kept harping on how we needed to throw out the whole thing. It was a false sense of safety at best. When I left to work on something closer to my life goals, at the very last big meeting one of my people I'd been mentoring said, "The last 3 people to leave this team worked on this one project. Maybe we should get rid of it." and everyone started nodding. Son of a bitch.
Now, I wouldn't have stayed anyway, but someone else might have. I've seen other situations like this play out, and while there's always gonna be someone who 'takes their ball and goes home', often enough it's someone reasonably determining that they cannot or will not be responsible for the chaos represented by Option A over Option B. This will burn down, fall over, and sink into the swamp.
I still have no idea what exactly R7RS is
Committee consensus took us up through R5RS. There were about 30 members of the committee, though obviously some were more active than others. The problem with that was that we got no change except at the margins. Implementations were extended in random incompatible ways.
Then we had consensus of a small committee (5 members, later 4) for R6RS, followed by a community ratification vote. A lot of people thought the resulting standard was over-engineered, and I am quite sure that many people didn't understand all of it (I didn't for sure, especially macros and records.) Some implementers adopted it, others declared they never would.
For R7RS-small and the early stages of R7RS-large, we had the open SRFI process (anyone can propose, the community helps refine, the author decides when to freeze the result).
Now we have a (de facto) Sitzfleisch process: however stays in their seat and is still arguing the longest, wins. I eventually ran out of energy for this one.
Note that in all cases the text controls the meaning, not the author(s), and when the standard and an implementation collide, it is the implementation that is wrong. This is very nearly a sacred principle, as in C/C++ and various other multiple-implementation languages.
Inconsistency is more expensive the closer to the language definition it arises as the blast radius is wider.
Compromises and redundancy are more valuable in the library layer.
Lisp blurs the lines somewhat but it's usually possible to subdivide a system into a core and stuff built on that core.
What if they (whoever it is, who could or should do this) worked on a proposal, that specifies, how language features should be added to the language? I mean, there are things like continuations and macros. Those need to be really solid. But based on them, could one not make everything else an optional addition, implemented on top of them, instead of in a dialect's core? So that Schemes could all go for R7RS small (except those that object to things in it) and then basically have a "folder" in their sources of things that are additionally necessary to have R7RS large things? Those things being implemented in the way that the standard proposes? Then we could get to a R7RS large step by step, feature by feature.
I guess this depends on whether things in R7RS large are at their core incompatible with how R7RS small works. Probably it also depends on those dialects implementing the standards correctly for the primitives, that the extension mechanism is supposed to be based on.
I also don't know enough to tell what attempts have already been made to resolve things, so perhaps someone already had this idea and it does not work.
If you want a large language, isn't it a better idea to build it on top of something the makes better guarantees for the user? I prefer my program to not continue executing after reaching an erroneous state.
I’m sad how quickly this rocketed to top 3 on front page and how little content there is, it’s just someone resigning from a project virtually none of us know about. The “My resignation letter” was titillating enough to skyrocket upvotes and engagement
The former want the language to stay as minimal as possible with a tiny standard library so that there are fewer concepts and options for students to stumble over. The latter want a full-featured language (but still minimal, it is Scheme after all) with a large standard library of useful types and functions so they can get stuff done.
These two perspectives are both reasonable but fairly incompatible.
For most of its history, Scheme leaned towards education. Around the type of the sixth edition (RSR6), pulled somewhat the other way and the language and library spec got much bigger. This alienated a lot of folks who wanted to stay a small teaching language.
For RSR7, they tried to resolve that by simply splitting the language in two: a small one and a large one. Then each subcommunity can have what they want.
Around the same time, the language PLTScheme renamed itself to Racket to clarify that they aren't trying to be beholden to the overall direction of the Scheme community. Racket is also a "large Scheme" in that it's a Scheme-derived language that tries really hard to be batteries included for all sorts of uses. It also can be "subset" into smaller languages for use in teaching.
My impression (from far on the outside) is that Racket has taken up a lot of the oxygen, which may partially explain why RSR7-large never managed to reach consensus and ship.
For real world applications rather than education Racket and Clojure as well, in fact Clojure has taken up a lot of the oxygen across a variety of niche FP language eco systems. The Clojure toolchain and library support (much of it through the JVM and Java ecosystem) is excellent and far ahead of Racket for most of the same applications. But Racket starts faster and has a much smaller memory footprint. Depending on your workload and compatibility demands either the one or the other will be a clear favorite with Clojure coming out ahead.
But all of these and scheme (which I think is mostly propped up by virtue of being used a lot in education, I've yet to come across scheme in the wild) are very much niche languages. Clojure really does have an advantage of standing on the shoulders of Java and the JVM, without that I don't think it would have gotten as large as it did.
Traditionally, Scheme is as minimalist as possible by design. Therefore, the very idea of "R7RS-large" is likely controversial to some parties involved.
Apparently it has been an on-going argument for years on just what to include in R7RS-large, as we can see a Reddit thread from 2 years ago asking when it will be ready[0] and John Cowan (the person who is resigning from the committee) saying parts one and two are done and part three should "follow quiuckly thereafter".
> That depends entirely on how much time people can devote to it. The first two parts, Red and Tangerine, are already in place; Orange needs a few things pulled together before it can be voted on, and Amber should follow quickly thereafter.
I'm guessing getting that last 90+% of agreement stretched ever further and further on and as John said in the resignation letter, it was surely exhausting.
[0] https://www.reddit.com/r/scheme/comments/nohfwe/when_will_r7...
I believe r7rs-small was finalized over 10 years ago.
But with the widespread connectivity that we have it is very easy to launch a new language and to gain some small level of adoption. Programming languages are like kids: you can launch them in a night but it takes a lifetime of dedication and support to make them successful and given how hard it is to distinguish a small effort going nowhere from a future winner all this does is saddle up outsiders with the cost of maintenance or ultimately a rewrite in some other, hopefully wider supported language.
It would be great if people would just label their languages clearly as 'experimental, not meant for production' and 'long term supported' up front. Some languages, notably, 'Haskell' are successful in spite of actively holding back large scale adoption. This is a much healthier approach. It shows that the language really has merit.
Do you have any experience reaching to similar organizations? for example reporting compiler or linker bugs or trying to get support for new features or platform that are not well documented? If you don't and think it sounds fun go ahead and have fun if you can do that work without getting dragged into hot conflict.
I honestly don't think there can be any value in a standard that takes so long to come up with. Now in an industry that moves as quickly as this one.
It appears to be an instance of Sayre's Law: https://en.wikipedia.org/wiki/Sayre%27s_law
So, the stakes are very small, in terms of commercial value, but...
If you think of Scheme as an oasis, relative to most popular programming languages and communities, then the stakes can be quite large.
Also, used as a scripting language in the GIMP.
[1] https://en.wikipedia.org/wiki/Hacker_News
[2] https://en.wikipedia.org/wiki/Arc_(programming_language)
These days, I've been using PowerShell for economy data and some options stuff:
If you hadn't gone with Scheme, what's another language you'd have considered for this project?
For example, the MIR formality [0] project of the Rust programming language to formalize MIR (their intermediate language) was first prototyped in Racket [1], then rewritten in Rust. [1]'s readme give a rationale:
> For the time being, the model is implemented in PLT Redex. PLT Redex was chosen because it is ridiculously accessible and fun to use. It lets you write down type system rules and operational semantics and then execute them, using a notation that is very similar to what is commonly used in published papers. You can also write collections of unit tests and fuzz your model by generating test programs automatically.
> The hope is that PLT Redex will prove to be a sufficiently accessible tool that many Rust contributors will be able to understand, play with, and extend the model.
> One downside of PLT Redex is that it doesn't scale naturally to performing proofs. We may choose to port the model to another system at some point, or maintain multiple variants.
[0] https://github.com/rust-lang/a-mir-formality
[1] https://github.com/rust-lang/a-mir-formality/tree/1f40120f09...
The lack of static types was annoying; Typed Racket helped, but was so slow I only enabled it during unit tests (more precisely: Typed Racket functions can be faster than those written in normal Racket, but calling them from normal Racket functions will be slow as it performs run-time checks)
https://github.com/Warbo/theory-exploration-benchmarks/tree/...
I wrote an article about it in Russian (almost 15 years ago), for some reason google translate doesn’t work for archive url: https://web.archive.org/web/20210506123442/http://fprog.ru/2...
scheme@(guile-user) [5]> (exp (* (atan 1) -2))
$9 = 0.20787957635076193
scheme@(guile-user) [5]> (expt 0+1i 0+1i)
$10 = 0.20787957635076193+0.0i
a problem c/c++/java/js/python/rust/go can't handle after decades of progress. even my favorite R can't work this problem. scheme ftw.
>>> from math import atan, exp
>>> exp(atan(1)*-2)
0.20787957635076193
>>> 1j**1j
(0.20787957635076193+0j)
> exp(-2 * atan(1))
[1] 0.2078796
> 1i ** 1i
[1] 0.2078796+0iIs your complaint just that some popular languages don’t have complex numbers as part of the core/stdlib?
Languages that force you to be more verbose and don't let you build your own ultra-powerful abstractions seem to work better for large teams where you can force everyone to adopt a standard style. This makes onboarding much easier too.
I think the same problem applies perfectly well to developers who "create their own little ecosystem of classes and functions nobody else can understand" -- I don't think [0] would be made any harder to understand by having macros involved.
[0]: https://old.reddit.com/r/programming/comments/15s0lp6/how_we... (only picking on it because I saw it recently)
But I guess they look simple and uniform at a superficial, syntactic level. If you can't follow that it's your fault, if you can't follow Lisp code it's Lisp's fault...
Not because of any fault with Scheme per se (afaik), just that contributors to Julia are more likely to know Julia than Scheme, so it makes sense from a maintanence point of view.
R7RS is the Revised⁷ Report on the Algorithmic Language Scheme, the latest common-ground description of the language.
Revisions up to and including R5RS were fairly minimalistic (even if not all of the features new to R5RS are uncontroversial) and specified essentially no library facilities, which were usually either completely implementation-specific or released as RFC-style documents called SRFIs (Scheme requests for implementation). As a result, toy, teaching, or research implementations of Scheme were fairly easy to make, but moving programs between implementations was a bit of a crapshoot.
The reaction to that was R6RS, which is—if not the length of the Common Lisp spec—similar in scope, with utility and OS interface libraries, an extensive macro system, a freshly designed module system, and a lot of other stuff. When SRFIs for the new functionality existed, R6RS certainly took inspiration from them, but its redesigns were neither fully compatible nor taken through the public SRFI process (the standard was still subject to public discussion, but in a different venue with different procedures). And people wanting a minimal standard to implement on their own (a not insubstantial part of Scheme users) were told that R6RS wasn’t for them and pointed back to R5RS.
Long story short, the few commercial Scheme vendors (first of all Chez Scheme, prior to the Cisco acquisition and open-source release) largely adopted R6RS; the rest of the implementor community largely ignored it or cherry-picked some parts—and that means not only the myriad hobby implementations, but also the medium-scale ones like Chicken, Gambit, or Gauche. I think even Guile (whose stance on minimalism mirrors that of most other GNU software) requires some wrangling to get it close to R6RS.
R7RS was intended to close that divide: there’s R7RS-small, which is an R5RS-style lean spec, and R7RS-large, which was intended to be a R6RS-style real-world language, but composed with more respect to existing practice and SRFIs and with more implementor buy-in. It was to be released in several issues organized by topic (data structures, I/O, etc.). John Cowan managed to get a couple of these out the door over the last decade, but the efforts seem to have stalled. AFAIK Chez, the gold standard of real-world implementations how that PLT Scheme has reinvented itself as Racket and gone its own way, has also indicated no interest in even looking at R7RS-large however nice it turns out, because they have customers now and that takes priority over ecosystem health.
Well, sort of. They were running their own base system for a long time, but current Rackets are implemented as extensions of Chez Scheme.
You just summarized the historical reason why LISP and its various incarnations (Scheme among others) failed.
So many different patois, no way to move code from one to the other without giant headaches.
[0] https://practical-scheme.net/gauche/man/gauche-refe/R7RS-lar...
For example, we recently added tuples as a language feature to Dart, and also added a function in the async library that lets you await a tuple of futures in parallel and returns a future of the tuple of the resulting values.
When we added extension methods to the language, we also rolled out some extension methods in the core library.
You may be surprised! For context, R7RS is the latest standard for Scheme. Actually it's two standards: a 'small' one for the core language (similar to R5RS; this was finished a decade ago), whilst this involves the 'large' standard, which is trying to agree on a "standard library".
Some reasons people may have upvoted this, or otherwise be interested in Scheme:
- R7RS has been dragging on for so long, it may be nice to see some/any sort of status update
- Scheme has so many diverse implementations (Racket, Guile, Gambit, Chicken, Chez, Stalin, etc.) that it's really important to have some common standards.
- Scheme was a major influence on Javascript (along with Self)
- Scheme pioneered many features that are now taken for granted, e.g. first-class functions (it's a "1-lisp"), lexical scope, tail-call elimination, continuation-passing style, call/cc, etc.
- Scheme is commonly used as a scripting language by applications written in other languages (similar to Lua). Indeed, Guile is the "official" extension language of the GNU project (e.g. see Guix, Shepherd, etc.).
- Scheme was/is taught at many schools and university courses
- Well-known textbooks like SICP use Scheme; and indeed guide the reader through writing their own implementation!
- Scheme is used for programming language research (e.g. "towers of interpreters", (delimited) continuations, miniKanren, etc.). Indeed Racket used to be called PLT Scheme (PLT = Programming Language Theory)
that's why i upvoted! this is a pretty significant status update if you're interested in r7rs or scheme in general.
Child A: I want the whole pie!
Child B: How about we split it 50/50?
Adult C: You two need to compromise. A gets 75%, B gets 25%.
(I am not implying that any particular persons are A, B, and C here.)
If one could make a wish list it would be the suggestions in Marc's proposal in the chez issue tracker, immutable pairs, immutable strings, and RRB trees in the standard library. Like an opinionated love child racket and Clojure :)
Even though I am more.of an r6rs guy I have always applauded r7rs large. At the same time I am glad you put your own health first. That is always the most important. Apart from the r7rs process, your contributions to all SRFIs I have been following has been amazing.
Take care.
> Clojure really does have an advantage of…
Look, I’m a fan of clojure, I spent two happy years using it. …but it seems obnoxious to bring it up here like this.
Is there really any reason to think that clojure has taken the wind out of the sails of the group of people who were using scheme?
It seems like a massive, totally unsubstantiated take, that really doesn’t add anything here.
We're talking about a minimal dynamically-typed Lisp language and speculating about its challenges around adoption and consensus. Given that Lisps are already a niche language, it's completely germane to bring up another minimal dynamically-typed Lisp that has almost certainly captured some of the overall small potential userbase.
Take a look at the list of proposed features and try to decide if you can clearly bucket them as language or library: https://srfi.schemers.org/
In this case, however, it might be more that there's an innate value that a small number of people recognize as important, so they care about it in a way that seems outsized, to people who aren't aware of that importance.
1. At the REPL, if you type `T` (true), and you get back `T`, the test passes.
2. Define factorial. Then type `(/ (factorial 100) (factorial 99))`. If you get back 100, the test passes.
3. Type `(atanh -2)`. If you get a complex number, the test passes. If you get the correct complex number [namely -0.5493061443340549+1.5707963267948966i] extra credit. Far too many non-Lisp languages return NaN or throw an exception.
When you run e.g. Python, the runtime written in C is indeed being executed. If nothing else in the world was written in C except the Python runtime, IMO it would still be fair to say that C is widely used. A security flaw in C compiler could potentially cause a vulnerability in any Python program.
The question was "is Scheme used for anything in production?" and it is correct to say "yes it is used for HN" even if HN is not directly written in Scheme.
The main benefit of basing Racket on Chez instead of C was maintainability. A bit of performance and a few fairly unimportant features (like single floats) were lost.
> Unless the implementation language is exposed to users of the implemented language, it doesn't matter what the implementation language is.
But Racket can call Chez Scheme procedures, and vice versa.
For that matter, gfortran can call gcc functions.
Even if this were correct, though, my experience is that I find very little enjoyment in things that are targeted at what in your terms is success. For example, Go feels dreadfully unpleasant even though I can't deny the good—occasionally downright brilliant—engineering that went into it, kind of like a mass-produced concrete residential building. Let's be honest, I'm in this largely for the hackery, a little bit for the feeling of having solved somebody's problem, and not in the slightest for the social acceptance. You might not agree here (or you might!), but I hope that, if one day nobody does, I still have the self-awareness to step away from the computer and go do something else.
For me Go feels like Pascal cut off C's face and is wearing it Hannibal Lector style.
That said, it's an absolutely fabulous language, standard library included, for implementing a worldwide ads serving network. Gotta give them that. For other problems that are more or less technically similar it's also great.
The Guix package collection is also sizeable and growing exponentially-- within a few years, it'll probably outgrow most Linux distros in terms of size.
I prefer guix. Every day of the week.
* I really enjoy using numeric towers and it is upsetting to me every time I go to another language where I can't just work with rationals as a default.
* Having statistics functions, a GUI library, and a plot library all part of the standard distribution is wonderful. Dependencies are kept to a minimum, which I appreciate. Everything feels coherent and not over-engineered.
* Poking around in the large standard library was straight forward and not difficult. I added candlesticks [1] to the plot library without understanding much of the plot library's design or implementation details. I think this would have been much more involved in many other languages.
Where I perceive Java as nicer than Racket:
* I wish Racket had real threads like Java. Having futures and places for actual concurrency / parallelism is not as nice.
* I wish Racket had the rich data structures built in as Java has. You need to reach for an external library for a sorted data structure; this is not ideal.
* Java's performance is great and its future is promising. Java already has some great GCs including low pause time GCs, Project Valhalla will add value objects to Java, and Project Loom will enhance the concurrency functionality offered in Java.
I don't have much JavaFX experience, but my perception is that it would be fine and just as "cumbersome" as Racket's GUI and plot libraries.
[1] https://docs.racket-lang.org/plot/renderer2d.html?q=candlest...
-- https://idris2.readthedocs.io/en/latest/faq/faq.html
At this point, the creator has described it as "Pac-Man complete", able and easy to implement a game like Pac Man. (Or itself - it compiles to Scheme but is written in itself.)
Dependent types are still rather new; I believe Idris and its libraries are one of the largest, if not the largest, body of general-purpose software that uses them. (F* maybe?) How to use dependent types properly in a standard library seems be an ongoing development.
(This might sound strange to people unfamiliar with dependently typed langs, but infinite streams etc., servers that "loop forever" doing request-repsonse can still be modeled without TC.)
Many problems are quite challenging.
(-> report
revised
revised
revised
revised
revised
revised
revised) (chain report
(revised _)
(revised _)
...)
There are benefits to this approach, such as it handling both applying returned lists and multiple return values by default. CL-USER 21 > (let ((n 7)
(report '(report)))
(flet ((revise (report)
(cons 'revised report)))
(do ((report report (revise report))
(i 0 (1+ i)))
((= i n) report))))
(REVISED REVISED REVISED REVISED REVISED REVISED REVISED REPORT) (define range+ (make-range-merger +))
(define (double-range range)
(range+ range range))
, which I think is a little nicer than (setf (fdefinition range+)
(make-range-merger #'+))
or having to precede range+ with funcall everywhere I want to use it). (define foo (make-foo))
What is it? A function or a non-function?I prefer the Common Lisp version:
(defvar *foo* (make-foo)
"*foo* is the current input/output foo object.")
It's clear that DEFVAR usually defines a variable and not a function. Bonus: we can document the thing in a standard way.For functions I would define a define macro.
(define foo (make-foo)
"foo is a function with two arguments of type bar, it returns ..."
(ftype (function (bar bar) baz))
Which would expand into a (setf fdefinition), a type declaration and setting the documentation.I prefer the uglier, but better standardized and slightly more practical language.
However it appears that Idris is Turing complete https://cs.stackexchange.com/questions/19577/what-can-idris-... https://gist.github.com/porglezomp/b7bbbecbac1c2289fc890a53d... so I'm confused.
Note also the use of Fuel -- this is to provide "fuel" for the computation, but it's a data structure which can only decrease in 'size' -- which is used by the compiler to prove totality (termination).
("codata" is a way to model 'infinite' computations as data structures.)
It might have been better for you to have been a little more direct-- "I like that exponentiation of complex types just works in Scheme; I don't think that works in other languages!"
I'm not sure why you think scheme is unique in being able to do this-- indeed, it's one of the examples of std::pow on cppreference:
https://en.cppreference.com/w/cpp/numeric/complex/pow
> std::cout << "i^i = " << std::pow(i, i) << '\n';
> i^i = (0.207880,0.000000)
I also hope it wasn't a way to humblebrag that you have a kid in middle school that knows math that lots of other people around here don't (having forgotten it from alg2/precalc or just having trouble reading your comment). Know your audience and prevailing context, and be clear.
Except RISC-V, because RISC-V. Or, I expect, because they must have gathered statistics from a big chunk of real-world (mostly C and -compatible) code and got a bit fat nothing for the usage of the overflow flag—not because it's useless but precisely because you couldn't get at it from (compiler-independent) C.
If floating point extensions aren't present, there aren't even flags.