Изменить стиль страницы

Seibel: Wouldn’t the Haskell guys come back and say, “Yes, that’s our monads and the way that it’s clearly differentiated is in the type system?”

Deutsch: You know, I have never understood Haskell monads. I think I stopped tracking functional languages at ML.

If you look at E—this is not a language that anyone knows about to speak of—it’s this language which is based on a very strong notion of capability. It’s related to Hewitt’s actor languages and it’s related to capability-based operating systems. It has ports, or communication channels, as the fundamental connection between two objects, the idea being that neither end of the connection knows what the other end of the connection is. So this is very different from a pointer, which is uni-directional and where the entity that holds the pointer has a pretty strong idea what’s at the other end of it. It’s based on very strong opacity.

My sort of fuzzy first-order idea is that you have a language in which you have functional computations and you do not have sharing of objects. What you have is some form of serialized ports. Whenever you want to talk to something that you only know by reference, it’s part of the basic nature of the language that you are aware that whatever that thing out there is, it’s something that’s going to be dealing with multiple sources of communications and therefore it has to be expected to serialize or arbitrate or something. There’s no concept of attribute access and certainly no concept of storing into an attribute.

There are languages in which you have opaque APIs so the implementations can maintain invariants; it still doesn’t tell you anything about the larger patterns of communication. For example, one common pattern is, you have an object, you hand it off to some third party, you tell that third party to do certain things to it, and then at some point you ask for that object back. That’s a pattern of sharing. You, the caller, may never have actually given up all pointers to the object that you handed off. But you agree with yourself not to make any references through that pointer until that third party has done whatever you asked them to.

This is a very simple example of a pattern of structuring a program that, if there were a way to express it linguistically, would help people ensure that their code was conformant with their intentions.

Maybe the biggest reason why I haven’t actually undertaken this effort to design a language is that I don’t think I have enough insight to know how to describe patterns of sharing and patterns of communication at a high enough level and in a composable enough way to pull it off. But I think that is why constructing software today is so little better than it was 30 years ago.

My PhD thesis was about proofs of program correctness. I don’t use that term anymore. What I say is you want to have your development system do as much work as possible towards giving you confidence that the code does what you intend it to do.

The old idea of program correctness was that there were these assertions that were your expressions of what you intend the code to do in a way that was mechanically checkable against the code itself. There were lots of problems with that approach. I now think that the path to software that’s more likely to do what we intend it to do lies not through assertions, or inductive assertions, but lies through better, more powerful, deeper declarative notations.

Jim Morris, who’s one of my favorite originators of computer epigrams, once said that a type checker is just a Neanderthal correctness-prover. If there’s going to be a breakthrough, that’s where I see it coming from—from more powerful ways of talking declaratively about how our programs are intended to be structured and what our programs are intended to do.

Seibel: So, for instance, you could somehow express the notion, “I’m passing a reference to this object over to this other subsystem, which is going to frob it for a while and I’m not going to do anything with it until I get it back.”

Deutsch: Yes. There was some experimental work being done at Sun when I was there in the early ’90s on a language that had a concept similar to that in it. And there was a bunch of research done at MIT by Dave Gifford on a language called FX that also tried to be more explicit about the distinction between functional and nonfunctional parts of a computation and to be more explicit about what it meant when a pointer went from somewhere to somewhere.

But I feel like all of this is looking at the issue from a fairly low level. If there are going to be breakthroughs that make it either impossible or unnecessary to build catastrophes like Windows Vista, we will just need new ways of thinking about what programs are and how to put them together.

Seibel: So, despite it not being qualitatively better than Smalltalk, you still like Python better.

Deutsch: I do. There are several reasons. With Python there’s a very clear story of what is a program and what it means to run a program and what it means to be part of a program. There’s a concept of module, and modules declare basically what information they need from other modules. So it’s possible to develop a module or a group of modules and share them with other people and those other people can come along and look at those modules and know pretty much exactly what they depend on and know what their boundaries are.

In Smalltalk it is awkward to do this—if you develop in Smalltalk in the image mode, there never is such a thing as the program as an entity in itself. VisualWorks, which is the ParcPlace Smalltalk, has three or four different concepts of how to make things larger than a single class, and they’ve changed over time and they’re not supported all that well by the development tools, at least not in a very visual way. There’s little machinery for making it clear and explicit and machine-processable what depends on what. So if you’re developing in the image mode, you can’t share anything with anybody other than the whole image.

If you do what’s called filing out—you write out the program in a textual form—you have absolutely no way of knowing whether you can read that program back in again and have it come back and do the same thing that it does because the state of the image is not necessarily one that was produced, or that can be produced, by reading in a set of source code. You might have done arbitrary things in a workspace; you might have static variables whose values have been modified over time. You just don’t know. You can’t reliably draw lines around anything.

I’m on the VisualWorks developers’ list and the stuff that I see coming up over and over again is stuff that cannot happen in languages that don’t use the image concept. The image concept is like a number of other things in the rapid-prototyping, rapid-development world. It’s wonderful for singleperson projects that never go outside that person’s hands. It’s awful if you want software to become an asset; if you want to share software with other people. So I think that’s the real weakness of the Smalltalk development approach and a serious one.

The second reason I like Python is that—and maybe this is just the way my brain has changed over the years—I can’t keep as much stuff in my head as I used to. It’s more important for me to have stuff in front of my face. So the fact that in Smalltalk you effectively cannot put more than one method on the screen at a time drives me nuts. As far as I’m concerned the fact that I edit Python programs with Emacs is an advantage because I can see more than ten lines’ worth at a time.

I’ve talked with the few of my buddies that are still working at VisualWorks about open-sourcing the object engine, the just-in-time code generator, which, even though I wrote it, I still think is better than a lot of what’s out there. Gosh, here we have Smalltalk, which has this really great codegeneration machinery, which is now very mature—it’s about 20 years old and it’s extremely reliable. It’s a relatively simple, relatively retargetable, quite efficient just-in-time code generator that’s designed to work really well with non type-declared languages. On the other hand, here’s Python, which is this wonderful language with these wonderful libraries and a slow-as-mud implementation. Wouldn’t it be nice if we could bring the two together?