I've come to the same conclusion: don't say in markdown what you meant to say in code - spend the time to make the code more clear. The code is always the source of truth, and stale docs (they all get stale) are a constant drag on the LLMs pattern matching capabilities. If you want the LLM to follow certain patterns, you have to make your code base exemplify those patterns, not write about them.
Exactly! What gets lost in these discussions is the fact that LLMs are models of language. That's it. They produce text which is completely inert, until someone decides to run that code, bake that recipe, or fire at that target.
Consider how trivial it would be to write a program that would destroy every computer on the world. Any competent developer could write this in a hour. An LLM in 5 minutes. The trick is actually getting the code onto every computer in the world and running it! Until someone grants it agency and runs it IRL, the artifact has zero impact.
The models can produce whatever scary text they want. But if a human acts on it, connects that with their email or their drone weapon, it's the human who bears total responsibility. We desperately need some legislation to enforce this; otherwise I see a future where almost any accountability can be avoided by AI-washing the problem.
Frontier models are subjectively worse at this, in my experience. Very intelligent but very prone to expanding scope. I need to spend more time prompting to get good results. Maybe I'm just working on boring stuff that doesn't require "frontier" intelligence?
> This gave me pause. Who had actually made the decision then? Arguably there has been several layers of human review, but the actual source of the decision was hard to pin down.
Cynically, this might be the real reason managers and investors love AI. It diffuses responsibility. No one is accountable. "Oops the AI messed it up" is a convenient excuse for bad management.
> I have not yet encountered a fully satisfying explanation as to why Lisp is perceived as being less readable.
Difficulty is, by definition, relative to one's skill. You cannot so quickly discount the fact that 99% of programming is taught in Java/C style language syntax. If you've had lifelong exposure to Lisp, you might feel exactly the opposite. The author does a poor job of justifying why these pop-cognitive-psych theories should have more weight than prior exposure.
Personally, as someone with decades of exposure to both styles, I look at the factorial example and see everything I love about Lisp syntax - consistent, no magic keywords and syntax to memorize, it represents a tree just like my mental model of code, there's no way to fall through and forget an else, expressions instead of statements, no early returns ... literally everything about the Lisp example is more readable to me. YMMV.
> Difficulty is, by definition, relative to one's skill
It's a factor and not the sole factor. Saying it's "by definition" is incorrect.
> The author does a poor job of justifying why these pop-cognitive-psych theories should have more weight than prior exposure.
There's no reason to believe either way, except one path has decades of evidence. Human behavior is not overcome by programmatic "elegance". The dismissive "pop" prefix is signaling bias.
> no magic keywords and syntax to memorize
ie no syntactic sugar.
Pointless repetition is counter productive.
>a there's no [logical] way to fall through
>b [no way to] forget an else,
>c expressions instead of statements
>d no early returns
b. The interpreter catches it.
d. Pointless execution is counter productive.
> literally everything about the Lisp example is more readable to me
That's a single data point. Statistically it's worse, but you're practiced and apparently still physically able to quickly discern the nested count (or use an IDE). Yet another example of a position that is counter to existing studies. Heavy nesting is error prone, even when a program compiles (eg Monden et al., “Evaluating the Applicability of Reliability Prediction Models between Different Software,” ISSRE 2001)
every time I get to use lisp syntax I feel a sense of relaxation, as if the background stress of thinking about precedence and the meaning of all these magic sigils and control flow constructs just melts away and I can finally see clearly what's going on. my first professional programming language was lisp, and almost every single project in the 35 years afterwards was C style. but it still feels like home.
Like most comments here, I kinda throw up in my mouth thinking about all the weird DSLs that would come from unrestrained abstraction.
What about a slightly different angle: a custom language runtime? The language itself stays true to the original but you build your own custom compiler and dev tooling: an expanded stdlib, LSP, linting, formatting rules, build systems, test runners, package manger, host extension system, etc.
This is becoming somewhat of a reality in the Clojure world. https://clojure.cc/dialects/ lists ~30 languages which are recognized as "Clojure" but have radically different host environments. Of course Clojure has macros too so nothings stopping you from going overboard on the DSL weirdness.
I could see the following scenario: Your company picks Typescript. You evaluate Bun and Deno and others but nothing really works. You take the most promising one, build a little test suite to make sure it stays consistent with the language spec, fork it, and add the runtime features you need. Your dev team still writes Typescript but you have full control over the tooling and how that code works at runtime.
Locksmith is awesome, how am I just now discovering this?
Your comments re: database state are spot on. DDL can fail in subtle ways. It's not even enough to take a snapshot of the current state and validate; things can change under your feet.
Take adding a unique index on a column: a simple CREATE UNIQUE INDEX statement, right? But you realize it will fail if the values aren't unique already, so you run a SELECT query to confirm. Yep, all unique. Deploy the app which runs the migration on startup - fail. A non-unique key arrived in the time between your queries.
Even more fun if you CREATE UNIQUE INDEX CONCURRENTLY and a non-unique key arrives in the middle of the DDL execution.
Wouldn't that indicate an issue in your business logic attempting to do this in the first place?
Or if you are relying on DB to fail and your business side to detect and react, you'd still have that built into the business logic so you can just keep retrying the schema migration until it succeeds (if it's rare this happens).
So while I can see how this can happen, it basically is a bug and it means you are doing the migration yet the invariants are not going to be satisfied. Basically, even if it succeeds, you will have future inserts fail with unique constraint being broken.
reply