Hacker News new | ask | show | jobs
by sundarurfriend 44 days ago
The tools the language gives you to create those abstractions make a lot of difference, however.
2 comments

But every abstraction that an LLM has to write is a choice. Your way of writing Python may not match that choice. The next run of the agent might not choose the same way.

Because the language gives you many different tools, an LLM generated codebase can get inconsistent and overly complicated quickly. The flexibility of Python is a downside when you’re having an LLM generate the code. If you’re working in an existing codebase, it’s great - those choices were already made and it can match your style.

When an LLM has to derive its own style is when things can devolve into a jumbled mess.

To me applying LLMs to a python (or similarly dynamic) code base where it’s currently spaghetti and monkey patched, it can miss things just like I can.

But… I have to admit Opus 4.7 has been very pragmatic in detecting root causes and proposing sensible fixes to bugs in this situation (ie bugs encountered in production not compile time).

It’s also fine at matching current styles and conventions (which is great if they are good styles and conventions).

In terms of new code, rust would have been near impossible to write with such a high degree of non-local reasoning, so I’m assuming these bugs wouldn’t be present.

The larger models really are more reliable at following instruction and reasoning their way to solutions. I haven't found that the harness makes that much difference. CoPilot, Claude, Pi, all see similar results for me. What really does make a difference is clean task separation and a clear plan / todo / implement workflow. I've consolidated a lot of the way I work with agents in https://www.agentkanban.io - the task board keeps the tasks discrete and minimal. I built in plan todo implement into the agent instruction that binds the board task to the chat.
That’s why proper using LLMs on large python codebases establish coding standards docs and tests. Turning the LLM loose is chaos, but having clear arch and naming and other standards can get pretty consistent results.
Name one of those abstractions that is missing in Python.
You joking?

- strong typing - real concurrency (heaven forbid you want a background task without having to spool up an external message queue and worker) - immutability - limitations in error handling (sort of just typing really) - limitations in nullability (also typing) - memory layout is usually hidden or abstracted away - no actual private methods or classes

That's far from a complete list, but maybe you're taking for granted the typical pythonic conventions that many practice. It requires a ton of work to design and architect python systems of any non-trivial size for maintainability and understanding. No language is perfect, but there are plenty of languages that make supporting complex systems easier than python.

> strong typing

Python is a strongly typed language. Strong and Static typing aren't the same thing.

You are obviously correct, but even if we let aside parent's confusion about strong/static typing, it's a weak argument.

Python does provide type annotations and extensive tooling to make static analysis, so this whole "missing abstractions to help with understanding" is simply false. You can even setup a python project to make annotations mandatory.

There are plenty of things to criticize about Python - performance, packaging and multiplatform distribution come to mind - but to think that it is missing the tools to help build and understand complex codebases is frankly absurd.

In all the years I used Python at startups and firms, there always was extremely heavy resistance to using types correctly if even using them at all. Not one of the firms would have passed at even 80%. Moreover, me encouraging its use was always met with antagonism. In summary, Python types are a disaster for code comprehension and maintainability because they're optional. So you're right that Python has the tools, but wrong overall because you shouldn't be needing tools for something that should be a default.
You are moving the goalposts. The point is that the abstractions exist. You can use them if you want and they will help you to build an understanding and managing complexity if you do.

If you inherit a complex-but-working python code base and you think that types would help you, getting an LLM to add type annotations and enforce checking is certainly less work than "rewrite it in Rust".

Plenty of teams in startups will ignore automated testing as well, it does not mean that python is lacking the tools for it, nor does it mean that a hypothetical language that mandates 100% test code coverage would be better to "build understanding" or "managing complexity".

you probably mean that python is not static typed.
So, the abstractions are there, you just happen to think that the implementations are flawed or limited. This is not the same as claiming they are lacking.
No, they're not there. Did you read my comment? It's not just flawed or limited implementation, those are things that python just doesn't have.
It absolutely does.

- Typing annotations + mypy can completely help you build and understand a complex system. WIth pyright you can even analyze code that is not annotated. The tooling that enables developers to design and conceptualize their application around the type abstraction is there. You make it sound like people can write`x = "2" + 20` in python like in Javascript or PHP4.

- Concurrency: take your pick of multithreading, multiprocessing or asyncio. The abstraction of a thread model is there. The abstraction for an event loop is there. Would it be nice to have something like the Actor model as well? Sure, but to go from that to "python does not have it" is a completely wild take.

- "No actual private methods or classes": I mean, really? Obviously classes are supported. You can create different classes by composition, you can create a hierachical structure. You can use Protocol to define types that must implement interfaces. You can define functions that are overloaded and you can have method dispatching. All of these ABSTRACTIONS are provided. It's not because they are not forced on you that they don't exist.

Not the person you replied to, but I think the point is that it isn’t really that interesting to point out that you can achieve certain things in Python with enough diligence.

Practical experience shows that languages that force some strictness about things that are known to be sources of trouble as complexity grows unsurprisingly make it easier to manage those sources of complexity.

It is vastly easier to write a performant, multithreaded program in Rust than it is in Python. That doesn’t mean it is easier to write all programs in Rust than in Python - it isn’t.

As far as I know python type annotations are not enforced at runtime, these are really just helpers or extensions to your local dev environment

It's interesting to me that Python requires third party tooling (mypy) but we are still giving credit to Python that it has all the tools it needs

Yes, complex systems have been built in Python but that's despite it's tooling not because of it

Our python applications are all mypy, and we have been experimenting with the uv solution as well. I'm glad that Python has type annotations and classes but it sure doesn't feel the same as a statically typed language