- there is a lot of software, and there is about to be a whole lot more - most of it is not very good - slow, buggy, clunky - dependency sprawl - supply chain attacks - and now we're asking even more from our software than ever before - not really hackable - not really visible / homoiconic - unfortunately, merely regurgutitating the software we already have isn't going to be great - produce much more software than any one could ever meaningfully review - so, how does one build correct, optimal, integrated software? - if software is so cheap, why can't we make it really good? - if we can quickly and cheaply rewrite software from and to any language, where do we end up - switching costs near zero, incremental adoption eventually becomes less important - where do we want to end up? - what characteristics would the last language have? - would it look like an existing one, or something totally different? Higher Order Programming - the history of programming is one of monotonically increasing levels of abstraction: from handcrafting gears, to wiring up vacuum tubes, to punching cards, to coding assembly, to writing C, to programming Java, to scripting Python, to asking an LLM to script Python. - climbing the ladder of abstraction yields more output for every bit of effort - so we gradually remove ourselves from the cumbersome burden of having to actually spell out exactly what we want the machine to be doing: which electrons? which bits? which registers? what memory? what computer? where computer? when computer? - it follows then that we might want to go all the way, that the ultimate sophistication of programming is not programming at all, but more like "talking to a colleague"? - oh, how great software could be, how magnificient, how accessible, if only we could make programming as simple and unconstrained as natural language? - if we didn't have to write code at all, nor trouble ourselves with any of the nuances and rigor imposed by formal languages! - one can only imagine the splendidness of an ecosystem of unconstrained creation! - fortunately, magnificiently, we already have precedent to understand what that low-code, high volume engineering evolves into: game development! - as many nerds will know, early on, game development - even more so than software development - was a complete dredge, and only a self-selected guild of turbonerds could pull it off successfully. - then, eventually, the nerds figured out how to package the hard bits into reusable components and evolve more complete, higher level packages of reusable software components we call a "game engine". - initially, when using an engine, maybe you didn't always get exactly the same level of control, or even hit quite the same highs as the best hardcore engineers. - but it was a lot more productive, and it enabled a scale of project - better tools also enabled more people like game designers, writers, and artists, .. to more directly contribute to the game (visual scripting, material editors, ..) - so: - lot of the time is just iterating in some more interactive editor - sometimes you "play" the game, sometimes you edit the game, sometimes you build new tools to help you edit the game - continuous granularity - reusable parts, "asset stores" (ShadCN), .. - it's all part of the game Long Live Code - "coding is solved" ("bugs not solved yet") - well, define "coding", define "solved"? - if we increasingly work through other tools, why invest in a language? - it's a fair question though: why should we even think about code at all if it can all be written by AI anyway - in some sense, this is like asking we care about numbers when calculators exist - what even is the point of code? why did we ever write code in the first place? - code, in itself, is inert and useless - nobody really wants code much like nobody wants software or computers in and of themselves - the code is not the product, and usually the software is not the product, either - as long as there are humans involved at the edges and on the sign off, we need some common ground - programming is about problem solving, about iterating on a solution and then formalising it in a repeatable form. - in the olden days, we used to solve problems with artisinal human-directed next-character-prediction, now we can often work at a higher level. - I want to know, what is the space of all possible software programs to solve my program, and how do I most efficiently get there, where do I go when I'm there, how do I stay in the right place, and so on - abstraction, yes, but not purely abstraction of specification, also abstraction of exploration, with full specificity available on demand - I've tried that, it doesn't work, I don't want to do that - but we must still understand, or the software sits in some weird disconnected castle in the sky that serves nobody - (well over a year of "vibe coding" has shown this pretty concolusively) - if programming is really just about problem solving, and code is just one medium for formalising solutions, we should expect to see some other evolved forms at varying levels of abstraction - indeed, spreadsheets have worked for decades, game dev people have been doing this for a while, we have now figured out a new way to prompt simple software into existence - historically, when some more "accessible" programming-ish becomes too common, the "real" programmers no longer consider it programming. thus, excel is not "programming", just like image classification is not "AI" - and of course, there is the trivial but important point that we're already not writing most code ourselves - the OS, standard libraries, dependency ecosystems, some compiler/transpiler is writing the actual low level code for us, .. - old adage that a complex system that works starts from a simple system that works - in any non-trivial systems I have seen, there is no useful separation of the system and its "specification" - sometimes the exact sequence of steps matters, sometimes it does not - the granularity of the specification to care about depends strongly on how standardized the solution is. - every attempt to put something purely "above" code and then have it define the behavior of the software with sufficient specificity ends up reinventing code in a worse way (config languages, Gherkin tests, drag and drop coding tools, "APIs will replace everything", etc.) System Scaffolding - a new kind of user is coming online, and there is a lot of excitement about "agent first design" - a myriad of developer-adjacent tools are being rebuilt to become "agent native". - It's not entirely clear what "agent native" means, beyond good APIs, high performance, open standards, which all just sounds like building software in the way we should have done anyway. - most things that are "good for agents" - fast iteration, clean boundaries, programmable software - are good for humans too, we just haven't had the opportunity to the big rewrite until now - like with every technological shift, what are the new abstractions, what is the new shape of software and how do we get there? - our tools for building, interacting with, understanding software are pretty primitive - if everything is code, how do we make sure it's the right code? - "oh just have the AI tell you if the code is right" but again what is right? - (in this sense, the "alignment problem" feels much more like a product and legibility problem, and certainly not merely an intelligence problem, which is short term bearish but long term very bullish) - this does not magically go away with more abstractions or "smarter AI" - understand the shape of software and the space of all possible software - make a map - much better static and dynamic analysis - "software in motion" - code is going to run everything, even more so than it already does (literally) - fundamentally, there is not a single test, suite of tests, mathematical proof, or any other final gate that you can run to convince me that some non-trivial general program is correct - (mathematical proofs are ofc very useful for rigid and fully formalizable systems) - doesn't matter whether it's human written or not, software is just very complex - and the only way to assess "correct" for any interesting software is to see it in motion under many different angles, over time - I don't know what I want until I see it, and I also don't know what I don't want until I see that too - correctness is an iterative process, alignment is continuous, the shape is changing - "correctness" must be specified acrosss many layers to systematically exclude all the things we do not want - incremental, iterative, multi-level precision - alignment requires visibility, we cannot align what we cannot see - need a common vocabulary - correctness is much more iterative, squishy, and multimodal than some cold mathematical proof - (especially as we get into squishy computation!) - visibility and precision must be built on a solid foundation, incrementally - precision requires looking systems.. - .. from many angles, in detail, high low, statically and dynamically, in motion, statically, all sorts of dynamics, ... - you can't engineer precision and alignment (i.e. understanding) into a system post-hoc (or at least, only with great difficulty that far exceeds the cost of doing it properly from the start) Boring Software - there is something beautiful about doing the most with the fewest possible parts - in programming, a minimal, simple language like C or even Go is elegant, the least parts to get the most done, with deliberate "no" to the last 20%. - even "multi-paradigm" languages like Java or C# that have organically accumulated more systems-y features over time do not (attempt to) cover the complete spectrum - (though very few people would have called either "minimal" at the time they were introduced) - boring software must mean complete software, an integrated stack, since that has fewer parts. - tremendous advantage to using a single language for everything, as shown by the popularity of e.g. TypeScript monorepos (suboptimal though they are in various respects) - if software is going to become even more ubiquotous, how do we fill thos elast 20% - TypeScript is a great foundation - there is already wide range of prior art in the realm of "TS ergonomics with systems performance", but that is just one aspect of what we'Re trying to do here - static hermes, assembly script, ... - all in - not incrementally adoptable. - (though we do have C ABI ofc) - what is the ideal final system? - it is very tempting to get a blank piece of paper and dream up the "perfect system" - but it probably does not matter per se - pragmatic perfection - I don't want to learn a new and totally different language, I already know the ones that exist - I like imperative programming - I want to use the Web, basically TypeScript, and build with stuff I'm familiar with - I want to use what I already know, with minimal new learning - Predictable, known behavior - even if imperfect - is better than something totally new, theoretically perfect thing - (besides, we usually figure out that the grass isn't quite greener anyway..) - the current set of modern programming languages is pretty good - colored functions are fine, Promises are fine actually. microtasks a little weird but whatever - number is okay as a type actually, it's convenient - bigint and string as lowercase primitives are fine, not ideal, but fine - all in all, it's fine, and most importantly: it's familiar - (... and it's how the web works!) - no intention of "fixing" anything that is sound but clumsy and can be trivially linted for - more importantly, want a complete language that can represent all the things we need, and then constrain by package / library (but it all has to go togetheraaa) - so let's just get on with it - what is the minimum edit distance from TypeScript to a universal language that keeps TypeScript's ergonomics and familiarity, is strict and sound and analysable, and also runs reliably at machine speed? - basically, what is "TypeScript++"? TS that runs predictably like JVM/CLR/Go with som Rust-y bits - the question is explicitly not what is the "best theortical version if we did TypeScript all over again". - instead: "what is the most typescript we can make it, removing only what is absolutely necessary" (default decision = keep) - what's the most boring thing we could build? - don't try to be cute or clever or fancy - no "improvements", only corrections - don't "fix" what's not actually broken - only use boring ideas already proven by other languages / libraries / .. - safe, sound, predictable, and above all: familiar TypeScript++ - TypeScript is already tantalizingly close to being a serious, native, universal programming language - the dichotomy between "scripting languages" and "systems languages" no longer makes much sense if it's not humans doing the typing (assuming "compile times" are fast) - TS++ fashions itself as a "superset of a strict subset of TS", which is vaguely reminiscient of the relationship between C and C++ - mechnically, what is the ergonomic ladder of TS++ between TS -> Rust, what are the minimal things to remove for unsoundness, and the minimum features to add to cover the whole universal language spectrum - there are a lot of interesting details details in making "TS++"