One of the enduring lessons from the Racket project is that no full-blown, general-purpose programming language is particularly appropriate for introductory education. By the time a language grows to be useful for building large-scale systems, it tends to have accumulated too many warts, odd corners, and complex features, all of which trip up students. The journal paper for DrScheme (the old name for DrRacket) explains this in some detail.
Indeed, our closest fellow travelers of are the
Racketeers. In fact, the first version of Pyret
was merely a #lang
in Racket. Nevertheless, Pyret represents a
departure from Racket (for now and for the near future, at least) for
several reasons:
#lang
facilities, though designed to create
new languages—and a great prototyping ground for Pyret—proved to not
be quite enough to support a language creation process of the scale
of Pyret; and the need for a strong Web run-time system also meant
that we did not get enough out of the Racket ecosystem (see instead
where we ended up).
Nevertheless, that only represents the state of systems today; if
someday the two grew closer together, many or all of us would
rejoice.Yes.
First of all, Pyret is much more powerful than you might realize. Pyret is already fully-fledged enough to self-host its compiler, which is a non-trivial and realistic challenge. What that means is, when you run Pyret in your browser, it loads JavaScript code that implements a Pyret-to-JavaScript compiler (i.e., it compiles the Pyret you type into JavaScript and runs it in the browser). This compiler was produced by the Pyret-to-JavaScript compiler by compiling the Pyret-to-JavaScript compiler. Take a look at the compiler's bootstrapping phases to get a sense of its sophistication.
Second, underneath Pyret is a very powerful run-time system based on over a decade of research. You don't see it as a user of the language, and that's the point. Many other languages expose the limitations of JavaScript's run-time to users (e.g., can't halt a long-running computation, can't yield control to the event loop, etc.). These languages effectively let the medium become part of the message, whereas we believe programmers — especially early-stage student programmers — should not have to confront these complexities, which are irrelevant to (and often significantly interfere with) the material they are trying to learn. Imagine if other languages said, “We'd love to give you function calls, but your machine's instruction set doesn't contain them, so we can't — sorry!” Yet they do the equivalent when it comes to giving you control over your computation on top of JavaScript. In contrast, Pyret is uncompromising.
Third, if you want to teach a media-rich curriculum, you actually need a pretty full-featured language at least under the hood. For instance, Pyret's built-in support for reactive programming requires a much more sophisticated run-time system — and corresponding language features — than one that didn't offer this at all or just punted to JavaScript for this support. (Essentially, event-loops are first-class entities in the language.) We just haven't emphasized these features when talking about Pyret, focusing instead on the curricula they support.
Broadly, we view building an awesome teaching language as a useful design discipline that necessarily entails all the features typically expected of a mature language. When building a language, you're constantly confronted with questions: what to do next, how to do it, and whether to do it at all. Language designers therefore need a mental framework that guides their choices. For some, it might be “Build an awesome language for shared-memory concurrency!” For others it might be “Build an awesome language for writing scientific computations very, very concisely!” For us, it's “Build an awesome teaching language!” So whenever we're confronted with a design (or implementation) choice, we first ask how it would play out in this specific context. Then we ask how it would impact our long-term goal. We have yet to find actual contradictions between the two, but it's certainly re-ordered priorities.
That's right. We are focused on introductory programming education at the school and college levels, and Pyret is actively being used at these levels. It is used in several “CS 1” and “CS 2” college-level courses. It is also a central part of most of the curricula of the Bootstrap project to teach algebra, data science, AI, physics, and more at the middle- and high-school levels. This gives us a very tight feedback loop.
Of course, even in that setting there are differences of opinion about what needs to be taught. Some believe inheritance is so important it should be taught early in the first semester. We utterly reject this belief (as someone once wisely said, “object-oriented programming does not scale down”: what is the point of teaching classes and inheritance when students have not yet done anything interesting enough to encapsulate or inherit from?). Some have gone so far as to start teaching with Turing Machines. Unsurprisingly, we reject this view as well.
What we do not take a dogmatic stance on is exactly how early state and types should be introduced. Pyret has the usual stateful operations. We discussed this at some length, but eventually decided an introduction to programming must teach state. Pyret also has optional annotations, so different instructors can, depending on their preference, introduce types at different times.
Pyret is driven by the How to Design Programs (HtDP) philosophy of programming education; one could almost view it as a language designed to make teaching from HtDP comfortable. However, we also have our own curricular ideas that extend or run parallel to those of HtDP, which we have published in a self-contained and comprehensive book, A Data-Centric Introduction to Programming (DCIC).
Some of our central ideas (many shared with HtDP) include:
check-expect
family of operations with examples and testing.Yes and no.
Yes in that, broadly speaking, we view what we are doing as very much a research effort. We have specific, novel goals in mind (some of which we've described elsewhere in this document), and finding good solutions to achieve those goals will require innovation. This is the very essence of research. Some of that research is on the curricular side, though, and may not require any language innovation. Indeed, as much as possible we want Pyret to remain a language that is easy to approach and understand.
However, “research” also has a narrow meaning in academia, in the sense of publishing lots of papers. This is an un-goal, and almost an anti-goal. Every paper takes months to write, and those are months we are not spending on the language and curriculum. We view this as a poor time trade-off. We'll write papers sometime, but our immediate focus is on shipping code and textbooks and other materials of immediate value to students and educators. If this means we get “scooped” on some of our technical innovations, that's just fine; we consider that a good trade-off.
Ultimately, though, research requires doing new things. We don't want to do new things just for the sake of it. We've long been inspired by this quote from Paul Graham:
The difference between design and research seems to be a question of new versus good. Design doesn't have to be new, but it has to be good. Research doesn't have to be good, but it has to be new.
For us, design is essential; research is optional. We actively dogfood Pyret both as teachers (actively teaching with it) and as programmers (actively building things with it), which gives us ongoing feedback about its points of friction. Where necessary we have done and will continue to do research, but publishing academic papers about it — rather than putting it to work educationally — will continue to take a back seat.
Pyret has some support for static typing. We chose a conventional type system with tagged unions and a type checker, resulting in straightforward type errors without the complications associated with type inference algorithms. However, there are still some rough edges to the type system. In particular, typing tables is very hard and remains an open problem.
If you'd like to stay abreast of our developments or get involved in our discussions, please come on board!
Because pirates supposedly said “arrr!” (or “yarrr!”) a lot. (Sometimes they sing, too.) Note that you must pronounce it with a guttural sound, so it can't be mistaken for a file written in the R programming language. You should consider swashing your buckler as you speak.
Yes, she's Bonny!
Look closer. It's a lambda.