hmm, yeah given LLM's ability to churn out lots of code quickly and be overly verbose in that code that is a potential downside. That it could in a quick one time edit create so much intellectual overhead that Python might be the wrong language to understand what is going on.
What language do you feel is easier to reason about in the large?
Haskell would be my vote, and Rust too, actually, both because of their very strong type systems. The type system lets you very quickly figure out what something is before you figure out what something does, and it turns out that separating those two concerns as hard as those two languages do often results in doing the whole one-two punch faster.
Haskell does not qualify for a large training set, though. (Nor for readability in my opinion)
I think I have never seen haskell software made wih LLM's but well, aside from university, I have not seen Haskell code at all.
(Also Haskell purists I would associate with people who avoid LLM's)
I would rather go with Rust given these choices.
But I have good results with typescript (or javascript for simpler things). Really large set of examples. Tools optimized for it, agents debugging in the browser works allmost out of the box.
And well, a elaborate typesystem.
I give up rust because it’s not functional enough. There aren’t many things Claude can prove about a table viewer, and Haskell fits very well, and have enough libraries. Claude is pretty good at Haskell. I barely write Haskell before but I do know monad.
I used Claude to generate Haskell and it works really well. Claude struggles sometimes with respecting abstraction boundaries, but Haskell enforces parts of those boundaries in its type system better than a lot of other languages (if a module can’t do IO, for example).
Works well, in my experience. Sometimes the agent does weird stuff that you have to rewrite, but I get the sense that this happens in any language.
Maybe Haskell’s training set is not large enough, but it seems to work despite the smaller training set.
In the window of Haskell-like and highly readable, I’d throw OCaml and F# out as strong candidates.
In practice your code can be cleaner than Python, deeply flexible naming capabilities including full sentences with backticking, efficient and powerful discriminated unions and types enable near-English domains, the type system keeps you honest and provides exhaustiveness guarantees, domain modules of applied functions are obvious and locally coherent domain grammars, and there is potent DSL support to create mini-grammars for legibility and expressiveness.
I used to write python by hand to reason then type it up in C#. F# is just as easy with a pen, but far more powerful and with a powerful type system and aggressive compiler. OCaml and F# are also highly token efficient languages, beating Python across the board for agentic work.
I’d add perl (similar runtime semantics as python, but at least sigils give you some hint of developer intent. If you see &@%$$ck() in perl, you know you’re in for a ride).
I’d also add, C, C++, Rust, Java, Swift, Typescript, Ruby, Lisp, Make, Awk and Sed.
I've "written" a lot of rust via LLMs, and the rust tooling and features give a lot of useful guard rails to LLMs that produce pretty good code overall, certainly compared to the python I've seen it crank out. Clippy and fmt alone often cause the LLM to hit a snag and realize it's mistake and take a better approach. It's quite a powerful combo IME
There are many languages with similarly strong type systems - Scala, Kotlin, OCaml, etc (and nowadays, even Java). A GC may also be an advantage in that the LLMs may get it right in less tries.
I'd say Java, because it has a massive footprint amenable for training, and a strong type system (does not have sum types though and those are trendy).
You'd have to steer the LLM to use the style you want, and not massively overarchitect things though, but that's going to be an issue nonetheless.
I like C#, it's how I make a living, but it's way too large today. I can program in valid C# and it looks like C or I can program in C# and it looks like a functional language or I can program in C# and it's looks all angle-brakety like C++.
The problem with that is everyone has an opinion on what good C# looks like.
For personal projects, I'll take a much simpler language any day.
C# has recreated the C++ dialect conundrum. For some it’s effectively an idempotent functional language with unfortunate failings of exhaustiveness, for others it’s Java ca 2009, for others it’s C++ but not quite.
Discipline, effort, linters, reviews, more discipline, more effort, retraining, discipline… and foot guns everywhere because so much of the adaptation has been a 95% solution. Personally I got everything C# promises even now when F# was dropped years ago and have found the interim pretty annoying.
While C# is a particularly egregious case, I think all reasonably long-lived, popular languages suffer from this problem. Go is being very intentional about not falling in this trap, but JavaScript, Python, Java.. modern/idiomatic code in all of these languages looks very different from the code you'd write using them 15 years ago.
At my workplace, we use the .editorconfig and static analysis heavily to push us towards a consistent C# feature-set and style. This plays the same role that pyupgrade would in python, for instance.
I do agree. C# is an hidden gem for IA. There are not that much different ways to get somewhere so the model have probably been trained on the framework and libraries everybody uses (the Microsoft ones).
Compared to most languages, including Java, C# will have a hard time letting you compile incoherent code.
You barely need any dependencies other than aspnetcore and efcore for most applications and your AI knows them well.
It’s easy to do TDD with it so it’s easy to keep your IA from hallucinating.
I definitely agree with the sentiment. However this part.
> There are not that much different ways to get somewhere
This is far from true.
C# is a language where you can operate on the raw pointers through unsafe keyword. On the other end of the spectrum, you can have duck-typing in dynamic blocks.
For operating on collections you can use old style loops, or chain of lambdas or sql like syntax.
I have been coding in C# old school way for most of my life at this point, and I feel like I'm in a foreign land reading code from some other C# projects.
What language do you feel is easier to reason about in the large?