I remember than when they announced Mojo this sentence was precisely what made me very skeptical, because they vastly underestimated how complex is Python and how hard it is to be even close to be 100% compatible, let alone being a superset (I know it firsthand, having worked many years on PyPy)
The fact that they changed the narrative is actually a good thing for the Python community IMHO.
E.g., in parallel with Mojo and way before it was announced I started working on SPy, which turned out to share many goals, ideas and features with Mojo, but from a "Pythonic first" point of view. I never claimed that SPy would be a "compiler for Python" and/or a "Python superset", but when Mojo was announced I started to hear comments like "now that we have Mojo, why continuing working on SPy?".
To be clear I'm not trying to shame them for changing their minds or for not going at some pace or whatever. It was just that given a lot of public stuff, including on their homepage and wikipedia, it seemed to be something other than what it currently is. It's still a cool project and I hope to see it do well.
That's okay, I'll do it for you. I don't think they 'changed their minds' at all. Modular achieved their $1.6bn valuation partly on the back of the promise of creating "Python++". That promise has now served its purpose and is about to become a liability (because it was never going to work out), so they're ditching it. And no, when there are hundreds of millions of dollars of VC on the line, Hanlon's Razor just does not cut it.
How does this make any sense? No company raises 100s of millions of dollars and reaches $1B in valuation on the promise of creating a programming language.
Modular has commercial products; Mojo is just one layer of the stack and is not what they sell.
I understand the author's confusion, because Mojo actually advertised itself much closer to "PyPy with high-performance language extras" early on. I was got distracted for a couple of years and was also surprised to find that it's now its own language, just with a good Python interop story (at least as part of the vision).
I think the move makes sense, for what they set out to be, full compat with python was going to be a burden.
I write a lot of Mojo, and like the language a lot. This article was very painful to read (they missed t-strings! among many other things). From the inside the pivot away from "superset of python" seemed pretty well managed and reasonable. A lot of it was motivated by not wanting to repeat a lot of the warts of python, and the fact that performance is always the number one driver for Mojo.
Mojo is a really cool language with some awesome ideas. I'd highly recommend a read through the docs and trying it out on your own a bit. It really is incredibly fast, and the compiler stack is the most unique out there now and not just "yet another LLVM" situation.
The language still seems to be on track for 1.0 sometime this Summer, and the stated goal from Chris is to open source the compiler shortly after that, which I think will help adoption a lot.
Yeah this post felt weird, the thrust seemed to be that the author had some understandable misconceptions about Mojo and then proceeded to stumble through their misconceptions and assumptions about how Mojo works instead of .. reading the docs?
I also felt unsure if this made the article pointless. I decided it wasn't pointless because of other people in general misunderstanding, including Mojo's wikipedia page, as the post mentions, about the state of Python compatibility. And that the homepage included quotes that seemed to suggest Python compatibility, as the post mentions.
I agree it's a long shot from being "a python superset", but it does still look pretty similar. If someone wrote a port of the python stdlib I'm sure it would look one step closer).
For your timings, I'd suggest compiling with mojo build instead of running mojo run.
Thanks! Please note, the article wasn't about Mojo being a bad language or anything. It was just to show that it really isn't compatible with Python right now, despite public statements that seem to hint otherwise. Altering the script to the point that it doesn't run in Python, as you've done, doesn't mean very much in this regard.
I'd be interested to look at Mojo in another article to focus on what it does well, but the talks of Python compatibility is what I focused on here.
When Mojo launched three years ago the rationale for being compatible with Python, if I remember correctly, was that it would allow them to bootstrap the new ecosystem from Python's standard library and enormous array of existing packages.
This works around the fact that new languages are inevitably held back by the need to build their own standard library that covers the many things developers expect to be able to do.
In 2026 porting code from one language to another has become disturbingly cheap thanks to LLMs and coding agents. I wonder if the "compatible with Python" bet isn't actually as valuable as it was before, because there's no a way for them to accelerate the creation of their own Mojo-native standard library?
In 2026 porting code from one language to another has become disturbingly cheap thanks to LLMs and coding agents.
I respect your optimism abstractly, but don't you feel like this is quite exaggerated? Releasing of a PoC port of a library to another language is step like 2 of 200 for multi-lang libraries right? Because that's what people are talking about, they're not talking about the one-off demo but "oh I have maintained packages in Mojo".
Even a one-off port of something like Pandas to Mojo... the instant Pandas does, what are you doing?
Though to your point, Python compatibility also goes fairly beyond syntax stuff. If it was "just" syntax (modulo the lack of u prefix) Python 2 and 3 would have been an easy port!
EDIT: to even further highlight my point on difficulty... PyPy, a project whose almost entire existence is "we have another Python", has trouble keeping up with CPython. I don't want to dismiss how LLMs make a lot of steps easier but "disturbingly cheap"... the code is the easy part?
When it comes to building out the standard library I'm not talking about libraries with the complexity of Pandas or PyPy. I'm talking about the non-glamorous pieces of a standard library, like itertools or JSON parsing or text wrapping or pretty printing.
The kind of things that a new programming language needs to have and that might represent tens or hundreds of thousands of lines of code but that are well understood problems which don't require human creativity, they need someone or something to bang out thousands of lines of boring, predictable, tested and documented code.
But, that said: you can get a LONG way in March 2026 porting something of the complexity of Pandas to another language with the assistance of coding agents. Max Woolf, a self-described coding agent skeptic, wrote a bunch about that recently.
Max Woolf, a self-described coding agent skeptic, wrote a bunch about that recently.
That "self-described" is doing some very hard lifting, given that his home page appears to be very proud of his day job of.. spamming slop. But sure, he's happy to call himself a "skeptic" for a post or two if it helps him look better.
Look I do believe you can use these tools to get a bunch of porting work done for the initial thing, and to kinda explore the feasibility. At the risk of talking past one another I'm more concerned about the running costs of lib maintenance post initial release. Remember when the Py2 -> Py3 "official" porting strategy was "run 2to3"? I mean this a bit glibly but there's stuff involved
itertools is a good example of near-best-case scenarios on LLM porting, because there are pure python specs, there's not a lot of movement, and at some level the results are very straightforward for most all of the public API. And it's not that big of a library
JSON parsing is a bit of an interesting example though. If you can rely on the test suite (that itself has to be ported in the current version of Mojo, introducing another chance for drift) then you're golden. But otherwise you have two choices:
just port over the spirit of the library. In that case Mojo can just rely on its host language capabilities and be done with it.
try to be 100% compatible. There any drift in the semantics of the language can intro bugs. Any underspecified part of the Python language implementation is at risk of intro'ing drift.
Anyways tbh if I were Modular I would hire someone who's good at writing type inference to try real hard to get source capabilities rather than maintaining ports. Not that hard with certain kinds of code (famous last words).
Aside: in the article you linked, the image is a case of Opus doing a fancy optimization to divide by 255. Except at least according to my read of the compilation output if you actually look at the compilation output a better implementation of that function would have been x / 255. I could be very wrong on this but that's my read!
I'm not a super skeptic on this stuff, it's more that often these porting articles seems to highlight at least one incorrect thing. It's one thing for the tool to make mistakes, it's another for an article to highlight a mistake as a success.
The glib thing to say is that people interacting with these are not domain experts and therefore don't have the right place to judge the quality of the result. Buuuuuut when you show up with benchmarks and fairly close results it's hard to argue the results are wrong. Just always a bit unsatisfying to open the black box and find a bunch of "silly" things inside.
The classic technique here (Granlund + Montgomery, 1994), is 2x higher throughput on sapphirerapids by static analysis:
let zero_extend = val as u64;
let reciprocal_mul = 0x80808081u64;
let shifted_result = reciprocal_mul.wrapping_mul(zero_extend);
(shifted_result >> 39) as u32
I'm not familiar with uarch before Nehalem or ARM, so maybe there's an arch which prefers to avoid the imul.
Neat! I like the put_output trick to avoid noise and blackbox on the compiler explorer
Thanks for the deep dive though. I was prepared to be proven wrong but still feel a bit vindicated that "just type in the constant division dummy" seems to have been the right strat
I wonder how well LLMs can translate into new languages. Has anyone tried? I know there are people here writing a new language a month so maybe some can share some insights
Judging from being able to create new lisp frameworks and then use them, (I'm replacing straight bash use for agents) I think the answer is close to "it will work quite well with enough context".
To add to what others have said, there is a roadmap; At the moment Modular is building towards phase 1... which is a language for writing high-performance GPU kernels. A lot of the initial Python compatibility features (typeless functions) were removed because they had a lot of problems and were outside the scope of the roadmap for this phase. I imagine Mojo will be a lot closer to Python towards phase 3 of the project.
I read through most of this thinking "okay sure that's reasonable for an early stage project... also unfortunate but reasonable for an early stage project..." until I got to the bit about the $380M. Dang that is a lot of money.
I've recently listened to a bunch of interviews with Chris Lattner from some years ago and as recently as 2025.
I wanted to learn more about the Swift design as I was thinking about switching my main language to that after hearing that Lattner wanted Swift to be take over the world.
Over the course of many interviews I learned that he had completely abandoned Swift due to understandable circumstances, but then I also heard him talk over and over, many many times, to the point of boredom, that Python was amazing and that Mojo would be a superset of Python. That was basically the only selling point of Mojo over other low-level languages.
I couldn't care less about Python and its confusing ecosystem, syntax, and type system, so that didn't work on me, but I kept listening anyway.
How ironic is it to discover now that after many years they didn't make any progress in the Python compatibility.
I was going to say they should have just gone with some new syntax, as most languages do.
On the other hand that is kinda weird too: why does every new language have to invent new syntax for doing (conceptually) exactly the same things all other languages do?
So I guess Mojo is ok, they should just have never said they were a superset of Python.
Agreed that the superset situation dug them a bit of a hole from the start.
I do think that having a default stance for Mojo of "when in doubt we just do it like Python" has really helped it move quickly from a development standpoint. It reduces the amount bikeshedding for sure.
It's a bit unfortunate that as an industry we're leaning heavily into "annotate function parameters and return types". Not because I dislike static typing (far from it!) but it does make it harder to write APIs with complex types, since those complex types end up needing to be duplicated and repeated.
I like how in Typescript at least you can extract arg types decently easily. Really want more of that tooling in other gradual type systems
There's a hilarious docs commit in which they "clarify" what they meant by "superset of Python" (by removing that phrase entirely).
They're not walking it back though! Just providing more context.
I remember than when they announced Mojo this sentence was precisely what made me very skeptical, because they vastly underestimated how complex is Python and how hard it is to be even close to be 100% compatible, let alone being a superset (I know it firsthand, having worked many years on PyPy) The fact that they changed the narrative is actually a good thing for the Python community IMHO.
E.g., in parallel with Mojo and way before it was announced I started working on SPy, which turned out to share many goals, ideas and features with Mojo, but from a "Pythonic first" point of view. I never claimed that SPy would be a "compiler for Python" and/or a "Python superset", but when Mojo was announced I started to hear comments like "now that we have Mojo, why continuing working on SPy?".
Glad that this is over :)
That is fun, thanks for sharing!
To be clear I'm not trying to shame them for changing their minds or for not going at some pace or whatever. It was just that given a lot of public stuff, including on their homepage and wikipedia, it seemed to be something other than what it currently is. It's still a cool project and I hope to see it do well.
That's okay, I'll do it for you. I don't think they 'changed their minds' at all. Modular achieved their $1.6bn valuation partly on the back of the promise of creating "Python++". That promise has now served its purpose and is about to become a liability (because it was never going to work out), so they're ditching it. And no, when there are hundreds of millions of dollars of VC on the line, Hanlon's Razor just does not cut it.
How does this make any sense? No company raises 100s of millions of dollars and reaches $1B in valuation on the promise of creating a programming language. Modular has commercial products; Mojo is just one layer of the stack and is not what they sell.
I understand the author's confusion, because Mojo actually advertised itself much closer to "PyPy with high-performance language extras" early on. I was got distracted for a couple of years and was also surprised to find that it's now its own language, just with a good Python interop story (at least as part of the vision).
I think the move makes sense, for what they set out to be, full compat with python was going to be a burden.
I write a lot of Mojo, and like the language a lot. This article was very painful to read (they missed t-strings! among many other things). From the inside the pivot away from "superset of python" seemed pretty well managed and reasonable. A lot of it was motivated by not wanting to repeat a lot of the warts of python, and the fact that performance is always the number one driver for Mojo.
Mojo is a really cool language with some awesome ideas. I'd highly recommend a read through the docs and trying it out on your own a bit. It really is incredibly fast, and the compiler stack is the most unique out there now and not just "yet another LLVM" situation.
The language still seems to be on track for 1.0 sometime this Summer, and the stated goal from Chris is to open source the compiler shortly after that, which I think will help adoption a lot.
Yeah this post felt weird, the thrust seemed to be that the author had some understandable misconceptions about Mojo and then proceeded to stumble through their misconceptions and assumptions about how Mojo works instead of .. reading the docs?
I also felt unsure if this made the article pointless. I decided it wasn't pointless because of other people in general misunderstanding, including Mojo's wikipedia page, as the post mentions, about the state of Python compatibility. And that the homepage included quotes that seemed to suggest Python compatibility, as the post mentions.
@eatonphil! I took a stab at converting your Python script to Mojo: https://gist.github.com/sstadick/688ba3510d59367b2c40f17d9c1ca5ad
I agree it's a long shot from being "a python superset", but it does still look pretty similar. If someone wrote a port of the python stdlib I'm sure it would look one step closer).
For your timings, I'd suggest compiling with
mojo buildinstead of runningmojo run.Thanks! Please note, the article wasn't about Mojo being a bad language or anything. It was just to show that it really isn't compatible with Python right now, despite public statements that seem to hint otherwise. Altering the script to the point that it doesn't run in Python, as you've done, doesn't mean very much in this regard.
I'd be interested to look at Mojo in another article to focus on what it does well, but the talks of Python compatibility is what I focused on here.
It indeed still feels very Python-like.
When Mojo launched three years ago the rationale for being compatible with Python, if I remember correctly, was that it would allow them to bootstrap the new ecosystem from Python's standard library and enormous array of existing packages.
This works around the fact that new languages are inevitably held back by the need to build their own standard library that covers the many things developers expect to be able to do.
In 2026 porting code from one language to another has become disturbingly cheap thanks to LLMs and coding agents. I wonder if the "compatible with Python" bet isn't actually as valuable as it was before, because there's no a way for them to accelerate the creation of their own Mojo-native standard library?
I respect your optimism abstractly, but don't you feel like this is quite exaggerated? Releasing of a PoC port of a library to another language is step like 2 of 200 for multi-lang libraries right? Because that's what people are talking about, they're not talking about the one-off demo but "oh I have maintained packages in Mojo".
Even a one-off port of something like Pandas to Mojo... the instant Pandas does, what are you doing?
Though to your point, Python compatibility also goes fairly beyond syntax stuff. If it was "just" syntax (modulo the lack of
uprefix) Python 2 and 3 would have been an easy port!EDIT: to even further highlight my point on difficulty... PyPy, a project whose almost entire existence is "we have another Python", has trouble keeping up with CPython. I don't want to dismiss how LLMs make a lot of steps easier but "disturbingly cheap"... the code is the easy part?
When it comes to building out the standard library I'm not talking about libraries with the complexity of Pandas or PyPy. I'm talking about the non-glamorous pieces of a standard library, like itertools or JSON parsing or text wrapping or pretty printing.
The kind of things that a new programming language needs to have and that might represent tens or hundreds of thousands of lines of code but that are well understood problems which don't require human creativity, they need someone or something to bang out thousands of lines of boring, predictable, tested and documented code.
But, that said: you can get a LONG way in March 2026 porting something of the complexity of Pandas to another language with the assistance of coding agents. Max Woolf, a self-described coding agent skeptic, wrote a bunch about that recently.
That "self-described" is doing some very hard lifting, given that his home page appears to be very proud of his day job of.. spamming slop. But sure, he's happy to call himself a "skeptic" for a post or two if it helps him look better.
Look I do believe you can use these tools to get a bunch of porting work done for the initial thing, and to kinda explore the feasibility. At the risk of talking past one another I'm more concerned about the running costs of lib maintenance post initial release. Remember when the Py2 -> Py3 "official" porting strategy was "run
2to3"? I mean this a bit glibly but there's stuff involveditertoolsis a good example of near-best-case scenarios on LLM porting, because there are pure python specs, there's not a lot of movement, and at some level the results are very straightforward for most all of the public API. And it's not that big of a libraryJSON parsing is a bit of an interesting example though. If you can rely on the test suite (that itself has to be ported in the current version of Mojo, introducing another chance for drift) then you're golden. But otherwise you have two choices:
just port over the spirit of the library. In that case Mojo can just rely on its host language capabilities and be done with it.
try to be 100% compatible. There any drift in the semantics of the language can intro bugs. Any underspecified part of the Python language implementation is at risk of intro'ing drift.
Anyways tbh if I were Modular I would hire someone who's good at writing type inference to try real hard to get source capabilities rather than maintaining ports. Not that hard with certain kinds of code (famous last words).
Aside: in the article you linked, the image is a case of Opus doing a fancy optimization to divide by 255. Except at least according to my read of the compilation output if you actually look at the compilation output a better implementation of that function would have been
x / 255. I could be very wrong on this but that's my read!I'm not a super skeptic on this stuff, it's more that often these porting articles seems to highlight at least one incorrect thing. It's one thing for the tool to make mistakes, it's another for an article to highlight a mistake as a success.
The glib thing to say is that people interacting with these are not domain experts and therefore don't have the right place to judge the quality of the result. Buuuuuut when you show up with benchmarks and fairly close results it's hard to argue the results are wrong. Just always a bit unsatisfying to open the black box and find a bunch of "silly" things inside.
You dropped a -O. https://godbolt.org/z/qbh3hG74G Opus is still worse, but I'd rather steelman both. :)
The classic technique here (Granlund + Montgomery, 1994), is 2x higher throughput on sapphirerapids by static analysis:
I'm not familiar with uarch before Nehalem or ARM, so maybe there's an arch which prefers to avoid the imul.
Neat! I like the
put_outputtrick to avoid noise and blackbox on the compiler explorerThanks for the deep dive though. I was prepared to be proven wrong but still feel a bit vindicated that "just type in the constant division dummy" seems to have been the right strat
I wonder how well LLMs can translate into new languages. Has anyone tried? I know there are people here writing a new language a month so maybe some can share some insights
Judging from being able to create new lisp frameworks and then use them, (I'm replacing straight bash use for agents) I think the answer is close to "it will work quite well with enough context".
LLMs model languages with fidelity proportional to occurrence in the training corpus.
Not quite, under/over representation is what allows poisoning
Is that actually true? I would you’d see diminishing returns above a certain point.
To add to what others have said, there is a roadmap; At the moment Modular is building towards phase 1... which is a language for writing high-performance GPU kernels. A lot of the initial Python compatibility features (typeless functions) were removed because they had a lot of problems and were outside the scope of the roadmap for this phase. I imagine Mojo will be a lot closer to Python towards phase 3 of the project.
I read through most of this thinking "okay sure that's reasonable for an early stage project... also unfortunate but reasonable for an early stage project..." until I got to the bit about the $380M. Dang that is a lot of money.
I've recently listened to a bunch of interviews with Chris Lattner from some years ago and as recently as 2025.
I wanted to learn more about the Swift design as I was thinking about switching my main language to that after hearing that Lattner wanted Swift to be take over the world.
Over the course of many interviews I learned that he had completely abandoned Swift due to understandable circumstances, but then I also heard him talk over and over, many many times, to the point of boredom, that Python was amazing and that Mojo would be a superset of Python. That was basically the only selling point of Mojo over other low-level languages.
I couldn't care less about Python and its confusing ecosystem, syntax, and type system, so that didn't work on me, but I kept listening anyway.
How ironic is it to discover now that after many years they didn't make any progress in the Python compatibility.
What is the killer feature of Mojo now?
Its killer feature is writing GPU kernels.
Outside that, it's got a lot of cool stuff: comptime, dependent type system, origin system, builtin SIMD support at all levels of language.
I was going to say they should have just gone with some new syntax, as most languages do.
On the other hand that is kinda weird too: why does every new language have to invent new syntax for doing (conceptually) exactly the same things all other languages do?
So I guess Mojo is ok, they should just have never said they were a superset of Python.
Agreed that the superset situation dug them a bit of a hole from the start.
I do think that having a default stance for Mojo of "when in doubt we just do it like Python" has really helped it move quickly from a development standpoint. It reduces the amount bikeshedding for sure.
It's a bit unfortunate that as an industry we're leaning heavily into "annotate function parameters and return types". Not because I dislike static typing (far from it!) but it does make it harder to write APIs with complex types, since those complex types end up needing to be duplicated and repeated.
I like how in Typescript at least you can extract arg types decently easily. Really want more of that tooling in other gradual type systems