The Peterman Post
The Peterman Pod
Creator of Scala: Comparing Languages And How AI Will Impact Them | Martin Odersky
0:00
-57:30

Creator of Scala: Comparing Languages And How AI Will Impact Them | Martin Odersky

There are so many choices every programming language creator makes while navigating engineering tradeoffs in building one.

This made me curious about Martin Odersky’s (the creator of Scala) thoughts comparing different languages. His deep domain expertise made his responses comparing Rust, Zig, Python and Scala interesting.

He also had a lot to say about how AI will impact programming language ecosystems in the future. For instance, he talked about some research he was working on to strengthen the static guarantees programming languages give to provide more safeguards for LLMs.

Hope you enjoy the conversation!

Check out the episode wherever you get your podcasts: YouTube, Spotify, Apple Podcasts.

Timestamps

00:44 - Why care about functional programming

06:35 - Why should people learn Scala

09:26 - Rust vs Scala

12:42 - Rust vs Zig

15:45 - Scala vs Python

18:31 - The programming languages that influenced him

22:16 - How running on the JVM works

26:33 - Why writing a compiler is hard

29:19 - Why Twitter adopted Scala early on

31:00 - How he believes AI will impact programming languages

43:40 - Will there be less engineers in ten years

44:34 - Top programming languages to learn to grow

46:18 - Top technical book recommendation

46:51 - Why he chose academia instead of industry

48:28 - Reflecting on Scala

55:42 - Advice for his younger self

Transcript

00:44 — Why care about functional programming

Ryan:

[00:44] What is functional programming? And why should an imperative programmer care about the functional way of programming?

Martin:

[00:52] So functional programming is programming with values, so you don’t have state that changes, like mutable variables that change or arrays that change. You have values and you have functions, and the functions transform these values into other values. So it’s a very restricted form of programming. And most real functional programming languages are impure in the sense that, yes, of course, at some point you have to touch state and change things and write to standard out and things like that.

[01:24] But the idea is to do that sort of very late, so to have the largest part of your program represented as values and functions that transform values. And the benefit you get from that is essentially much better predictability and fewer bugs, because these side effects to, let’s say, a global variable or a field in some object graph or things like that, they can really trip you up. They can essentially, they’re an undocumented effect of your function, so it’s not reflected anywhere typically.

[01:57] But maybe you have a comment if things are good. And these things are very hard to keep in your head and generally reason about. So the advice from functional programming is essentially to keep these things to the bare minimum and possibly to nothing if your function maps into these things. The other reason why functional programming is nice is that it’s very directly linked to mathematics. So in mathematics you have theories of, let’s say, polynomials or strings or lists or things like that.

[02:33] And in none of these theories will you find the concept of mutation; that just doesn’t exist. So you can take a polynomial and you can transform it into a new polynomial, but you can’t change a coefficient at 0.3 at the third coefficient and pretend it’s the same polynomial. It’s not in mathematics, right? It’s clearly something different. So functional programming, you could say, follows quite closely the way mathematics sees things.

Ryan:

[02:58] What would you say to someone that doesn’t do functional programming because it’s not convenient?

Martin:

[03:04] I guess two things. One is it’s a learning curve. So initially your brain is wired to do imperative programming from when you were very young. I imagine most people learned an imperative language first, and then it’s hard to see how you would express things differently. But if you persist in that a little bit, and it doesn’t really take much, then you will essentially reap the benefits very quickly, that you say, well, actually my program got a lot clearer.

[03:36] I can understand it better. I don’t really have to track some steps, go step by step through my program with a debugger or things like that to figure out what it does. Typically I don’t need a debugger when I write functional code. That’s really not necessary. The other thing is to essentially know when to stop. So there is a strand of functional programming called pure function programming, which tries to express as much as possible in pure functions and to delay the side effects and wrap them up in monads or whatnot.

[04:15] And that can get very inconvenient very quickly. So my answer to that would be, it really depends. And in most cases, it’s completely okay to have your side effects as long as these are well documented and you use them. So basically, use these things in moderation. I would say functional programming is great for 95% of your program, and if you need some side effect, some imperative feature, for the last 5%, that’s also okay.

Ryan:

[04:45] Is there any quantitative measure of the, I guess, the correctness benefits that functional programming gives you over imperative?

Martin:

[04:56] I think there are some studies. It’s not quite clear how significant they are. I think people criticize them a lot. The studies tend to say that a language like Scala would have fewer bugs than a language like C/C++. But I don’t really want to insist on that because these studies are very hard to do, and the methodology is very hard to get right. I believe the effects become more important in large programs than in small ones.

[05:28] For small ones, you can do anything, really. You can write a loop, you can write a recursive function. It doesn’t really matter. And it’s very much a matter of taste which one you prefer. But in a large system, I believe static types have certainly proven their worth, even if we don’t really have a conclusive study that shows it. I mean, I can point you to a study, and if you’re a dynamic typing enthusiast, then you will point to another that essentially claims the opposite.

[05:59] So it’s very, very hard to do empirical software engineering on that scale. And so I’m afraid I can’t really give a good answer. I just have a feeling that mostly functional statically typed languages is sort of a sweet spot for getting programs right. Maybe the other thing is when you really need to get them absolutely right, like with proofs and things like that. If you do Rocq or Lean or any of these things, these are all functional languages.

[06:29] So people wouldn’t even attempt to do something like C/C++ here.

06:35 — Why should people learn Scala

Ryan:

[06:35] When you think about Scala in the environment of all programming languages, what sets Scala apart? Or maybe put it another way, why should someone learn Scala in 2026?

Martin:

[06:47] Well, Scala is the only functional language that is also a very capable object-oriented language. In fact, it was born by the idea that we can actually make a fusion of the two in a way which is not side by side, but which really combines the features in a nice synthesis. So that was what Scala was about. That’s what I wanted to show, and that’s been largely successful. So you can write really beautiful programs in this combination.

[07:19] Object-oriented programming comes in when you talk about components and modules and essentially encapsulation, these sort of things where functional programming typically doesn’t really have a very strong story. I mean, there are languages like Standard ML or OCaml that do have very capable module systems, but other functional languages don’t. And people, when they think of functional programming, they don’t really think much about components and interfaces and these sort of things, which are things that I believe also matter very much.

Ryan:

[07:50] Could you give an example? Maybe an object-oriented thing that you could do in Scala, but you couldn’t do in Haskell, which is pure functional.

Martin:

[08:00] It’s sort of ingrained in the whole fabric of the thing that everything is essentially objects, what you do. So one thing that you get is what I think Simon Peyton Jones called the power of the dot, that you say it’s super convenient. You have an object and then you do dot, and then you have the environment that immediately tells you what are the methods and fields of that object, that you can use them.

[08:24] So it focuses your mind. Whereas in functional programming, it’s typically you have a sea of functions that can be applied to arguments, and you have to figure out what they are.

Ryan:

[08:34] When you think about the systems programming languages like Rust, Zig, Go, C/C++, in your opinion, which one would you say is kind of the best one? And then maybe we can compare it to Scala.

Martin:

[08:46] In this day and age, systems programming languages need to be memory safe, guaranteed memory safe. So that would already exclude quite a few of them, but it would leave Rust and Go, I think. And Rust and Go are at different levels. Go is really not a sort of nuts-and-bolts systems programming language. This is more a language in which you would write, let’s say, an application server or some middleware or some cloud infrastructure, or things like that.

[09:13] It’s not something you would use for embedded, say, which you would use Rust for. So I think in the domain, both of them are probably the ones that are the leading ones that I would take most seriously.

09:26 — Rust vs Scala

Ryan:

[09:26] And then when you compare Rust or Go with Scala, what are the pros and cons of the different language designs? What’s something that Rust does better than Scala? Something Scala does better than Rust.

Martin:

[09:40] So Rust is closer to the metal, you have better performance guarantees. I guess the fact that Scala is a garbage-collected language means that you always have some pauses. I mean, garbage collectors have become quite, quite capable. I mean, they’re brilliant and the pauses are really very, very small. But it’s a fact that you do need a big chunk of memory to run fast, and I guess Rust could run in much smaller memory.

[10:08] So I believe that’s better for embedded systems and things like that. I believe right now Rust is actually overused because a lot of people push Rust for things higher up in the stack where your garbage collector is fine. But essentially, you still want to write code without, and that is for me a bit an exercise in, I don’t know, just intellectual that I can do it.

[10:37] I don’t really think there’s a big sense in it to write memory management for a garbage collector. You should absolutely use one because it makes a lot of things simpler. So yes, of course, if given enough brains, I can write code around it, and I can do that. But why should you? I mean, it can be much simpler. So that was for Rust, for Go. Go is sort of a language that lags behind. I mean, it was intentionally designed to be very, very small and essentially to be the standards of the ‘90s.

[11:15] So now they have gotten generics, which is a big step. So I believe that sort of is a step forward for that. But it’s still a fairly limited language. What you can do, which has an advantage that essentially it forces a very uniform style because there’s not much different things you can do. And there’s probably a culture fostered to do things in a certain way, which makes it easier to essentially read one another’s programs and essentially jump in a new code base and things like that.

[11:47] So I think that would be my main advantage of Go that I see there.

Ryan:

[11:51] Is it possible to turn off the garbage collector in Scala?

Martin:

[11:55] Not in production. So we have some research that would let you use essentially your own memory allocators and things like that, the way let’s say Zig does it. The problem with that is always that you can leak references into memory that you reclaim, and then all hell breaks loose. Essentially, your pointers, you point to memory that’s undefined. But in Scala we now have a very good way to actually track these references, so we can actually prevent that statically by the type system, that this will never happen, and you can still have your own allocator.

[12:36] That said, we haven’t really shipped that in production yet. So right now I would say you use the garbage collector. Scala.

12:42 — Rust vs Zig

Ryan:

[12:42] Yeah, I see a lot on the Internet, people comparing Rust and Zig, or kind of a fierce debate on which one is better. When you think about Rust versus Zig, what are the merits of the two compared to each other?

Martin:

[12:58] So what I can see is Zig has a really nifty compile-time construct, essentially inlining, where the compiler does smart inlining, and that is quite clean and quite powerful. And Rust has macros, but I think they’re more clunky than the Zig version. In Scala, we have something quite close to Zig. We also have essentially a thing that’s based on inlining and optimizations by the compiler. But we have a restriction, which I believe Zig doesn’t have, and that is that there cannot be additional type errors after inlining.

[13:41] So the thing is, you inline, and then the question is: Is the inline program guaranteed correct, so type-correct, or might you have type errors? The typical example where you might have type errors is C++ templates. In fact, that’s quite scary in C++ that you can expand a template, and then you get very, very complex type errors and very, very hard-to-debug things. So Zig, I believe, its inlining mechanism is much saner.

Ryan:

[14:10] When you say inlining, can you explain the concept?

Martin:

[14:13] Inlining just means that in Scala we can write `inline` in front of a function, and that means that the compiler will, before it starts code generating, during the time when it looks at the type code, which are trees, take the function body. When it sees a function call to that function, it will take the call and replace it by the body, and then it will do some optimizations. It can say, okay, so here we have essentially an application to, let’s say, a value which is a lambda, but I know where the lambda points to, so let me forward the call right to the function.

[14:54] And with that you can already do quite a bit of essentially optimizations, which are guaranteed because the inliner must inline. That’s not a thing. An optimizer has essentially discretion whether they want to inline things or not, and so you can never rely on that. But an inliner, which is essentially a compile-time based on the typer, must inline, so you can rely on it, and constexpr in Zig and C is essentially very similar.

Ryan:

[15:25] Okay, so it’s a way to get rid of the function call, or the overhead of a function call, and tell the compiler you can do more because it’s all, I guess, inline.

Martin:

[15:37] Yeah, you reveal the implementation, and that means the compiler can do something with that.

15:45 — Scala vs Python

Ryan:

[15:45] When you think about all the dynamically typed languages, which one stands out as one that you think is kind of the best among them?

Martin:

[15:53] Python is ubiquitous, and it has a nice syntax. A lot of Python programs look like they’re very easy to read, so that’s definitely an advantage. And the other one would probably be something like Scheme, which is sort of very grounded in computer science theory and lambda calculus and things like that. So both of them are sort of interesting in their own way. But of course Python is 100 times more popular.

Ryan:

[16:23] If you compare Scala to Python, for instance, I guess what are the trade-offs that the two languages take?

Martin:

[16:30] I think the gap is closing because Python now actually has an optional type syntax and a number of type checkers that check that syntax. And Python is getting some of the features that Scala had since the beginning, like pattern matching is in one of the recent Pythons. So I think actually the gap is closing not just between Python and Scala, but between a lot of programming languages in general. They’re sort of all drifting to a standard set of features, which mostly come from functional programming.

[17:01] Actually, pattern matching, for instance, strong type systems, generics, polymorphism, all these things came from closures, all these things came from functional programming. And so the gap is closing in that sense. Python is, I think the main advantage of Scala over Python is that it has a strong type system that is always on, and that gives you essentially guarantees that certain bad states can’t happen.

[17:34] So really you can rely on it. Whereas I think the Python type system, well, it’s just syntax. It has a number of type checkers, but in general you have fewer guarantees. And I believe it’s also the ecosystem and culture that doesn’t value types as much in Python. So I think that’s probably the main difference syntactically. The two languages, I think with Scala 3, are actually also quite close.

[17:59] So Scala 3 looks a lot like Python in that sense. You could say, well, you can see it as a language that has strong types and runs on different runtimes than Python. Or I should say the other thing with Python, which is really great, is that Python is a fantastic glue language because I can essentially have very, very efficient linkages to high-performance C libraries, pandas or NumPy or things like that.

18:31 — The programming languages that influenced him

Ryan:

[18:31] You mentioned that a lot of the programming languages, they’re kind of drifting or kind of being inspired by the other ones and adopting new features. In the design of Scala, is there a programming language that you admire most and influences Scala the most?

Martin:

[18:48] Historically, Scala was essentially, you could say it was a blend of Java, OCaml, and Standard ML, which is close, an ML-like language, and Haskell. So I’m by trade an imperative programmer. PhD is from Niklaus Wirth. I know Pascal, Modula. That was sort of my first generation of languages, and I like them a lot. And then I became sort of a converted functional programmer. So I looked very closely at ML, OCaml, Haskell, and these things.

[19:23] And then Scala came about. There was a predecessor language called Pizza, and I was working on that with Phil Wadler, who’s one of the original Haskell designers. And the idea was to have essentially an accessible functional language on a very widespread platform, which was the JVM at that point. And in order to prepare for that, I wrote a Java compiler. So that’s how I learned a lot about Java and what Java was.

[19:53] And in the end I had to say, well, it’s actually quite useful. I was quite dismissive at first, but afterward I found it actually quite useful. I mean, this was very early Java, this was Java, even pre-1.0. So now Java is, of course, even more useful, but also a lot bigger than what it was at the time. So when we came up with Scala, which was sort of the second iteration after Pizza, Pizza was the language I did with Phil Wadler.

[20:24] The ideas came mostly from Java, OCaml for the modules and the component model, and Haskell a lot for the standard libraries. So if you look at the function names in the Scala standard library, then there’s sort of a mixture of OCaml and Haskell, you could say, but you recognize a lot coming from both of these languages.

Ryan:

[20:48] If I recall correctly, Java had some sort of licensing with it, or it was owned by a company. How were you able to build on top of Java? Or did you have to pay for licenses, or how’d that ecosystem work?

Martin:

[21:05] The language standard was open source. There was a lot of experimentation with Java at the time. I think the only thing that Sun, that was the company at the time, they’re very particular about, is that if you did something that was using Java and had Java in it, you had to call it Java, and you couldn’t have a different name. So that’s why initially, for instance, Microsoft clashed with them, and then Microsoft went away and designed C#, which was sort of a.

[21:40] Java, some steroids. They threw in a bit more than what Java had. At the time, I think the nastiness came, Sun was actually quite an open company. So at the time, we were not worried about that. So that was in the time frame from 1998 to 2004, 2005, something like that. And at the time, there was no issue. I think the issue came later when Sun was acquired by Oracle and Google forked Scala on Android.

[22:11] Java on Android, and that’s when the fight started, but that was much later.

22:16 — How running on the JVM works

Ryan:

[22:16] So when you say that Scala was using the JVM or built on top of it, like concretely in the tech stack, what does it mean that Scala uses the JVM? Like, how does Java source code eventually execute on a machine?

Martin:

[22:32] So the JVM is essentially defined by its bytecode. The bytecode is essentially an intermediate format which you can translate your program into. And then the bytecode is run first by an interpreter and then essentially by an optimized compiler, just in time. Compiler JIT. So that’s called JIT. They do that. And so if you know how to output bytecode, and that’s not very hard, then you can run on the JVM.

[23:06] So that’s essentially the idea. The harder part then is interop, that you say, okay, I run on the JVM. I have to make sense of all these Java libraries out there. So I have to somehow map a Java concept into a Scala concept so that the compiler can understand what it is and I can document what it is for Scala programmers that maybe don’t understand much Java. So that is sort of work that sort of goes more into the details.

[23:35] That said, I mean, that’s not the only Scala platform, so it was born on the JVM, but now it also exists on JavaScript and Node.js, on WASM and on Scala Native. So it’s really a multi-platform language.

Ryan:

[25:05] Let’s say I write a Scala program. I have the source code, I have to compile it, and then I have some Java bytecode, and then I call the JVM and I pass in this bytecode, and it just works.

Martin:

[25:19] Yeah, exactly.

Ryan:

[25:21] What would the advantage be of compiling Scala to Java bytecode instead of doing something like C/C++ where you compile it all the way to machine code from source?

Martin:

[25:33] We have that too. So Scala Native compiles directly using LLVM to native code. The advantages of compiling to bytecode is essentially, again, the interop can use all the Java libraries, then the garbage collectors. So the JVM has actually very good garbage collectors, high-performance ones, and the runtime loading. So what I can do on the JVM is I can compile, let’s say, a one-line thing into a little Java bytecode, and I can immediately load that bytecode and execute that.

[26:13] And that makes it very easy, for instance, to have a REPL, because that’s how a REPL would work, a read-eval-print loop. So I would just generate a snippet of Scala code to bytecode, load it into the running JVM process, and it gets executed. And that’s much harder if you go to binaries; basically, binaries don’t really have a concept for that.

26:33 — Why writing a compiler is hard

Ryan:

[26:33] You mentioned that you wrote a compiler for Java before Scala, and I’ve heard that compilers are notoriously hard to build. Can you explain the hard parts and why they’re hard?

Martin:

[26:46] Compilers are very intricate because I think there are a lot of requirements on a compiler. So you have languages which are already complex artifacts. Then you have a thing called type inference, so you have a type system, but essentially you want the compiler to infer a lot of types that make sense. Because you as a programmer think, well, the compiler should know that, and it should, but actually for the compiler to do that is quite hard.

[27:21] And then, of course, you also demand that it would generate very efficient code for your program, because again, the compiler should know that, right? So there are a lot of demands on that. Plus, there’s a demand that it should be very, very fast. And to square all these demands requires quite a bit of work, basically. There are also things that make it easier for compilers because they’re fundamentally deterministic programs.

[27:47] So essentially, you run a compiler on a source, and you always get the same output, so it means they’re easier to debug. You can just replay things and repeat things. Whereas if I would have some cloud service or distributed application that has other nightmares, right? Every run is different, and how do you even figure out what goes wrong?

Ryan:

[28:07] So when you wrote that compiler, I think Espresso for Java, how long did it take to write that by hand?

Martin:

[28:16] At the time, it took me about three months, I think. Not full time, maybe half time. Three months, half time, something like that. But that was a very simple compiler. So that’s the other thing with compilers: they typically start simple, and when you’re at the 10-year mark or 20-year mark, then there’s lots and lots of essentially other requirements to a compiler that make them more complex.

Ryan:

[28:37] Were there libraries that you could rely on to kind of piece together components of it, or did you have to write everything from scratch?

Martin:

[28:47] There was a library to generate bytecode, I think. I think I used that in that version. Yeah, I did, yeah. So there was a library, essentially a high-level library, to just assemble bytecode and put them into the right format and things like that. But that was essentially it. The rest I wrote by hand.

Ryan:

[29:07] That’s crazy because, well, I mean, these days a lot of people, even more so now, we’re thinking less about using AI and more about kind of writing the code. So that’s pretty impressive.

29:19 — Why Twitter adopted Scala early on

[29:19] I saw one of the big, I guess, moments for Scala was that Twitter adopted it, and I wanted to know the story behind that. How did they choose such an obscure language at that time?

Martin:

[29:30] It was very obscure at the time, that’s true. So I believe the story was Twitter originally was written in Ruby, and it wasn’t very reliable because I believe it’s again a problem with garbage collector and memory management and things like that. And it was a small company at the time, so 25 people, including the ops people, and essentially the board and VC investors said you can’t go on like this, being unreliable like that.

[30:03] You should do Java, because Java was sort of the solid choice at the time. But some of the engineers at Twitter, they wanted essentially something more fancy as a programming language. And there are some people who knew OCaml and liked OCaml, but of course OCaml didn’t run on the JVM. And then they found Scala and said, well, Scala is actually quite a lot like OCaml and we can tell our investors that we do Java because it’s not a lie, we do JVM bytecode.

[30:33] And that’s essentially what it comes down to. So that’s why they picked it. And they were quite the first. But once they picked it, sort of the floodgates opened because at that time they were a very interesting company and a lot of people admired them. So a lot of people followed and did the same thing. Mostly they came from dynamic languages, so Twitter came from Ruby, others came from PHP or JavaScript, things like that.

31:00 — How he believes AI will impact programming languages

Ryan:

[31:00] I mentioned a little bit that AI is kind of generating a lot of code, and I wanted to ask you what you thought maybe the future of programming languages might look like if you speculated or drew it out further into the future. If AI is generating more of the code, how do you think that might affect the programming language ecosystem?

Martin:

[31:22] Yeah, I think right now we’re sort of in an existential crisis, right? So we have AI generating the code, but humans being asked impossible tasks, like to review all these mountains of code and things like that, which will never work. And at the same time, AI has also gotten extremely good at exploiting vulnerabilities in code, like we all heard of Fable and things like that, that you can’t use it anymore because it’s too dangerous. It will exploit things.

[31:53] So we are at a moment where it’s essentially very dangerous that we lose control as humans of what actually happens here. And that’s a challenge that I think programming languages can help meet. And probably definitely not only programming languages, that’s not a silver bullet, but they definitely can help things. So I think one of the things is that the focus, if the code is AI-generated, then the focus has to go elsewhere.

[32:26] And I think the focus will go to the interfaces and to the types. So I expect types will become a lot stronger and more precise than what we had. Because types are essentially the handle that we can make a contract between the human and the AI that the human can understand and that’s concise enough to be reviewed and that essentially the AI can keep to. We have to level our game quite a lot because right now, I mean, let’s face it, type systems are mostly recommendations. They’re mostly things that mostly hold, but not always. There are no guarantees because you can always have a cast or value, you use some dirty memory or.

[33:13] I mean there are a number of techniques to undermine the type systems, and we have to close all these holes from the beginning because once there is a hole, somebody can exploit it. So I think strong types, strong high-level types, will help. And then I think the other part is generally the programmer has to think much more about what the requirements are and what are essentially the high-level specifications and be able to leave the code to be generated by somebody else in confidence.

[33:50] And I think we’re not quite there yet, but we have some ideas about how we could get there. So one technique that I believe we can use, and it has been around for a long time, but maybe its time has come now, is capabilities. Capabilities essentially were used in operating systems to give very fine-grained permissions to entities, users, programs, and things like that. And I believe that can be used also for agents and agentic AI to say, well, once we have agents, we have to give agents very precise and fine-grained capabilities for what they can do, and that lets us essentially be confident about what they will not be able to do.

[34:34] They will not be able to leak my API keys or my email or do other things. So I think that’s an important part. And the existing languages are not there yet. I think Scala is halfway there. At least it’s there in essentially stuff we’re working on, which we have in the lab and we have released as an experimental feature. So I’m quite excited about that. The first thing that you have to do is definitely be memory safe.

[35:08] So a language that essentially is not memory safe, that lets you essentially access undefined memory, is immediately out because you can’t guarantee anything. So that’s. In that sense, it’s good that there is a drive to use, let’s say, Rust as a memory-safe language that was even promoted by the American government, I believe. So that’s definitely a very useful drive. But I think you need a lot more, because you need much.

[35:36] Rust talks essentially mostly or only about memory. You need to talk about a lot more things than memory. You need about essentially read permissions, write permissions, access to secrets, all these things that go beyond that. And you could say, okay, Martin, you’re totally unrealistic because all our software is written in C/C++ and we will not be able to rewrite that. But I believe AIs can help there, right?

[36:09] So AIs are great in rewriting software. So if we know what to rewrite, too, I think we might be able to get there.

Ryan:

[36:17] You mentioned some of those experimental features in Scala that might have some sort of safety guarantees or signal capabilities. Can you explain what that might look like, or maybe give an example?

Martin:

[36:30] So a simple example would be, let’s say somebody gives me a file and I have access to the file, let’s say a log file or something like that. I have access to a file for a limited time, and then I need to close it. So typically I have an operation that essentially somebody passes a file to me, to an operation that my program provides, and the program does something with a file, and then the environment will close it.

[36:59] But how do we make sure that I don’t hold on to the file after I gave it back to the environment, or after I pretended I’m finished with it? Because, hey, I have a file, I could have stored it in a variable, I could have stored it on the side, I could have gone back to it and done something with it. So capabilities help me prevent that because essentially I can say, okay, so this file is a capability.

[37:23] And then I can further say, well, this capability can be used only in a limited scope, and the type system will make sure that the capability doesn’t escape. And the way we do that is that if a type refers to capabilities. So if I have a thing that I say, I give you back a lambda or a stream and it holds onto the file. So the stream holds onto the file in secret. In our language, that won’t be a secret anymore because the type has to declare that the thing I return does hold on to the file.

[37:56] The file is a capability, and I can’t essentially hide capabilities I have access to in my type. I have to declare them. And that gives me essentially this control that then I can also enforce, to say, well, at this point you’re not allowed to have any capability because the type that I enforce you to have is a type that doesn’t hold capabilities. And that way I enforce with the type system something which previously hasn’t really been enforceable for memory safety.

[38:26] It’s essentially the same thing with arenas, that I have an area where I allocate memory and then I want to get rid of it. I have to make sure I don’t have pointers pointing into it. And that’s exactly the same situation, and let’s say for accessing secrets again. So it’s a very common pattern that I say in certain situations I want to make sure that you don’t have, or that you only have a set of defined capabilities that I give you, and nothing else.

Ryan:

[38:57] You mentioned memory safety is an absolute table stakes. What are the programming languages that you think of that are not memory safe? I know there’s C/C++, but what are the other ones?

Martin:

[39:08] The big ones are C. I don’t know about. I think Zig or Nim or other low-level systems languages are not memory safe. So that was sort of in Rust, the big achievement, that you can be a low-level systems language and be memory safe. Nobody sort of thought that was possible before Rust came. So that’s why I would think, I don’t want to say anything wrong, but I would think that essentially most other low-level systems languages would not be memory safe.

[39:40] But you really need more than memory safety. You really need capability safety, that you say, when I essentially hang on to something, I can’t sort of forget capabilities to say I hang on to something and I just conveniently forget that I have access to that. And I can’t forge capabilities to say, well, if I need a capability, I just make one up. These two things need to be prevented. And that goes beyond memory safety.

[40:07] But memory safety without memory safety, essentially you have nothing because you can fake everything.

Ryan:

[40:12] A lot of programming language design and how we write code in the past is writing the source code so that it’s nice for humans to read. But if humans are no longer interacting with the code, what kind of things come to mind that we might not care as much about but are good for machines to read?

Martin:

[40:34] For instance, the first thing is maybe sometimes you want to read it, but you probably wouldn’t have written it. So easy to write is definitely not a big criterion anymore. Easy to read to some degree, yes, but that means you don’t need any of these sort of syntactic hacks, like to write plus plus in C or things like that. That’s easy to write, right? But I don’t, I mean I’m sure we will still have that, but it doesn’t really matter anymore.

[41:03] I mean, whether I write an assignment in long form or with X, whatever. So I think these things won’t matter much less. The things that matter much more are, that continue to matter, and are essentially high-level ways to constrain and specify what my program should do. So constrain what it should not do, that’s one of the things. And also specify what it should do. And I mean some people say a golden age for formal verification because we can be very precise in our specifications, and our AI can actually not just furnish the program, but also the proof that the program actually meets the specification.

[41:48] And I think that’s true. That’s really very exciting in a lot of areas. But in the large, the problem is you often don’t really have the formal specification, or it’s just as hard to write a formal specification than to write a program, or sometimes even harder. So that means that we will still live in a world where we specify things by natural language, by prompt to the agent, and the agent then will do the code.

[42:16] But I imagine that also that will be a lot more formal in a way. So in a sense right now the prompts, I mean, it’s fantastic what they can do with the prompts, but then we throw away the prompt or it’s hidden in the chat history with the agent. So that’s really a shame. So I really should have the prompts as first-class values in my program, that I can say, well, essentially that’s what the program is about, and if I change the prompt, then the AI will know essentially what the incremental change was and change the program incrementally, these sort of things.

[42:51] That’s another thing that I think we’ll see in future programming languages for agentic programming.

Ryan:

[42:57] Maybe some kind of meta information about the program, almost like a Git blame, but like a prompt, I guess, blame of what generated that part of the code.

Martin:

[43:11] You should be able to keep that around and come back to it. Yeah. Also because you might want to change, right? You might want to say, well, now it’s exactly the same, but I want to change this little detail. But I don’t want the LLM nondeterministically to generate a new program because that way it might get a lot of other things wrong that I reviewed already. So there really should then be an incremental small change to the code, and that means I need to keep the prompt as a part of my program.

43:40 — Will there be less engineers in ten years

Ryan:

[43:40] Ten years from now, do you think there will be more software engineers than today or less?

Martin:

[43:46] I think there will be less. And it will be a higher profession that essentially has higher standards. So it will be harder to become one. You will need to know quite a lot of logic and math to be competent at essentially keeping AI on the right track and things like that. It’s sort of, I can say, sort of like a control engineer for a factory where you don’t understand many things initially. It means that there must be more—you must be higher skilled than a factory worker of 50 years ago or something like that.

[44:27] And I think the same will happen for software, where you will need fewer but more qualified people.

44:34 — Top programming languages to learn to grow

Ryan:

[44:34] One thing that a lot of people recommend is to become better at programming: you should learn multiple languages. And I wanted to know, aside from Scala, what are the top programming languages you would recommend people learn to expand their mind?

Martin:

[44:49] So definitely a systems language. I think to know how hardware works and how software links with hardware, I would learn a systems language. I’m sort of torn between C and Rust there because C has going for it that it’s very simple and very close to the metal. In Rust, you have to learn a lot of abstractions, but on the other hand, it is memory safe. So I would say probably initially C, to figure out what these things are.

[45:17] And then if you decide to become a systems programmer as a career, then you should switch to Rust. I guess that would be one thing. The other thing would be something more with a verification, improving background because that will be a lot more, will become a lot more important. So I would actually do a course in Lean or Rocq, one of these languages, to say we. We should be able to use AI or to.

[45:48] To have to develop first an intuition what it means for a program to be correct, because I guess for most people have only a very, very fuzzy intuition for these things. And learning one of these languages would sharpen the mind. Yeah, so I think those. And then, of course, Scala too as a language that essentially sits right in the middle where fairly provable, strong types, high expressivity, these sort of things.

46:18 — Top technical book recommendation

Ryan:

[46:18] When you think of a top technical book that you might recommend to people, does anything come to mind?

Martin:

[46:23] I got a lot out of Structure and Interpretation of Computer Programs. That was a book from the 90s. It was an intro text at MIT at the time, or 80s even, I think. And in fact, the courses I taught on Coursera and at EPFL are based quite a lot. Well, to some degree they’re based on that material. So, of course, not the same language and strong types instead of dynamically typed.

46:51 — Why he chose academia instead of industry

Ryan:

[46:51] But still, when you look back on your career, why did you choose to work in academia instead of industry?

Martin:

[46:57] When I came to the end of my studies, I was asked to do a research project, and the project I picked, or the professor then asked me to modulate that a little bit. In the end, I found it super interesting to say I work on something that I don’t know whether it has a solution or not. So it might be that. The question is yes, it might be. The question is no, we have to do research, and that’s sort of how it started.

[47:24] And then I believe the main advantage of being in academia is really the long term and being independent. So in the long term, I mean, in industry, I’m sure there are many periods, including now, where I could be paid 10 times what I’m being paid at university if I joined Google or any of the other companies in Silicon Valley. But then times also change, and sometimes essentially what you do is no longer relevant, and then it’s very easy to get fired. And then you say, no big deal, I can do something else.

[48:00] But at a university you have essentially long-term tenure to do exactly what you want. So no manager, you can define your own research agenda. Of course you have to get some money. That is hard. You have to get grants and things like that. You have to convince students that what you do is the right thing. But that’s also very rewarding, working with students. So I think in the end I’m very happy that I took the career I took.

48:28 — Reflecting on Scala

Ryan:

[48:28] What about looking back on Scala? You have so much experience there. What are some things that went well or things that didn’t go well, and maybe some learnings you could share?

Martin:

[48:39] Scala was initially this experiment that we could combine object-oriented and functional programming. And technically that experiment was a big success. In terms of the ecosystem, it had a lot of challenges. I don’t know whether there was A Brief, Incomplete, and Mostly Wrong History of Programming Languages by James Iry, which is quite hilarious. And there’s a Scala entry there that says I discovered Reese’s Peanut Butter Cups.

[49:07] And I had an idea to essentially have a language where you put in both object-oriented and functional, and then it ends with these pieces of both communities. And they promptly declared jihad. And at the beginning, it was very funny. But in retrospect, that’s to a large degree what happened. I mean, there were a lot of fights and cultural things like that, and it was a challenge. And I don’t know, in retrospect, I think it might have been more prudent to be more careful introducing functional features because that sort of was.

[49:51] We went in essentially quite complete. So essentially you can port most Haskell programs to Scala, maybe that you find them a bit less attractive looking, but you can do it. And that brought in essentially different cultures. And it caused a big clash of cultures. So, for instance, in Go, Go was a lot maligned because they didn’t even have generics. Right. And it’s true, it was a ridiculous language, but by not having it initially you sort of form a culture that when you add it, nothing much will go wrong.

[50:30] And people want to over-abstract or things like that. And by essentially going full hog into it with Scala from the start, we were not protected against that. And people did reach abstraction peaks and over-abstract it and things like that, and they still do it to this very day. So essentially having fancy abstractions is great, but you have to use them responsibly. And then it sort of clashes with the natural urge to just try out all these fancy things and do something that in the end maybe neither you nor nobody else understands very well.

[51:05] And it could have just been a simple map or things like that. But yeah, why do I use that when it can be complicated?

Ryan:

[51:13] Why would that upset someone?

Martin:

[51:15] Because of the library ecosystem. I think that the libraries are important because they sort of set the agenda, how you express your programs. And in particular the libraries that come from the Haskell side, they’re essentially monadic frameworks, and they require you to express your whole program as a monad, which is a concept that works well in functional programming. I have my reservations. I wouldn’t actually do that in my Scala programs.

[51:48] But by having prominent libraries out there, it’s quite normative that people feel like being a Scala programmer, they’re required to program this way. And then, of course, there are opinion leaders and conferences and all these things that tell you how you should be writing your programs. But I would say I think most of the Scala community is actually very, very level-headed, and I think most of the advice is great.

[52:18] But then, yeah, it’s still a challenge because it’s just too easy to. Mostly it’s not really the opinion leaders in the community, but let’s say it’s your boss. You have a small team in a company, your boss came from Haskell and says, “Hey, this is great. We do exactly like Haskell, the whole thing.” And then two years later the boss’s boss says, “No, nobody can understand this code. This code in the project is cancelled.”

[52:46] So these things happened in the industry. I’m not saying that all projects are like that, not at all. I mean, there are lots of really great success stories of Scala, but that’s essentially a challenge in terms of techniques. I think, in the end, I wish we had been a bit less dependent on the JVM in the sense that we took a lot from Java that intuitively makes sense but, in the end, and was very important for interop, but in the end could have been done better.

[53:25] So for instance, in Java, being an object-oriented language, you have universal methods like toString and equals and hashCode, and they’re defined for everything. And languages like Rust or Haskell, they’re no more discriminating. They have a thing called type classes where, essentially, at compile time, you tell exactly where you have equality and hashCode and these things, and it’s a bit more tedious to set these things up, but in the end it’s also safer.

[53:55] So I wish we had that, and we couldn’t because we sort of adapted Java‘s notion of what an object is, and it already came with all these things, which is sort of very convenient, but in the end caused friction.

Ryan:

[54:10] If I went back to you at that time, when you were starting it, and I said, what do you think is going to happen 20 years from now? What would you have said?

Martin:

[54:17] I would probably have said that while it was a footnote in memory, because, I mean, let’s face it, you do a thing and initially we had maybe five users or something like that outside our group, something like that. Right. And you don’t really expect that it would change a lot. And so no, I think it was quite by surprise that this actually happened. And I think the reason why it happened was that at the time Scala was a good bridge between dynamic languages that are slow and sometimes they crash.

[55:02] And solid languages, statically typed languages like Java, which were at the time quite cumbersome to write code in and there was a lot of ceremony and things like that. And Scala had inferred types, so you had types but you didn’t see them much. So it felt like a dynamic language, but it had also the solidity of essentially a good platform, and I think that’s what made it. And we’ve been copied a lot by a lot of other languages that put in these features then five or ten years later or things like that.

[55:33] But at the time, it was sort of Scala that was the first one that had it, and that’s sort of why it happened. But I wouldn’t have foreseen that by

55:42 — Advice for his younger self

Ryan:

[55:42] No means looking back on your career, when you just graduated college and kind of started your career, knowing what you know today, what advice would you give your younger self?

Martin:

[55:55] I think to take risks, be adventurous, pay it out. So essentially don’t follow the mainstream. If you take a fancy to do something wild and crazy technically, take the time to do it and do it. But I mean, yeah, so that’s what I would. Of course, you still need to sort of stay on track somewhat, but I don’t want to exaggerate that either. But yeah, so basically be a bit nonconformist.

Ryan:

[56:28] Awesome. Well, thank you so much for your time, Professor. I really appreciate it.

Martin:

[56:32] Thank you, Ryan.

Discussion about this episode

User's avatar

Ready for more?