Remix.run Logo
YuechenLi 10 hours ago

I wouldn't say Go is IDEAL for AI coding, but it certainly has the case for one of the best programming languages that currently AI uses. Go definitely has its share of problems for human authors because it's so verbose and boilerplate heavy, which means it's less of an issue with LLMs than it is for human coders. Rust is comparatively worse, because LLMs don't make the same coding mistakes that humans do that justifies the existence of the borrow checker, it only seems to get in their way, and they spend more time fighting Rust's infrastructure than writing code.

The biggest barrier to Go adoption seems to be Google's internal resistance to migrate C++/Java code bases to Go and refusal to admit that Go is an amazing application programming language and not really a systems programming language for bare metal OS/driver work. For example, one of the biggest barriers to Fuchsia adoption has been Google asking people to commit to Dart, I think Fuchsia would have fared a lot better as an Android successor/alternative if the official applications programming language just been Go.

(BTW Carbon isn't even a real programming language, it's still somehow stuck at 0.0.0.0 after 4 years of development which is honestly insane.)

Oh, so, little bit of self-promotion: if you like Go but is frustrated with the ergonomics of it, I would ask you to try out the programming language I developed, Oct, for LLM coding which you can kinda think of as my attempt at making Kotlin for Go's Java: It uses a codegen compiler and compiles to a plain Go binary, so it runs on everything that Go runs, and there is a lot of extra features as well: Rust style exhaustive tagged/payload enums/`match`, C#'s immutable records updated with `with`, exhaustive error handling easy parallel concurrency, xUnit.NET style unit test harness, TypeScript style compile time constraints, F# like SI unit system, Go code generation metaprogramming, etc. Would love to have some Go experts here on HN take a gander at it and provide some feedback.

https://github.com/yuechen-li-dev/oct

gr_norm 10 hours ago | parent | next [-]

> Rust is comparatively worse, because LLMs don't make the same coding mistakes that humans do that justifies the existence of the borrow checker, it only seems to get in their way, and they spend more time fighting Rust's infrastructure than writing code.

I have found exactly the opposite to be true: as always, people think they can write safe concurrent code without the machine checking them and end up getting it completely wrong in lots of subtle cases. Except the problem is now much worse because you're not even writing the code, or in many cases, reading it. I prefer a language with a type system that saves me from the review burden of closely checking (and pretty much always finding issues in) concurrency invariants. And even tells me a bit more beyond that about what the code is intended to do.

colwont 8 hours ago | parent | next [-]

Was also going to say this. If anything, the borrow checker in Rust is more likely to save you from LLM issues, because it won't bloody compile.

efnx 9 hours ago | parent | prev [-]

Came here to say exactly this. If you’re not writing the code (or especially reviewing it) then we need stronger type systems and more checks and fewer legal programs. Might as well move all the way to Idris or some not-yet-invented language that humans would find very restrictive.

nylonstrung 40 minutes ago | parent | prev | next [-]

> Go definitely has its share of problems for human authors because it's so verbose and boilerplate heavy, which means it's less of an issue with LLMs than it is for human coders

I think boilerplate & verbosity is an even bigger drawback with LLMs than human coding since context rot and "Lost in the Middle" phenomenon has so much effect on code quality

It seems that LLMs benefit from semantic and syntactical density

virtualritz 9 hours ago | parent | prev | next [-]

> Rust is comparatively worse, because LLMs don't make the same coding mistakes that humans do that justifies the existence of the borrow checker, [...]

That's a pile of bollocks, pardon my French. Source/proof?

And to the contrary:

I've been working on a TS codebase that calls into C++ native/wasm-compiled code for six months now. The code is mostly LLM written.

Over these last six months we had four use-after-free and two other ownership-related bugs in LLM-generated TS code.

Whereas we had zero issues of any such kind with LLM-generated Rust code that sits in another two native/wasm-compiled metacrates we use.

LLMs are not much better at ownership tracking than humans.

Especially if resource acquisition and release are far apart in code and/or somehow nested/stacked/non-straightforward.

afdbcreid 8 hours ago | parent | next [-]

The problem with ownership tracking is that it's global. Humans are bad with global things, linters too, but LLMs are exceptionally bad at them due to the context window and (currently, at least) not knowing enough where to search. So yes I'd expect them to make the same mistakes as human and even more frequently.

lowbloodsugar 4 hours ago | parent [-]

I feel like LLMs and vibe coding have opened up rust to the kind of script kiddie who would previously have been begging for help on r/javascript or whatever.

If there is a problem with global lifetimes then the problem is certainly the person driving (or not) the LLM. Global lifetimes? FFS. Rust is hard because writing services that don’t have bugs is hard.

LLMs are not currently able to vibe a sophisticated application or service in rust. If it tells you it can do it in typescript or python, the it most likely certainly has not and you will have a wonderful time in production. Rust will burst that bubble.

YuechenLi 6 hours ago | parent | prev [-]

I'm curious on what you mean by "TS use-after-free", because as you obviously know, TS is GC'd. I don't have access to your codebase of course, but it seems to me that it is an FFI/native code boundary lifetime bug in the binding between TS and C++/WASM, not part of the TS managed memory. Comparing TS to native C++ FFI and/or manually managed WASM resources interface vs Rust + Rust ownership checked resources interface is kinda comparing apples to oranges here.

And as other commenters here have said, Rust's main issue for LLMs is infectious lifetime propagation, where the borrow checker knows you violated a lifetime constraint but doesn't tell you how to actually solve it, so LLMs get error messages like:

  borrowed value does not live long enough
  cannot borrow `x` as mutable because it is also borrowed as immutable
  lifetime may not live long enough
And instead of trying to reason through the ownership graph, they just take the shortest path to get these things to go away by bypassing the borrow checker entirely, which defeats the entire point of using Rust to begin with.
ameliaquining 2 hours ago | parent [-]

Source? I haven't heard of that failure mode being especially prevalent. (Also, by "bypassing the borrow checker" do you mean unsafe raw pointers, Rc/RefCell, or something else?)

jaynetics 10 hours ago | parent | prev | next [-]

> Go definitely has its share of problems for human authors because it's so verbose and boilerplate heavy, which means it's less of an issue with LLMs than it is for human coders.

If the premise of the article is true, and I think that it is, that's quite the downside for AI coding with go. The premise being that reviewing now plays much more of a role than writing.

Personally, I'd rather review, say, a ruby oneliner that extracts specific row values from a csv file with filter_map, compared to 40 or so lines of go, many of which I'd have to check individually for possible mistakes.

ameliaquining 10 hours ago | parent | prev | next [-]

Go doesn't have any kind of story for incremental migration from C++ or Java; you are talking about rewriting all those codebases from scratch, which is an obvious nonstarter as long as engineering resources are finite.

IIUC Fuchsia uses Dart mostly for UI stuff and Go has never really tried to be competitive there? I don't see much of a reason to suppose this is a serious bottleneck to Fuchsia adoption, as opposed to the obvious reasons why it's hard to displace an existing OS with a huge install base.

foota 10 hours ago | parent | prev | next [-]

> "because LLMs don't make the same coding mistakes that humans do that justifies the existence of the borrow checker"

Citation absolutely needed.

YuechenLi 9 hours ago | parent [-]

Sure, what I mean by that is that LLM makes different kind of mistakes than humans, they usually take the shortest direct route to accomplish their task. You can see that with the Bun Rust rewrite, I don't think any human coder would put as many `unsafe` and `Clone()` and `Arc<Mutex<T>` in their code, so a lot of time, they would just attempt to bypass the borrow checker if they see it get in their way.

ameliaquining an hour ago | parent | next [-]

Bun is an unrepresentative example of a Rust codebase for this purpose because (1) it was a direct port from a memory-unsafe language, and (2) it has a major C++ dependency (JavaScriptCore) whose objects in memory are deeply entangled with its own in very lifetime-complicated ways, which is something like the worst-case scenario for Rust's model of memory safety encapsulation.

foota 9 hours ago | parent | prev [-]

Ah, so it's more that "LLMs just bypass Rust's safety" rather than "LLMs write perfect C"? That's a more fair argument.

sgt 10 hours ago | parent | prev | next [-]

So in terms of the mainstream languages, what would you say would be the most ideal language? (At least until Oct takes off!). Perhaps modern Java? .. Or even Zig?

YuechenLi 9 hours ago | parent | next [-]

C#, only because of dotnet ecosystem and tooling is great. TypeScript is a dark horse candidate, it's a great language with a great ecosystem trapped by JS tooling, and most of all, NPM. Rust is fine if you just tell LLMs to use short borrows only. I wouldn't even say Oct is the most ideal language, it's pretty good at getting LLMs to do science, but probably isn't the right language for all applications.

I have some very heavy criticism for Zig technically, because their whole thing about "no hidden control flow" becomes "shove all the hidden control flow into a second hard to debug runtime that runs at compile time", and manual allocation for everything is incredibly tedious and hard to keep track of in production code. I mean, C++ wasn't ALL wrong, there was a reason that templates exist in the first place, and having the entire generics model be just comptime isn't really a decision I agree with. The way I see it, Zig would probably find a niche as a language that configs C/C++ codebase at compile time instead of the C replacement they want it to be.

There are two more languages I have in the Oct repo, SDSL-V for SPIR-V shader/compute kernel authoring and Concept/Vulkan because the 20k line C Vulkan Prometheus runtime for GPU compute that we built is getting kind of unmaintainable even by AI that making up a new programming language to strangler fig refactor it is honestly the least bad option.

ameliaquining 10 hours ago | parent | prev [-]

For what purpose? Different use cases require different language features.

sgt 8 hours ago | parent [-]

Fair enough but people build simple API's with DB interactions in a variety of languages, Go, C#, Java, Zig, Rust, etc.

ffsm8 10 hours ago | parent | prev [-]

I mean I don't have anything against go, but frankly - it's not really better then modern Java.

Each have their trade-offs, both can support native compiled application code. Some architectures are easier to review and code in golang, but others go much better with Javas richer ecosystem and better composability.