How does it handle garbage collection? AFAIK GC is the main reason behind Lua's stack-based API: it's designed so that C code never needs to hold a pointer to a Lua object, which means an object will never be garbage-collected while C code is still trying to use it.
OTOH Python does allow C code to hold such pointers - so it requires that code to perform error-prone manual reference-counting.
The interpreter keeps track of globals and all stack frames. So it knows what objects are in scope.
If you're creating an object that can contain native ruby values inside it's own opaque structure, then when you define the class that wraps this structure you reference the callback functions you want to be called during GC mark and when the GC frees your object. During the mark callback you simply call rb_gc_mark on any of those internal values so the GC knows they are in scope.
In practice it's quite easy to use and you can find many examples of this. There is no equivalent I'm aware of to mark in lua, but the free callback is effectively equivalent to the __gc metamethod.
> they intended to make it compatible with existing Python code
That was the original claim, but it was quietly removed from the website. (Did they fall for the common “Python is a simple language” misconception?).
Now they promise I can “write like Python”, but don’t even support fundamentals like classes (which are part of stage 3 of the roadmap, but they’re still working on stage 1).
Maybe Mojo will achieve all its goals, but so far has been over-promising and under-delivering - it’s starting to remind me of the V language.
My bad. But my point sticks, because NZ TV licenCe did exist for most of the time TV has been in New Zealand, i.e. for well over forty years. These days, the state, aka "the Crown", controls major outlets, and still pays for some programming from public taxes as well as taking advertising revenue. So the public pays for it whether they want to or not. (Much like Australia which abolished its licence a while ago, and the Republic of Ireland which retains a TV licence but also carries advertising on RTÉ.)
The PEP for this change is here [0] and discussion of it is here [1]. Both are very long and seem to represent a huge amount of complexity, apparently to make installing Python easier for novices?
But what about those of us who listened to Rich Hickey and prefer "simple" over "easy"? With the executable installer no longer available, how do I get a copy of python.exe, python316.dll etc onto my machine so that `C:\Python316\python.exe <script>` works, without having to think about `py`, `pymanager`, Windows Store etc?
> apparently to make installing Python easier for novices?
That seems to be the goal. But from what I've seen on forums and Discord, nothing really works for that. People are becoming less and less computer literate, including people who want to try programming. I've seen multiple instances of people not understanding the idea of running an installer once and then running the thing it installed after that. Any number of Windows users who have never seen cmd.exe (or Powershell or any other alternative) before.
And the install manager makes things worse because the `py` name conflicts with the old launcher, and of course nobody (at least, among the people actually wrestling with this stuff) actually reads pages like the one in OP. Everyone tries to learn how to do stuff from third-party sources, and old sources explaining former ways to do things never go away or get updated.
... You know, I think I finally understand why people care about `uv` being able to install Python. (I mean, I'm on Linux so I'm insulated from this anyway, but still.)
In a similar vein, see this page about the performance of the interpreter for the dynamic language Wren: https://wren.io/performance.html
Unlike the Zef article, which describes implementation techniques, the Wren page also shows ways in which language design can contribute to performance.
In particular, Wren gives up dynamic object shapes, which enables copy-down inheritance and substantially simplifies (and hence accelerates) method lookup. Personally I think that’s a good trade-off - how often have you really needed to add a method to a class after construction?
Yes, language design is a hugely important determinant of interpreter or JIT speed. There are many highly optimised VMs for dynamic languages but LuaJIT is king because Lua is such a small and suitable language, and although it does have a couple difficult to optimise features, they are few enough that you can expend the effort. It's nothing like Python. It's not much of an exaggeration to say Python is designed to minimise the possibility of a fast JIT, with compounding layers of dynamism. After years of work, the CPython 3.15 JIT finally managed ~5% faster than the stock interpreter on x86_64.
CPython current state is more a reflection of resources spent, than what is possible.
See experience with Smalltalk and Self, where everything is dynamic dispatch, everything is an object, in a live image that can be monkey patched at any given second.
PyPy and GraalPy, and the oldie IronPython, are much better experiences than where CPython currently stands on.
The problem is that AI has been dominating the conversation for so many years, and they'll get more improvements from removing the GIL than they would from adopting the PyPy JIT.
The JIT would help everyone else more than removing the GIL, I wish PyPy became the reference implementation during 2.7
That is an incorrect analysis. CPython is difficult to JIT because of the lack of thought to the native bindings / extensions, not because of the language itself (as others point out PyPy was way faster long ago)
You're correct. I neglected that; extension API compatibility is a big (the most important?) difference between PyPy and CPython's JIT. Amongst language features that affect optimisation potential, an extension API can be the worst.
Edit: I think what you're alluding to is that tracing JITs can overcome a lot of dynamic language features which make things hopeless for method JITs. Where LuaJIT really shines vs PyPy is outside of JITed loops. (Also memory and compile overheads). I realise this is a bit of a motte and bailey.
That’s basically what is done all the time in languages where monkey patching is accepted as idiomatic, notably Ruby. Ruby is not known for its speed-first mindset though.
On the other side, having a type holding a closed set of applicable functions is somehow questioning.
There are languages out there that allows to define arbitrary functions and then use them as a methods with dot notation on any variable matching the type of the first argument, including Nim (with macros), Scala (with implicit classes and type classes), Kotlin (with extension functions) and Rust (with traits).
> Ruby is not known for its speed-first mindset though.
Or its maintainability, and this is one of the big reasons why. Methods and variables are dynamically generated at runtime which makes it impossible to even grep for them. If you have a large Ruby codebase (say Gitlab or Asciidoctor), it can be almost impossible to trace through code unless you are familiar with the entire codebase.
Their "answer" is that you run the code and use the debugger, but that's clearly ridiculous.
So I would say dynamically defined classes is not only bad for performance; it's just bad in general.
That's yet an other topic, as monkey patching can definitely be explicit in ruby. The dynamically generated things at runtime are generally through the catch all method missing facility that can be overwritten. This can also be done in, say, PHP. It just that the community is less fond of it. Not sure about what most popular ahead of time oriented languages expose as facility in this area, obviously one can always even decide to generate automodifying executable. There is nothing special about ruby when it comes to go into forbidden realms, except maybe it doesn't come to much in your way when you try to express something, even if that is not the most maintenance friendly path.
> In particular, Wren gives up dynamic object shapes, which enables copy-down inheritance and substantially simplifies (and hence accelerates) method lookup.
A general rule of thumb is that if you can assign an expression a static type, then you can compile it fairly efficiently. Complex dynamic languages obviously actively fight this in numerous ways, and so end up being difficult to optimize. Seems obvious in retrospect.
The funding was Microsoft employing most of the team. They were laid off (or at least, moved onto different projects), apparently because they weren't working on AI.
With Python being the main language for AI, isn't like more important to be more performant?
I kinda don't get Microsoft reasoning, maybe they're just tight in money
Python is pretty big as glue in the AI ecosystem as far as I can tell. It also seems to be most agent's 'preferred' language to write code in, when you don't specify anything.
(The latter is probably more to do with the preferences they give it in the re-inforcement learning phase than anything technical, though.)
How does it handle garbage collection? AFAIK GC is the main reason behind Lua's stack-based API: it's designed so that C code never needs to hold a pointer to a Lua object, which means an object will never be garbage-collected while C code is still trying to use it.
OTOH Python does allow C code to hold such pointers - so it requires that code to perform error-prone manual reference-counting.
How does Ruby solve this problem?
reply