The (well-known) Sapir–Whorf hypothesis (if dont know it, look it uop) is often invoked for natural languages, but there’s a pretty direct analogue for programming languages: the language you "think in" during solving a problem biases which abstractions and idioms you reach for first.
If you force an LLM to first solve a problem in a highly abstract language (Lisp, APL, Prolog) and only then later translate that solution to C++ or Rust, you’re effectively changing the intermediate representation the model works in. That IR has very different "affordance", e.g.
- Lisp pushes you toward recursive tree/list processing, higher‑order functions and macro‑like decomposition. (some nice web frameworks were initially written in LISP, scheme, etc...)
- APL pushes you toward whole‑array transforms, point‑free pipelines and exploiting data parallelism. (banks are still using it because of perforance)
- Prolog pushes you toward facts/rules, constraint satisfaction, and backtracking search. (it is a very high abstraction but might suit LLMs very well)
OK, and when you then translate that program into C++/Rust/python, a lot of this bias leaks through. You often end up with:
Rule engines, constraint solvers, or table‑driven dispatch code when the starting point was Prolog.
Iterator/functor pipelines and EDSL‑like combinators when the starting point was Lisp.
Data‑parallel kernels and "vectorized" loops when the starting point was APL.
In principle, an LLM could generate those idioms directly in C++/Rust. In practice, however, models are heavily shaped by their training distribution and default prompts. If you just say "write in Rust", they tend to regress towards the most common patterns in the corpus (framework‑heavy, imperative, not very aggressively functional or data‑parallel), even when the language would support richer abstractions.
By inserting a "thinking" step in a different paradigm, you bias the search over solution space before you ever get to Rust/C++. That doesn’t magically make the code better, but it does change which regions of the design space the model explores.
Same would also be true for python which is already a multi-idiomatic language.
So it might be a good idea to learn a portfolio of different languages and then try to tackle a problem with a specific language instead of automatically using python/go/rust because of performance.
Something to consider...
p.s. how would a problem be solved when the LLM would have to write it first in erlang? Is it the automatically distributed?
p.p.s. the "design pattern" of the GoF comes automatically to my mind, which might be a good hint to the LLM to use.
You can of course use any language but here is my advice: you should use the language that you know best to make your life as uncomplicated as possible when you want to understand what the LLM was creating.
Remember, you are the judge whether the code is OK and if you use assembler you might get really performant code, but can you trust it?
Of course it might be a good incentive to learn rust or go. Or challenge yourself to learn something really cool like LISP, COBOL, FORTRAN, APL or J. (just kidding...)
Previously in my life as an IC, I wrote a lot of Golang. I worked on the larger end to end encrypted video calling service.
I hated it. I was dreaming of Rust the entire time to release me from the hell of if err != nil dozens of time per day.
After hours with LLMs I've changed my tune. There have been 5 clients of mine (who have excellent engineering teams) but cannot get coherent results out of LLMs using python or Typescript.
I arrived back at Golang being a frustratingly simple, consistent, and low-thrash programming language which inadvertently made itself well represented in the training corpus [1].
My concession is that if you are going to write a median program (reading/writing files, network, db, etc.)...
Pick Golang especially if you've never used it. LLMs are extremely good at it, frustratingly so.
In the long run there is no alternative to really reading your codebase and understanding what is going on. You can leave the nitty gritty details to the LLM but you have to be in the drivers seat and know how the parts of your codebase works together. You have to be the architect and can leave the plumbing to the LLM, but dont try to make a plumber an architect.
God I miss openstep and CDE. It needs 16MB RAM (yes MB!) and together with a lighweight firefox clone you get everything you need. Eye candy is nice to have but not at that cost.
A 1.5b can be very good at a domain specific task like an entity extraction. An openrouter which routes to highly specialised LMs could be successful but yeah not seen it in reality myself
TOTP is also just password + some computation. So where is the difference?
There is a lot of security theatre around TOTP with the QR code and then need of an app but you can write a 8 liner in python that does the same when you extract the password out of the QR code.
Yes, TOTP is a secret + computation, and generating it is trivial once you have the secret. The security difference is that the TOTP secret is separate from the user’s password and the output is short-lived. Each of the two factors address different threat models.
You are supposed to store the password in a Secure Enclave, which you can only query for the current token value. You are also supposed to immediately destroy the QR code after importing it.
As I already mentioned, the fact that people often use it wrong undermines its security, but that doesn't change the intended outcome.
> That's at best a retcon, given given that the RFC was first published in 2008
How so? Apple didn't invent the idea of a secure enclave. Here is a photo of one such device, similar to one I was issued for work back in ~2011: https://webobjects2.cdw.com/is/image/CDW/1732119
No option to get the secret key out. All you can get out is the final TOTP codes. If anything, having an end-user-programmable "secure enclave" is the only thing that has changed.
I think they probably meant "Secure Enclave" in the same way that people say "band-aid" instead of "adhesive bandage", "velcro" instead of "hook and loop fastener", and "yubikey" instead of "hardware security token".
>Most TOTP apps support backups/restores, which defeats this.
Citation needed?
Yubico authenticator doesn't (the secure enclave is the Yubikey).
I'd be very surprised if MS Authenticator and Authy (which I don't use but are the most popular apps that I know of) support such backups
> Citation needed? Yubico authenticator doesn't (the secure enclave is the Yubikey). I'd be very surprised if MS Authenticator and Authy (which I don't use but are the most popular apps that I know of) support such backups
Google Authenticator has an export option that I've used in the past, so that one does it for sure. Authy allows cloud-based synchronization in any case, so exporting seems quite possible. MS Authenticator also allow cloud sync, so probably exporting is not difficult.
Well I don't disagree that it might be possible to abuse cloud sync in some way to export the secrets, but it's not quite as egregious as just including the secrets by default in an app backup
Not perfect, but (imho) still better than SMS 2FA, mail 2FA, or lack of 2FA
On the contrary - perfect security is only possible if your system is an inert rock. Or not even then, as the users could still use the rock "wrong" by beating security maximalists over their heads with it.
Also honestly TIL that TOTP are somehow supposed to also enforce a single copy of the backing token being in existence. That's not just bad UX, that feels closer to security overreach.
People in tech, especially software and security folks, tend to miss the fact that most websites with 2FA already put a heavier security burden on their users than anything else in real life. There's generally no other situation in peoples' lives that would require you to safely store for years a document that cannot be recovered or replaced when destroyed[0]. 2FA backup codes have much stricter security standard than any government ID!
And then security people are surprised there's so much pushback on passkeys.
--
[0] - The problem really manifest when you add lack of any kind of customer support willing to or capable of resolving account access issues.
Actually, the real countermeasure to PTH is to disable NTLM auth and rely only on Kerberos (and then monitor NTLM as a very strong indicator that someone or something is attempting PTH)
Of course kerberos tickets can be abused too in a lot of fun ways, but on a modern network PTH is pretty much dead and a surefire way to raise a lot of alerts
(You are absolutely right that privileged accounts must never login on less privileged assets, however!)
Yeah...we just went through this process over here. I was more just making the point that "If its possible to use a system wrongly which undermines its security, it is already broken" isn't always true. I guess you could argue its NTLM there thats 'already broken', but the idea was more "SysAdmins are sometimes given red buttons to never press under any circumstances."
If I managed to intercept a login, a password and a TOTP key from a login session, I can't use them to log in. Simply because TOTP expires too quickly.
That's the attack surface TOTP covers - it makes stealing credentials slightly less trivial by making one of the credentials ephemeral.
The 30 seconds (+30-60 seconds to account for clock drift) are long enough to exploit.
TOTP is primarily a defense against password reuse (3rd party site gets popped and leaks passwords, thanks to TOTP my site isn't overrun by adversaries) and password stuffing attacks.
Note that a prover may send the same OTP inside a given time-step
window multiple times to a verifier. The verifier MUST NOT accept
the second attempt of the OTP after the successful validation has
been issued for the first OTP, which ensures one-time only use of an
OTP.
Assuming your adversary isn't actually directly impersonating you but simply gets the result from the successful attempt a few seconds later, the OTP should be invalid, being a one time password and all.
WebAssembly in the browser does feel great when you look at things like Pyodide/Pyolite, JupyterLite, xeus, webR and even small tools like texlyre – you get a full language/runtime locally with zero server, just WASM and some JS glue. The sad part is that VS Code for the Web never really became that kind of self-contained WASM IDE: the WASI story is focused on extensions and special cases, and running real toolchains (Emscripten, full Python, etc.) keeps breaking or depending on opaque backend magic. So right now the best “pure browser” experiences are these focused notebook/tool stacks, not the general-purpose web IDE people were hoping vscode.dev would become.
MCP is just a small, boring protocol that lets agents call tools in a standard way, nothing more. You can run a single MCP server next to your app, expose a few scripts or APIs, and you are done. There is no requirement for dozens of random servers or a giant plugin zoo.
Most of the “overhead” and “security nightmare” worries assume the worst possible setup with zero curation and bad ops. That would be messy with any integration method, not only with MCP. Teams that already handle HTTP APIs safely can apply the same basics here: auth, logging, and isolation.
The real value is that MCP stays out of your way. It does not replace your stack, it just gives tools a common shape so different clients and agents can use them. For many people that is exactly what is needed: a thin, optional layer, not another heavy platform.
> Most of the “overhead” and “security nightmare” worries assume the worst possible setup with zero curation and bad ops.
You'll be surprised to learn that these are extremely common, even in large corporations. Security practice is often far from ideal due to both incompetence and negligence. Just this week, I accidentally got the credentials for the account used in our CI systems. Don't ask me how this could possibly happen.
Nah, MCP still has security issues, you can create an MCP server to exfil sensitive data by creating tools which AI at first things are doing something else but then in params you ask it to give sensitive info
Sorry but disagree. For me the main part is the resources, which automatically get mounted in the computing environment, bypassing a whole class of problems with having LLMs work with a large amount of data.
The (well-known) Sapir–Whorf hypothesis (if dont know it, look it uop) is often invoked for natural languages, but there’s a pretty direct analogue for programming languages: the language you "think in" during solving a problem biases which abstractions and idioms you reach for first.
If you force an LLM to first solve a problem in a highly abstract language (Lisp, APL, Prolog) and only then later translate that solution to C++ or Rust, you’re effectively changing the intermediate representation the model works in. That IR has very different "affordance", e.g.
- Lisp pushes you toward recursive tree/list processing, higher‑order functions and macro‑like decomposition. (some nice web frameworks were initially written in LISP, scheme, etc...)
- APL pushes you toward whole‑array transforms, point‑free pipelines and exploiting data parallelism. (banks are still using it because of perforance)
- Prolog pushes you toward facts/rules, constraint satisfaction, and backtracking search. (it is a very high abstraction but might suit LLMs very well)
OK, and when you then translate that program into C++/Rust/python, a lot of this bias leaks through. You often end up with:
Rule engines, constraint solvers, or table‑driven dispatch code when the starting point was Prolog.
Iterator/functor pipelines and EDSL‑like combinators when the starting point was Lisp.
Data‑parallel kernels and "vectorized" loops when the starting point was APL.
In principle, an LLM could generate those idioms directly in C++/Rust. In practice, however, models are heavily shaped by their training distribution and default prompts. If you just say "write in Rust", they tend to regress towards the most common patterns in the corpus (framework‑heavy, imperative, not very aggressively functional or data‑parallel), even when the language would support richer abstractions.
By inserting a "thinking" step in a different paradigm, you bias the search over solution space before you ever get to Rust/C++. That doesn’t magically make the code better, but it does change which regions of the design space the model explores.
Same would also be true for python which is already a multi-idiomatic language. So it might be a good idea to learn a portfolio of different languages and then try to tackle a problem with a specific language instead of automatically using python/go/rust because of performance.
Something to consider...
p.s. how would a problem be solved when the LLM would have to write it first in erlang? Is it the automatically distributed?
p.p.s. the "design pattern" of the GoF comes automatically to my mind, which might be a good hint to the LLM to use.
reply