# Did Modular just reinvent Julia?

**URL:** <https://discourse.julialang.org/t/did-modular-just-reinvent-julia/98214>\
**Category:** Offtopic\
**Tags:** mojo\
**Created:** [May 2, 2023, 5:22pm UTC](https://discourse.julialang.org/t/did-modular-just-reinvent-julia/98214 "2023-05-02T17:22:20Z")\
**Posts on this page:** 20\
**Page:** 13

<div class="post-metadata">

**Author:** ![pepa65](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pepa65/32/12168_2.png) [@pepa65](https://discourse.julialang.org/u/pepa65)\
**Post date:** [October 2, 2023, 12:49pm UTC](https://discourse.julialang.org/t/did-modular-just-reinvent-julia/98214/248 "2023-10-02T12:49:40Z")

</div>

And at the moment, Mojo doesn’t even support unicode strings (except for the filename extension…!).

---

<div class="post-metadata">

**Author:** ![ParadaCarleton](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paradacarleton/32/20005_2.png) [@ParadaCarleton](https://discourse.julialang.org/u/ParadaCarleton)\
**Post date:** [October 5, 2023, 5:07pm UTC](https://discourse.julialang.org/t/did-modular-just-reinvent-julia/98214/249 "2023-10-05T17:07:18Z")

</div>

> [@ParadaCarleton](#):
>
> 1. Replacing GC with a borrow checker, i.e. throwing errors at compile time if a possible memory leak is detected. It would definitely be great to have this as an _option_, as there are many (real-time) tasks that require memory management for high performance; this approach is great at preventing bugs, though. I have no idea how hard it’d be to implement this though. It would not be great to force users to use this for scripts; Mojo currently uses reference-counting in scripts, so I’m guessing the GC is going to be very slow if users try relying on it to save effort.

I’d like to add a note that as I’ve learned more about writing code with borrow checking and static typing, and tried out Mojo itself, I don’t think this makes the language harder; if anything, it makes programming much easier by eliminating a lot of bugs. Borrow-checking is also very easy to learn; it just says “You can’t have multiple variables pointing to the same mutable object.” The complexity of Rust really comes from features of the language other than the borrow-checker; setting aside a few pathological cases like linked lists where it’s easy to opt out of it. Reference counting being slow doesn’t really matter if you hardly ever have to opt into it in practice.

I’m starting to see the major advantage of Julia over Mojo as being metaprogramming that lets you use simpler syntax. Mojo’s metaprogramming system is extremely simplistic and almost a one-for-one copy of Zig’s; it accomplishes roughly the equivalent of using constants like `Val`, Static.jl, or StaticArrays.jl (along with tools like LoopVec.jl). And also, of course, Mojo doesn’t exist yet and doesn’t have any kind of ecosystem, so I’m forced to evaluate Mojo more as a proposed language than an actual one. There’s also somewhat more boilerplate code than in Julia, and substantially more than in Python.

The main advantage of Mojo is it encourages static programming by making it “opt-out.” The equivalent to a Julia “type instability” in Mojo is declaring a dynamic Python `class` or `def`–you need to explicitly request dynamism to get it, instead of having it handed to you without a peep. The Mojo devs seem to think Julia is too dynamic to be a good language for writing libraries, pretty much the same way Python is. Besides that, they seem to be under the impression that contributing features to Julia would have been a major slog and would have taken forever (slow reviews, bikeshedding, etc.).

---

<div class="post-metadata">

**Author:** ![ParadaCarleton](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paradacarleton/32/20005_2.png) [@ParadaCarleton](https://discourse.julialang.org/u/ParadaCarleton)\
**Post date:** [November 11, 2023, 3:28am UTC](https://discourse.julialang.org/t/did-modular-just-reinvent-julia/98214/250 "2023-11-11T03:28:06Z")

</div>

Further updates–I think I understand what Modular is doing now, and why they think they can make Python fast.

To oversimplify, there are 4 big things that make Python slow, and made people think it was impossible to fix Python performance:

1. Reference counting–Python uses reference counting (RC) for its garbage collection, which is extremely slow. This can’t be replaced, because Python’s C interface requires objects to be destroyed as soon as they’re no longer needed.  
Solution: use a borrow checker for functions marked `fn`, destroying Python objects at no runtime cost. Surprisingly, this isn’t a major barrier to beginners. Borrow checking just says you can’t have multiple names for the same piece of mutable data. Most scientific Python code satisfies this already, because it’s simple array or dataframe manipulation; borrow checking is only really a pain if you’re creating complex data structures like trees, linked lists, or graphs.
2. Dynamic typing–Python functions are always dynamically typed.  
Solution: Use Python’s built-in type declarations and type inference to identify types for most functions (already adopted in many projects). let people opt-out of static typing by using `def` instead of `fn` to define a function.
3. Runtime class modifications–Python classes let you add or delete methods or fields for Python classes at runtime. In practice, about 0% of Python classes use this “feature” (honestly, it’s a pure footgun), so you can just slap a label like `struct` on your class promising not to do that.
4. GIL–Python somehow thought it was a good idea to make it impossible to run Python on multiple threads. [Luckily, they’re in the process of removing that.](https://peps.python.org/pep-0703/)

It’s a pretty damn clever design. I like it, but the devil’s in the details.

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [November 11, 2023, 3:07pm UTC](https://discourse.julialang.org/t/did-modular-just-reinvent-julia/98214/252 "2023-11-11T15:07:41Z")

</div>

> [@ParadaCarleton](#):
>
> Python classes let you add or delete methods or fields for Python classes at runtime. In practice, about 0% of Python classes use this “feature” (honestly, it’s a pure footgun)

This is literally the only way that you can add a field to a Python object. Some fields are added in ` __init__ ` (which happens at runtime), but many fields are added in other methods.

---

<div class="post-metadata">

**Author:** ![ParadaCarleton](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paradacarleton/32/20005_2.png) [@ParadaCarleton](https://discourse.julialang.org/u/ParadaCarleton)\
**Post date:** [November 11, 2023, 5:56pm UTC](https://discourse.julialang.org/t/did-modular-just-reinvent-julia/98214/253 "2023-11-11T17:56:30Z")

</div>

> [@CameronBieganek](#):
>
> This is literally the only way that you can add a field to a Python object. Some fields are added in ` __init__ ` (which happens at runtime), but many fields are added in other methods.

Right. What I mean is that almost all fields are added in ` __init__ ` or some other constructor function, and then no new fields are added after initialization. There are very few situations where the fields of a Python class actually need to be modified at runtime (i.e. couldn’t be declared statically instead).

---

<div class="post-metadata">

**Author:** ![adienes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/adienes/32/37459_2.png) [@adienes](https://discourse.julialang.org/u/adienes)\
**Post date:** [November 11, 2023, 6:00pm UTC](https://discourse.julialang.org/t/did-modular-just-reinvent-julia/98214/254 "2023-11-11T18:00:44Z")

</div>

> [@ParadaCarleton](#):
>
> almost all fields are added in ` __init__ ` or some other constructor function, and then no new fields are added after initialization.

While I agree that dynamically adding fields or methods is certainly _less_ common than being present in the constructor

> [@ParadaCarleton](#):
>
> In practice, about 0% of Python classes use this “feature”

this is completely wrong and I don’t understand why you are claiming it as fact

even in my own code base I use this “feature” handily once, and in (IMO) a controlled and clear way, so I do not consider it a hack or a footgun. and my code is not that large, so if I have found a use I am sure many others (aka \>0%) have as well

---

<div class="post-metadata">

**Author:** ![ParadaCarleton](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paradacarleton/32/20005_2.png) [@ParadaCarleton](https://discourse.julialang.org/u/ParadaCarleton)\
**Post date:** [November 11, 2023, 6:07pm UTC](https://discourse.julialang.org/t/did-modular-just-reinvent-julia/98214/255 "2023-11-11T18:07:00Z")

</div>

> [@adienes](#):
>
> even in my own code base I use this “feature” handily once,

Using it exactly once in your codebase sounds like “about 0%” to me 😄 Are you defining “about” as `isapprox` here? 😉

If you want, that one class can be declared with `class` instead of `struct`, which will treat it like a dictionary (the way base Python handles classes). That has a performance cost but gives you that flexibility.

---

<div class="post-metadata">

**Author:** ![adienes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/adienes/32/37459_2.png) [@adienes](https://discourse.julialang.org/u/adienes)\
**Post date:** [November 11, 2023, 6:08pm UTC](https://discourse.julialang.org/t/did-modular-just-reinvent-julia/98214/256 "2023-11-11T18:08:01Z")

</div>

> [@ParadaCarleton](#):
>
> Using it exactly once in your codebase sounds like “about 0%” to me 😄

…  
but it’s not

this package has only 5 types total, and one of them adds methods dynamically

feels a little bit more like 20% to me

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [November 11, 2023, 6:08pm UTC](https://discourse.julialang.org/t/did-modular-just-reinvent-julia/98214/257 "2023-11-11T18:08:09Z")

</div>

It is pretty common to define fields in other methods. For example, a lot of fields in scikit-learn models get set in the `fit` method.

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [November 11, 2023, 6:11pm UTC](https://discourse.julialang.org/t/did-modular-just-reinvent-julia/98214/258 "2023-11-11T18:11:24Z")

</div>

I’ve always thought the mutating `fit` was a terrible design. Just return a different type!

---

<div class="post-metadata">

**Author:** ![ParadaCarleton](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paradacarleton/32/20005_2.png) [@ParadaCarleton](https://discourse.julialang.org/u/ParadaCarleton)\
**Post date:** [November 11, 2023, 6:15pm UTC](https://discourse.julialang.org/t/did-modular-just-reinvent-julia/98214/259 "2023-11-11T18:15:37Z")

</div>

> [@CameronBieganek](#):
>
> It is pretty common to define fields in other methods. For example, a lot of fields in scikit-learn models get set in the `fit` method.

Yes, but those fields could very easily be defined upfront. To convert from Python, you just need a tool that looks at all the methods, checks which fields get used, and then use the class to move `self.field` out of `fit`.

This is basically the Modular team’s plan–they think the vast majority of classes can be rewritten automatically (basically transpiling to Mojo) using very simple static analysis tools, and then the handful left behind can just stick to CPython.

---

<div class="post-metadata">

**Author:** ![adienes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/adienes/32/37459_2.png) [@adienes](https://discourse.julialang.org/u/adienes)\
**Post date:** [November 11, 2023, 6:40pm UTC](https://discourse.julialang.org/t/did-modular-just-reinvent-julia/98214/260 "2023-11-11T18:40:59Z")

</div>

> [@ParadaCarleton](#):
>
> Yes, but those fields could very easily be defined upfront

in my situation they cannot

I am using a subclass to implement a method for the base class

yes, I am sure there is some HN-style blog post out there moaning about how this is Terrible and Ugly and I must refactor it at once, but tbh I suspect any other approach in this situation would be more verbose and harder to follow, so I’m going to carry on

---

<div class="post-metadata">

**Author:** ![ParadaCarleton](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paradacarleton/32/20005_2.png) [@ParadaCarleton](https://discourse.julialang.org/u/ParadaCarleton)\
**Post date:** [November 11, 2023, 7:33pm UTC](https://discourse.julialang.org/t/did-modular-just-reinvent-julia/98214/261 "2023-11-11T19:33:51Z")

</div>

> [@adienes](#):
>
> yes, I am sure there is some HN-style blog post out there moaning about how this is Terrible and Ugly and I must refactor it at once,

It’s not a HN blog post so much as textbook programming principles that say parents shouldn’t depend on the behavior of their subtypes. If `f(::AbstractArray)` had code calling `@invoke f(::Vector)`, that would indicate a problem with your design. (Part of why multidispatch is so great is because it makes it difficult to violate this rule without weird constructs like `@invoke`, so it automatically enforces dependency inversion.)

If your package has 5 classes and is just for personal use (not meant to be extensible), then sure, that’s fine. That being said, this would probably get a PR rejected in Python (probably caught and blocked by a linter).

I wouldn’t be surprised if hacked-together scripts use dynamic classes closer to 10-20% of the time, but those can just keep using `class` since they don’t really need performance.

---

<div class="post-metadata">

**Author:** ![adienes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/adienes/32/37459_2.png) [@adienes](https://discourse.julialang.org/u/adienes)\
**Post date:** [November 11, 2023, 7:37pm UTC](https://discourse.julialang.org/t/did-modular-just-reinvent-julia/98214/262 "2023-11-11T19:37:33Z")

</div>

> textbook programming principles

the thing about textbooks is they don’t anticipate every real-world situation

> I wouldn’t be surprised if hacked-together scripts

🤷‍♂️ to be honest, I find this somewhat insulting. I don’t consider my code hacked-together, it was just the most straightforward and least verbose (and imo most understandble to a reader) approach even though it violates “basic principles.” when a hammer does the job, why use another tool?

please stop projecting your own style preferences onto “all code”

---

<div class="post-metadata">

**Author:** ![ParadaCarleton](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paradacarleton/32/20005_2.png) [@ParadaCarleton](https://discourse.julialang.org/u/ParadaCarleton)\
**Post date:** [November 12, 2023, 6:10pm UTC](https://discourse.julialang.org/t/did-modular-just-reinvent-julia/98214/263 "2023-11-12T18:10:43Z")

</div>

> [@adienes](#):
>
> to be honest, I find this somewhat insulting. I don’t consider my code hacked-together, it was just the most straightforward and least verbose (and imo most understandble to a reader) approach even though it violates “basic principles.

I’m sorry if calling it “hacked-together” came across as derogatory, which wasn’t my intent. When I said “Hacked together,” I meant it in the sense of e.g. Lisp hackers; a hacked-together project is just one that favors straightforward and less verbose code (for quick prototyping) over future extensibility (being able to subclass without breaking anything).

> [@adienes](#):
>
> please stop projecting your own style preferences onto “all code”

I think it’s a tradeoff rather than a style preference, and my point is that even if most code starts out like this, most high-performance code doesn’t end up looking like this after optimization. (That’s why Julia works!)

I don’t really care about the aesthetics; my point is that even if some Python code out there relies on this ability, you’re not going to find many uses of it in big Python libraries, which are the main draw for Python.

---

<div class="post-metadata">

**Author:** ![bertschi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bertschi/32/33462_2.png) [@bertschi](https://discourse.julialang.org/u/bertschi)\
**Post date:** [November 12, 2023, 10:05pm UTC](https://discourse.julialang.org/t/did-modular-just-reinvent-julia/98214/264 "2023-11-12T22:05:53Z")

</div>

Also decorators often depend on the ability to introspect and sometimes change the internals of a passed in function or class. The have also become quite widespread in modern Python.

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [November 12, 2023, 10:23pm UTC](https://discourse.julialang.org/t/did-modular-just-reinvent-julia/98214/265 "2023-11-12T22:23:15Z")

</div>

> [@bertschi](#):
>
> change the internals of a passed in function

Which decorators do that?

---

<div class="post-metadata">

**Author:** ![bertschi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bertschi/32/33462_2.png) [@bertschi](https://discourse.julialang.org/u/bertschi)\
**Post date:** [November 12, 2023, 11:16pm UTC](https://discourse.julialang.org/t/did-modular-just-reinvent-julia/98214/266 "2023-11-12T23:16:54Z")

</div>

[@latexify](https://pypi.org/project/latexify-py/) extracts information from the AST and [numba.@jit](https://numba.readthedocs.io/en/stable/developer/architecture.html) seems to work at the byte-code level. I’m sure there are more examples (had seen something recently, but cannot recall what it was at the moment) …

---

<div class="post-metadata">

**Author:** ![Barget](https://avatars.discourse-cdn.com/v4/letter/b/94ad74/32.png) [@Barget](https://discourse.julialang.org/u/Barget)\
**Post date:** [November 13, 2023, 8:05pm UTC](https://discourse.julialang.org/t/did-modular-just-reinvent-julia/98214/267 "2023-11-13T20:05:19Z")

</div>

Assuming one out of four of all class or function ever coded in Python falls into the “special case” category (which I think is a veeery generous assumption), the point that @ParadaCarleton is trying to make still stands. Namely, that (I quote) “they think the vast majority of classes can be rewritten automatically”.  
With this pessimistic assumption from above, you still optimize 75% of all classes & functions. Not bad!

As for numba.@jit, I then understand that things could go either faster by removing this decorator, or not slower by keeping it. That’s still a win (in the sense that the work done to accelerate Python code is not lost, and it’s easy to go further).

_Side note: ParadaCarleton was making a general point (never intended to cover all special cases). In that frame, I don’t see the added value in bringing a special case if it doesn’t invalidate the logic.  
(conversely, if the very purpose of the thread were to get a precise, thorough, and comprehensive understanding of the situation, then I understand)_

Anyway, @ParadaCarleton, thanks for bringing that up. This suggests that Mojo may challenge Julia more directly than expected (at least to me), if they manage to keep the simplicity of Python syntax (compared to the extension they’ve defined).

---

<div class="post-metadata">

**Author:** ![ParadaCarleton](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paradacarleton/32/20005_2.png) [@ParadaCarleton](https://discourse.julialang.org/u/ParadaCarleton)\
**Post date:** [November 14, 2023, 4:58am UTC](https://discourse.julialang.org/t/did-modular-just-reinvent-julia/98214/268 "2023-11-14T04:58:18Z")

</div>

I think that’s right, but these feel very tame compared with what people do in Julia. Python’s metaprogramming is clunky and pretty far behind Julia’s (thus [PEP 638](https://peps.python.org/pep-0638/)’s proposal for true syntactic macros, but it seems dead for now).

[Previous page](https://discourse.julialang.org/t/did-modular-just-reinvent-julia/98214.md?page=12)

[Next page](https://discourse.julialang.org/t/did-modular-just-reinvent-julia/98214.md?page=14)
