leetharris
3 months ago
I am not sure how to really refine this thought I have had, but I have this fear that every language eventually gets so bloated and complicated that it has a huge barrier to entry.
The ones that stand out the most to me are C# and Typescript.
Microsoft has a large team dedicated towards improving these languages constantly and instead of exclusively focusing on making them easier to use or more performant, they are constantly adding features. After all, it is their job. They are incentivized to keep making it more complex.
The first time I ever used C# was probably version 5? Maybe? We're on version 12 now and there's so much stuff in there that sometimes modern C# code from experts looks unreadable to me.
One of the reasons I have so much fun working in node/Javascript these days is because it is simple and not much has changed in express/node/etc for a long time. If I need an iterable that I can simply move through, I just do `let items = [];`. It is so easy and hasn't changed for so many years. I worry that we eventually come out with a dozen ways to do an array and modern code becomes much more challenging to read.
When Typescript first came out, it was great. Types in Javascript are something we've always wanted. Now, Typescript is on version 5.6 and there is so much stuff you can do with it that it's overwhelming. And nobody uses most of it!
This is probably just old man ranting, but I think there's something there. The old version I used to debate about was C vs C++. Now look at modern C++, it's crazy powerful but so jam packed that many people have just gone back to C.
BiteCode_dev
3 months ago
Javascript is not simple AT ALL.
It has 3 ways to declare functions, multiple variations on arrow functions syntax, a weird prototyping inheritance system, objects you can create out of "new" on functions, object literals that can act an pseudo-classes, classes, decorators, for-i loop + maps + filter + for-in loop (with hasOwn) + forEach, async / await + promises and an invisible but always-on event loop, objects proxies, counter-intuitive array and mapping manipulations, lots of different ways to create said arrays and mappings, very rich destructuring, so many weirdnesses on parameter handling, multiple ways to do imports that don't work in all contexts, exports, string concatenation + string interpolation, no integer (but NaN), a "strict mode", two versions of comparison operators, a dangerous "with" keyword, undefined vs null, generators, sparse arrays, sets...
It also has complex rules for:
- scoping (plus global variables by default and hoisting)
- "this" values (and manual binding)
- type coercion (destroying commutativity!)
- semi-column automatic insertion
- "typeof" resolution
On top of that, you execute it in various different implementations and contexts: several browser engines and nodejs at least, with or without the DOM, in or out web workers, and potentially with WASM.
There are various versions of the ECMA standard that changes the features you have access to, unless you use a transpiler. But we don't even touch the ecosystem since it's about the language. There would be too much to say anyway.
There are only two reasons to believe JS is simple: you know too much about it, or you don't know enough.
wk_end
3 months ago
I feel like a large slice of JS’s complexity comes from footguns you aren’t really supposed to use anymore; whereas with C# the complexity feels quite layered, multiparadigmatic, something-for-everyone, syntactic-sugary. But I probably know too much about JS and not enough about C#.
EraYaN
3 months ago
At least in C# you can ignore most of it and the complexity doesn't really come from numerous foot guns. You can still write Java 1.6/.NET 2 style C# code just fine, it's all there. The rest of the features can be fully ignored and they won't hurt you.
But then again the newer features they do make writing code a lot nicer, giving more compile time analysis warnings etc hopefully resulting in slightly better code. And the new features also enabled a lot of performance improvements in the runtime which is nice. .NET 2/4 wasn't all that fast, .NET 8 can be a lot faster.
BiteCode_dev
3 months ago
Well, all the people that used JS 15 years ago followed Douglas Crockford advice very much to heart.
debit-freak
3 months ago
> I feel like a large slice of JS’s complexity comes from footguns you aren’t really supposed to use anymore
I'm not inclined to use a language that can't be fixed.
leetharris
3 months ago
Hmm, I understand what you mean. But I think there's a difference between complexity and optionality / versatility.
For example, it has different ways to declare functions because assignment is generally consistent (and IMO easy to understand) and the "simplicity" of Javascript allows you to assign an anonymous function to a variable. However, you can also use a standard function declaration that is more classic.
But I do understand what you're saying. If anything, I think it's generally in agreement with my feelings of "Javascript doesn't need to be more complex."
> There are only two reasons to believe JS is simple: you know too much about it, or you don't know enough.
This is hilarious and probably true. I think I am the former since I've been working with it for 20+ years, but I also think there's a reason it's the go-to bootcamp language alongside Python.
BiteCode_dev
3 months ago
I do appreciate the modern features a lot personally, and the fact they have been added without breaking the world. Interpolation, spreading, map and arrow functions are a huge usability boon. Plus I'm glad I can use classes and forget that prototypes ever existed.
But I train beginners in JS and boy do I have to keep them in check. You blink and they shoot their foot, give the pieces to a dog that bite them then give them rabbies.
girvo
3 months ago
In fact, Javascript is so complex that one of the seminal books on it was specifically "The Good Parts", cutting down the scope of it to just the parts of the language that were considered decent and useful.
Lerc
3 months ago
I think the distinction with JavaScript compared to other 'complex' languages is that you don't have to go beyond "The Good Parts" to achieve significant functionality, and it has become idiomatic to use the good subset.
In some respects I think if there were a well defined "Typescript, The Good Parts" I would happily migrate to that.
I do wonder if there will, one day, be a breaking fork of JavaScript that only removes things. Maybe a hypothetical "super strict" might do the job, but I suspect the degree of change might not allow "super strict" code interacting with non "super strict" easily.
BiteCode_dev has provided a pretty good summary of a lot of the issues. A lot of them have easy fixes if you are prepared to make it a breaking change.
chii
3 months ago
> reasons to believe JS is simple
it's because people are talking past each other, and that's because people are using language wrong, and are merely talking past each other. The word simple is often used to mean "easy" or "familiar".
Simple is very different from easy, and familiar things are easy but doesn't have to be simple at all.
javascript is not simple, but it is easy.
debit-freak
3 months ago
> using language wrong
There is no wrong use of language; there's just people who don't bother to communicate well in the most effective language available. In this case you could simply cohere the two viewpoints since you have insight rather than blaming one party and calling them wrong (...which is wrong).
flappyeagle
3 months ago
[flagged]
liveoneggs
3 months ago
It's on the list of languages that used to be simple, I think.
BiteCode_dev
3 months ago
Yes, but when "the good parts" came out, half of this list was already true.
There is a reason we ignore a good chunk of the language to be productive with it.
nwienert
3 months ago
This is true, but what's also true is using biome or eslint more than half of your complaints are gone. JS has always had bad parts, but today it's a lot easier to avoid them thanks to linters. And if you do stay in the good parts, it's my favorite language, for many reasons.
That said, I hate the constant stuffing of features (though not this one which is much needed), more stuff around JS like WebComponents, or CSS adding a ton of sugar.
BiteCode_dev
3 months ago
I think what saves JS, like Python, is that despite the modern complexity, you can start to be productive in a few days with just the essentials and learn the rest with a smooth curve, slowly as you progress.
bryanrasmussen
3 months ago
>Javascript is not simple AT ALL.
I prefer languages with a small instruction set, as then you can learn all you can do in the language and hold it in your head. JavaScript used to have a small instruction set, I don't feel it does any longer.
Aside from this I don't know that I see any benefit to these structs, although perhaps that is just the article doing that whole trying to write JavaScript like Java thing that making classes and constructors enabled.
leptons
3 months ago
Even if you think Javascript is already complicated, that isn't a reason to make it more complex.
wvenable
3 months ago
Complexity isn't bad. If you have a simple language and you have to something complicated then you still have complexity, it's just expressed differently and uniquely in every code base.
Java doesn't have unsigned integer types because that is "simpler" but that doesn't remove the need to deal with unsigned integers in file formats and network protocols. But now you have to do a convoluted mess of code to deal with that. I'll take a complex language that solves real problems over a "simple" language any day.
mardifoufs
3 months ago
That is still pretty simple as far as mainstream languages go.
DanielHB
3 months ago
You are not wrong, but a lot of the stuff you mentioned is literally a non-issue with any modern JS environment.
It feels like any old language gets this way...
Zanfa
3 months ago
And ESM vs CJS. What should be an inconsequential transition, has turned into a minefield where adding a dependency to your package.json might blow up your build system, testing library or application without warning. Literally wasted weeks of my life debugging this pile of poop that is the JS ecosystem.
devjab
3 months ago
Is this really a JS or a Node issue though? We have no such issues with Bun.
Zanfa
3 months ago
I guess technically Node, but in practice JS, since Node is still the de facto standard non-browser JS runtime. "Just use X" where X is some other build tool/runtime/testing ecosystem is another weird trope that's somehow considered acceptable advice in JS, but would be a massive undertaking for any non-trivial project.
devjab
3 months ago
Maybe if someone suggests Deno or similar, but Bun is a drop in for Node and is as such completely interoperable with your Node code. Its similar to how you can adopt PNPM easily because it’s a drop in for NPM, where as yarn and others are their own things.
jknutson
3 months ago
3 ways to declare functions? I am probably blanking but I can only think of:
``` function foo () {} const foo = () => {} ```
renlo
3 months ago
function x() {/* ... */}
const x = function() {/* ... */}
const x = function foo() {/* ... */}
const x = (function() {/* ... */}).bind(this)
const x = (function foo() {/* ... */}).bind(this)
const x = () => {/* ... */}
const x = () => /* ... */
afiori
3 months ago
Apart from hoisting (which has little to do with functions directly) and `this` these are all equivalent
taosx
3 months ago
Not sure if it counts but there is `new Function("return x;")`
lelanthran
3 months ago
Doesn't `function* ()` count?
After all, you can add a `*` to any existing function without a change in the function or its callers.
wvenable
3 months ago
4 ways
Izkata
3 months ago
5 ways, the arrow functions have two different syntaxes:
() => { return 1; }
() => 1
wiseowise
3 months ago
That’s still one way - arrow function.
Izkata
3 months ago
Well, these have the same result, so if the two types of arrow functions don't count as different then neither should these two assignment versions:
const foo = (function() {}).bind(this);
const foo = () => {};
Edit: And speaking of assignment versions, there's a new comment that adds a third of the same. I kinda get the feeling a lot of the "multiple ways to declare functions" is just people who don't understand how the pieces of javascript fit together and think these are all independent. They're not. Just declaring a function has only a few ways, but declaring a function and giving it a name multiplies that out to some extent.In javascript, functions are first-class objects: they can be assigned to variables and passed around just like numbers or strings. That's what everything except "function foo() {}" is doing.
onsclom
3 months ago
`const foo = function() {}`
mr_toad
3 months ago
Do function expressions count?
kevlened
3 months ago
const x = { foo() {} }
Onavo
3 months ago
Why did JS's with keyword not work out while similar constructs in Python and Ruby were fine?
chthonicdaemon
3 months ago
Python's `with` and Javascript's `with` don't do the same thing. In Python it introduces a context, which is a scope within which certain cleanup tasks are guaranteed, which improves the ergonomics of things that require you to close() at the end, similar to `defer` in Go. In Javascript it allows you to access object properties without prefixing with a name, which leads to confusion about scope.
otteromkram
3 months ago
JavaScript is simple in comparison to other languages. Not many people would disagree.
BigJono
3 months ago
Yep and TS has all of that plus a gigantic layer of bullshit on top.
The web development community has created the perfect environment for nobody to ever get any work done while still feeling like they're being productive because they're constantly learning minutiae.
klysm
3 months ago
Typescript is the best thing to happen to JavaScript since ES6
7bit
3 months ago
Types are great, but I prefer Not having to transpile everything. Stepping throught the TS Code with a Debugger ist non trivial.
nolist_policy
3 months ago
You can use 90% of typescript from pure JavaScript: https://www.typescriptlang.org/docs/handbook/jsdoc-supported...
mightyham
3 months ago
I'm not sure what setup you have, but debugging TS code is pretty trivial. I use vite for all my projects at work and when running the dev server there is seamless integrations with the debugging dev panel in Chrome or Firefox.
klysm
3 months ago
Source maps solve this, it’s not a problem in practice
dingi
3 months ago
If only it had a sound type system.
mardifoufs
3 months ago
It has a very good type system, imo better than most "natively" typed languages.
klysm
3 months ago
Hasn’t caused me any practical problems
ericmcer
3 months ago
Yeah I was almost gonna say it makes this proposal feel redundant. I can enforce object shape pretty well using TS, not sure why we need another OOP like thing that tries to do the same.
klysm
3 months ago
Typescript doesn’t tell the JS runtime anything about what it knows
BigJono
3 months ago
[flagged]
stroupwaffle
3 months ago
Yeah I recommend reading “JavaScript the good parts” and don’t use anything far beyond those. Instead of “compile-time safety guarantees” by these vendor-lock-ins-masquerading-as-open-source, just use the language as it was designed: dynamically, and unit test—because you’re gonna be doing those anyway.
rezonant
3 months ago
This, except for:
> There are only two reasons to believe JS is simple: you know too much about it, or you don't know enough.
There is only one reason to believe JS is simple: because you don't know enough.
afavour
3 months ago
I think in this specific case it's JavaScript's requirement for backwards compatibility that bloats it... but there's a lot you can ignore. Like, you can declare a variable with var, let or const but there's absolutely no reason to use var any more. I feel similarly about the proposals to introduce records and tuples: https://github.com/tc39/proposal-record-tuple... in most scenarios you'll probably be better off using records rather than objects, and maybe that's what folks will end up doing.
But boy does it all get confusing.
> Now, Typescript is on version 5.6 and there is so much stuff you can do with it that it's overwhelming. And nobody uses most of it!
I'm not so sure about that. I think we end up consuming a lot of these features in the TS types that get published alongside libraries. We just don't know it, we just get surprisingly intuitive type interfaces.
dunham
3 months ago
> there's absolutely no reason to use var any more.
So I also thought. And then I recently learned that typescript uses `var` internally for performance.
From src/compiler/checker.ts:
// Why var? It avoids TDZ checks in the runtime which can be costly.
// See: https://github.com/microsoft/TypeScript/issues/52924
/* eslint-disable no-var */
var deferredDiagnosticsCallbacks: (() => void)[] = [];
goodoldneon
3 months ago
If performance is so important for your app that `var` is causing issues then JavaScript is likely the wrong language
nsonha
3 months ago
I can think of a few when hoisting is nice, stylistically:
if (...) var x = ...
else x = ...
/////
try { var x = ...}
catch (error) { x = ... }
/////
for (...) {
var x: NodeJS.Dict<any> = {}
x[key] = ...
}return x
afavour
3 months ago
All of those feel like anti patterns to me. Much more difficult to read.
wruza
3 months ago
The worst anti-pattern here is the catch- and finally-blocks living in a different scope.
Really, who thought it was a good idea that finalization and error handling blocks must have no access to their subject scope? Every damn language copies that nonsense, except for js and its `var` hoisting.
nsonha
3 months ago
That's subjective, Idk about "MUCH more difficult".
All it does is moving the declaration to the correct visual scope, instead of a dangling up-front declaration.
Admittedly, I understand most coders are aready trained to read the latter.
leetharris
3 months ago
> I'm not so sure about that. I think we end up consuming a lot of these features in the TS types that get published alongside libraries. We just don't know it, we just get surprisingly intuitive type interfaces.
Very true. As a downstream consumer, I can do all business logic in ancient, simple languages. But I'm sure these things are extremely nice to have for the more complicated upstream dependencies I rely on.
hinkley
3 months ago
When they made class declarations imply strict, I thought that was a pretty wise move. But it might have been good if they applied more limitations than that, made them super-strict.
Such as for instance making 'var' not work in class declarations.
afavour
3 months ago
ES modules too would have been a great opportunity to cut out some of the outdated cruft.
yakshaving_jgt
3 months ago
> Like, you can declare a variable with var, let or const but there's absolutely no reason to use var any more.
I am going to continue to use var for everything, because I think let and const are stupid.
It is not cool or interesting to learn about new scoping rules introduced by let, and it is not cool or interesting that so many people — especially juniors, but not exclusively — are lulled into a false sense of security by believing const means the referenced value is immutable, which it isn't.
I am going to continue to write small JavaScript, like from The Good Parts.
conartist6
3 months ago
"let" is one of the good parts. Just don't use const or var.
yakshaving_jgt
3 months ago
Why is it? Why is block scoping useful?
colejohnson66
3 months ago
Because it's how almost every C-syntax-like language works. JavaScript is the odd one out.
yakshaving_jgt
3 months ago
I’d prefer to just embrace it. Keep the language small. Prototypical inheritance works just fine. There’s enough in The Good Parts to get all the work done.
thot_experiment
3 months ago
> but there's absolutely no reason to use var any more
Naw, var has function scope and hoisting, both of which are useful.
hinkley
3 months ago
My job isn't to be infatuated with your code. It's to get through your code and get stories done.
People don't really get better at handling the complexity of large code bases. We are fundamentally the same organic matter that existed prior to the first computer coming into existence. So as code bases and library bases grow larger and larger, they need to be proportionately easier to read or even ignore.
Your code needs to be dead boring 90% of the time, otherwise you're imposing on your coworkers. And using variables before they're declared is just shitty behavior.
thot_experiment
3 months ago
Sure and I'd accept the weaker claim that "there's no reason to use var in a production codebase touched by many people"
yakshaving_jgt
3 months ago
> Your code needs to be dead boring 90% of the time
I also prefer boring code, but I think having the choice between var, let, and const is less boring than only having var.
hombre_fatal
3 months ago
You should probably accompany this kind of claim with a code snippet to show what we're missing out on.
afavour
3 months ago
Not in a sensible codebase
int_19h
3 months ago
Useful for what?
munificent
3 months ago
I've been meaning to write a longer essay on this for years, but I believe the reason for this observation is different cohorts.
Imagine you are a C# programmer just as C# 1.0 is released. C# is a fairly simple language at that time (and similar to other languages you already know), so you can get caught up on it fairly easily and quickly. A few years later, C# 2.0 comes out. It's got a handful of features, but not too much for you to absorb. Likewise C# 3.0, 4.0, etc. As long as you stay on the C# train, the rate of new features does not exceed the rate that you can learn them.
Years later, another person comes along and is new to C#, which is now at version 5.0. They are presented with a huge sprawling language and they have to learn nearly all of it at once to deal with codebases they are contributing to. It's a nightmare. They long for a language that's actually, you know simple.
So maybe they find some other newer language, Foo, which is at 1.0. It's small and they learn the whole thing. After a couple of years of happy productive use, they realize they would be a little more happy and productive if Foo had just one or two extra little features. They put in a request. The language team wants happy users so they are happy to oblige. The user is easily able to learn those new features. And maybe some other Foo users want other new things. 2.0 comes out, and they can keep up. They can stay on the train with 3.0, 4.0, etc.
They never explicitly asked for a complex language, but they have one and they're happy, because they've mastered the whole thing over a period of years. They've become part of the problem that bothered them so much years ago.
Fundamentally, the problem is that existing users experience a programming language as the delta between the latest version and the previous one. New users experience a programming language as the total sum of all of its features (perhaps minus features it has in common with other languages you already know). If you assume users can absorb information at a certain fixed rate, it means those two cohorts have very different needs and different experiences.
I don't think there's a silver bullet. The best you can hope for is that a language at 1.0 has as few bad ideas as possible. But no one seems to have perfect skill at that.
pjc50
3 months ago
Speaking as a long time C# developer (and before that, C and C++), every time I try to touch javascript I get that kind of allergic reaction - not because of the language features itself, but the ecosystem. In theory npm and nuget are the same kind of complexity; in practice, all the complexity of C# building disappears into Visual Studio.
A lot of people seem to think that the overall size and "complexity" of the language (and only the language) matters? Personally I don't think it matters how long the spec is if you and your team aren't using those features. The ecosystem matters more. "What should I use to write a GUI in C#?" is a complicated question with tradeoffs, but none of them have anything to do with the language per se.
Nothing is going to compete with C++'s template system for complexity, though.
nordsieck
3 months ago
> in practice, all the complexity of C# building disappears into Visual Studio
IMO, that's even worse.
It means that when you want to learn C#, you're also forced into learning a complicated tool that isn't really useful for much else.
At least when I'm learning Rust or Typescript, I can keep using my existing editor.
> A lot of people seem to think that the overall size and "complexity" of the language (and only the language) matters? Personally I don't think it matters how long the spec is if you and your team aren't using those features.
That works until you have to use code that does use those features.
> The ecosystem matters more. "What should I use to write a GUI in C#?" is a complicated question with tradeoffs, but none of them have anything to do with the language per se.
That's fair. At least to an extent.
The further you stray from the ecosystem's intended use cases, the more you have to depend on the quality of the language itself. Thankfully, for mature, mainstream languages like C#, there are a lot of things you can do before that point.
neonsunset
3 months ago
> in practice, all the complexity of C# building disappears into Visual Studio
> IMO, that's even worse.
To be fair, the more accurate way to phrase it is "disappears into .NET tooling". Because this part is also exposed through standard CLI of .NET, and isn't Visual Studio specific. Managing packages through npm and dotnet is quite similar, with a significant difference that the average dependency graph of a .NET application or a package is 10 to 100 times smaller than the one of Nodejs, and the compatibility breaks happen much, much more rarely.
> It means that when you want to learn C#, you're also forced into learning a complicated tool that isn't really useful for much else.
This is untrue. On top of Visual Studio, your choices are Rider, VS Code and VSCodium, Neovim and Emacs, and anything else that integrates through VSC extension bridges, LSP and debugger adapter protocols.
I also usually recommend to all newcomers to start with CLI to manage projects and packages, because it's more straightforward than navigating through all sorts of windows in an IDE, and because they also get know the basics .NET builds on top of. It's an experience that is very similar to using Cargo.
troad
3 months ago
This is spot on, well written, and perfectly reflective of my recent experience doing some recreational language hopping.
Incoherence through gradual accretion of complexity is the probably fate of most non-trivial systems, beyond just programming languages. Individual programs, certainly. Buildings too. (People?)
Also, I am a big fan of your books, Bob! Thank you! :)
johnfn
3 months ago
Something about OP didn't strike me quite right, but your explanation here really nails it, I think. Especially because I can see that I'm in quite an old JS cohort - and quite happy with the language as a result - but if I were to start coding in JS yesterday I think I would gnash my teeth and tear out my hair.
iainmerrick
3 months ago
This is quite a compelling story, but thinking about it, I don’t fully agree.
There’s more than one language that I initially disliked, and only learned to like after some of (what I saw as) the glaring flaws were fixed. After they added more features!
For one, Objective-C. I didn’t like it at all until they added ARC, removing the need for manual addRef / release everywhere. After that, coming to the language pretty late, I came to like Obj-C quite a lot.
JavaScript is another one. For a long time I thought it was an awful language and avoided using it, but a few things have brought me round and now I really like it:
- modules
- async/await
- TypeScript, if you’ll allow that as a “JavaScript feature”
I even quite like JS classes, although I could live without them.
Simplicity is good, but power and expressiveness are also good.
terandle
3 months ago
Been using .net since 2.0 and nah C# has jumped the shark. Primary constructors are a very poorly designed feature that for some reason was added in the last version.
The new-ish yearly release cycle I think is mostly to blame, they feel like they need to add some headline features every year but the team also, maybe due to org-chart politics, seems to not really able to make deep runtime level changes that are needed to actually add anything useful so they just add syntax sugar every year bloating the language.
kevingadd
3 months ago
The emphasis on syntax sugar has a very useful side effect, which is that new language features can be used on old runtimes. To this day some of the newer C# features are usable when targeting the ancient .NET Framework 4.x, like 'ref returns'. This would not be possible if every new language feature was paired with runtime-level changes. (Many new language features do come with changes to the runtime and BCL). I support a bunch of people who use NET4x to this day and I'm able to write modern C# for that target thanks to the language and compiler being designed this way.
A lot of stuff is also designed to be independent of library changes - IIRC for example if you use nullability, the compiler will emit the Nullable attribute's definition into your .dll as a hidden class, so that your library will work even on older versions of the runtime with older base class libraries. Doing this complicates the compiler (and adds a tiny, tiny amount of bloat to your dll) but means that more people can adopt a new feature without having to think about upgrading their SDK or runtime.
My personal opinion is that if a change can be done adequately entirely at the compiler level without runtime/library changes, it should be done there. It allows the people working on the language, libraries and runtime to iterate independently and fix problems without having to coordinate across 3 teams.
wvenable
3 months ago
> Primary constructors are a very poorly designed feature that for some reason was added in the last version.
I upgraded to .NET 8 recently and I love primary constructors. I don't use them everywhere but they are great for dependency injection or for small classes.
terandle
3 months ago
Beware the footguns!
https://mareks-082.medium.com/dark-side-of-the-primary-const...
Let's just say they could have done a much better job on it. It feels rushed and haphazard for such a mature language.
wvenable
3 months ago
It doesn't seem that bad -- the lack of readonly would be my only concern out of that article and one I didn't actually consider.
I think, as a feature, this is sort of the MVP. They could have done a better job of it by adding more to it (e.g. maybe allow the readonly modifier on the constructor properties). It's hard to imagine them being able to take anything away from primary constructors that would make it better.
mdhb
3 months ago
Just as a quick side note this is actually one of the things I’ve come to appreciate most about some of the work you and the others have done with Dart where it very clearly has gotten much more powerful and has had to deal with some major changes in requirements over the years as well but on the whole I feel with only a few exceptions the complexity doesn’t feel like it’s gotten away from me or the community at large at all. It’s very obvious to just look at it and see that a tremendous amount of work has gone into the language design itself and just figured now would be a good time to offer my appreciation for that.
munificent
3 months ago
Thank you!
We try really hard. I'm always worried about pouring too much complexity in and alienating new users. At the same time, we also want to serve existing users who really do benefit from new features. It's a tricky balancing act.
spease
3 months ago
I can't speak for how C#; but in C++'s case, the issue is that there's a lot of programmers who don't keep up with the language that they're using. As a result, you get a few people pushing the language ahead, who are deeply involved in its future. And then the vast majority of people are still using C++03, and it's still taught the same way as it was ~20 years ago.
I think the only way to address what you're alluding to is to continually deprecate small parts of the language, so that upgrading is manageable for active codebases. And you probably have to be really aggressive about pushing this forward, because there will always be excuses about why you should hold back just this one time and this one feature is an exception that needs to be held back just a little bit longer.
But in the long run, if you don't force people to change a little bit continuously, it will become a big enough issue to split the ecosystem. See python2 to python3. Or you end up forced into supporting bad practices for all eternity, like C++. And having to take them into account for every. Single. New. Feature.
Further raising the barrier to entry to participation in developing the language to people who are completely focused on its development and have unusual mastery of it, who can't identify with the people struggling with its complexity.
If not at the technical level, then at the business level, where people definitely don't have the time to understand why it'd be safer for the go-to heap allocation method should return a scoped pointer instead of a raw pointer.
Unfortunately, this probably is only viable for strongly-typed languages like C#; for loosely-typed languages like Python, the risk of iterative changes is that if someone moves a codebase several generations ahead at once, it'll introduce lots of subtle changes that'll only become obvious once certain codepaths are exercised...and given how bad testing coverage is for a lot of software, that probably risks breakages only occurring once it's deployed, that are nontrivial to discern via reviews or even static analysis.
pjc50
3 months ago
> continually deprecate small parts of the language
Did you see https://news.ycombinator.com/item?id=41788026 ?
"My concern, and IMO what should be the overwhelming concern of the maintainers, is not the code that is being written, or the code that will be written, but all the code that has been written, and will never be touched again. A break like this will force lots of python users to avoid upgrading to 3.17, jettison packages they may want to keep using, or deal with the hassle of patching unmaintained dependencies on their own.
For those Python users for whom writing python is the core of their work that might be fine. For all the other users for whom python is an foreign, incidental, but indispensable part of their work (scientists, analysts, ...) the choice is untenable. While python can and should strive to be a more 'serious', 'professional' language, it _must_ have respect and empathy for the latter camp. Elevating something that should be a linter rule to a language change ain't that."
Strongly phrased, but planned obsolescence in a language is really expensive. You're basically quietly rotting the work of your users, and they will hate you for it.
I note that C# basically hasn't deprecated any of the language itself, the dotnet core transition was a big change to the runtime. And that was expensive enough, again due to dropping a lot of old libraries.
sensanaty
3 months ago
But they can simply continue using whatever version of Python works for them, right?
I never got this argument, personally. Sure, having to rip out a bunch of code because of lang-level changes can suck, but you also only really need to do that if you're starting a new project anyway or for whatever reason want to keep being pinned to @latest version of the lang.
If you're a researcher who uses Python 2 as a means to an end, then just stick to Py2. It's unreasonable to expect the entire python world to freeze in place so you don't have an annoying migration journey. If you need the latest Py3 features, them's just the brakes I'm afraid, eventually APIs need to change.
spease
3 months ago
No, because features get added to new versions of Python, and libraries they need to use may depend on those features. “Just don’t upgrade Python” is advice that’s only going to last a finite amount of time before introducing pain points and/or risk.
pjmlp
3 months ago
Not keeping up with the language is quite common in traditional enterprises, that is why you get shops still doing Python 2, Java 8, .NET Framework (C# 7.x), C89, C++98,....
People get paid to keep running what already exists, not to write new stuff.
Usually new stuff only comes to be if there is a new product being added into the portfolio, and most of the time it comes via an aquisition or external contractors, not new development from scratch in a cooler version of the stuff they are using.
lolinder
3 months ago
> When Typescript first came out, it was great. Types in Javascript are something we've always wanted. Now, Typescript is on version 5.6 and there is so much stuff you can do with it that it's overwhelming. And nobody uses most of it!
TypeScript today can be written the same way that TypeScript was when it first started to become popular. Yes there are additions all the time, but most of them are, as you observe, irrelevant to you. They're there to make it possible to type patterns that would otherwise be untypeable. That matters for library developers, not so much for application developers.
To the extent there's a barrier to entry, it seems largely one that can be solved with decent tutorials pointing to the simple parts that you're expected to use in your applications (and a culture of not overcomplicating things in application code).
tgv
3 months ago
TS is pretty good. In the beginning, I had to resort to 'any' frequently, but nowadays it's often possible to avoid that by writing some auxiliary types. It's not easy, but you can get quite far. JS without TS' safety net is a nightmare...
d13
3 months ago
As a very experienced TS developer myself - this is absolutely correct, the best reply in this thread, and I hope the OP reads it.
wvenable
3 months ago
> The first time I ever used C# was probably version 5? Maybe? We're on version 12 now and there's so much stuff in there that sometimes modern C# code from experts looks unreadable to me.
That's funny given many of the changes were made to make C# look more like JavaScript!
C# 6 introduced expression-bodied members for simplified syntax (like JavaScript), null-conditional operators, and string interpolation. C# 7 brought pattern matching, tuples, deconstruction, and local functions. C# 8 introduced nullable reference types for better null safety, async streams, and a more concise switch expression syntax. C# 9 to C# 12 added records, init-only properties, with expressions, and raw string literals, global using directives, top-level statements, list patterns, and primary constructors.
In C#, if you need a string list you can do:
List<string> items = []; // Not as concise as JS but type safe.
As for TypeScript, nobody is supposed to use most of it -- unless you're authoring a library. You benefit from it's features because somebody else is using them.Languages draw inspiration from each other -- taking the good parts and incorporating them in. C# is a vastly better, easier, and safer language than it used to be and so is JavaScript.
eddd-ddde
3 months ago
This is why always say the true beginner programming language is C.
Stupid easy to learn, have some loops, have some conditions, make some memory allocations. You will learn about the fundamentals of computing as well, which you might as well ignore (unknowingly) if you start with something like JavaScript (where is this data living in my computer?).
lukan
3 months ago
And this is why I always say, we have a world full of computer consumers, not programmers.
C as a first language is only easy, if you happen to bring along a deep technical interest (and pre knowledge) about the "technical fundamentals of computing".
Most people do not have that.
Tell them about heap and memory allocations and you will get a blank stare.
But show them some simple functions, to make some flashing graphics on the sceen - and they will have fun. And can learn the basics of programming at the same time.
And then you can advance more low level, for those who feel the call. But please don't start with it, unless you have some geeky hacker kids in front of you who really want to learn computers. Then C makes sense. For "normal" people not so much.
randomdata
3 months ago
Excel is the best first language if you just want a world full of computer programmers.
But there is an implicit context here around those who want to program alongside the professionals. That comes with wanting some deeper understanding of the machine.
jerf
3 months ago
I'm not saying this because I like Go per se, though one might argue I like Go because I can say this, but "Go, but stay away from all concurrency for a while" is becoming my go-to recommendation for new programmers. Fewer foot guns, it's close enough to the metal you can learn about it (there's even an assembler you can play with if you want to), and despite being 15 years old is essentially not the result of 15 years of language-construct-astronautics. It also lacks a lot of the accidental complexity of C in the compilers, using new modules is "go get" rather than essentially learning a new sublanguage, a lot of advantages.
But do stay away from the concurrency. I occasionally get flack on that point, but try to remember back to your programming days when you were having enough trouble keeping track of how one instruction pointer was flowing; it doesn't help to immediately try to keep track of multiple. Gotta recover the novice mindset for a moment when recommending programming langauges.
I used to recommend Python, as many others did. Your cited disadvantages of such languages are certainly true, but Python used to make up for it with the ability to do real work relatively quickly, and while it may not have taught you how the machine worked, it did a good job of teaching programming. But now... well... Python was my primary hobby language for about 8 years around 2000-2008. I'm fluent in Python. I wrote metaclasses. I wrote a bit of a C module. And I can still read it, because I do check in from time to time. But it's not the same language anymore, and almost every change it has made has made it harder to recommend as a new language. It used to be the simple alternative to Perl that still had most of the power... now I think it's harder to read than a lot of Perl 5, what with all the constructs and the rules about what happens and the difficulty of resolving what a given line is going to do with all the ways of overloading and decorating and overriding everything. And the culture of having all this power, but using it selectively, is gone from what I can see; now it's "we have all this power and what a shame it would be not to use it".
hombre_fatal
3 months ago
The problem with C is that beginners generally want to build something.
"Oh, you want to build an app that does X? Well, first learn C for three months and then switch to Python/Javascript/etc. to build the thing that motivated you in the first place" doesn't fly.
GordonS
3 months ago
Aye, especially nowadays with the ubiquity of computing - "hello world", or console apps in general, aren't the most enticing of projects anymore.
n_plus_1_acc
3 months ago
How can you teach C when there's no list of UB, there's sometimes no agreement on how to read the standard, and loads of non-standard-compliant compilers.
bobthepanda
3 months ago
Plenty of universities teach C every day even if that means specifying a compiler, and usually it’s a very boring compiler that gets chosen
n_plus_1_acc
3 months ago
Right, but all C courses I've done had UB in examples without mebtioning it. There teachers just didn't know what they are teaching.
bobthepanda
3 months ago
Unless you are writing a compiler and code specifically tailored to take advantage of UB, there’s not much to say about it other than “be careful about UB cause it can make your program buggy from your POV.”
lelanthran
3 months ago
> How can you teach C when there's no list of UB, there's sometimes no agreement on how to read the standard, and loads of non-standard-compliant compilers.
Right. Becuase no one ever learned C as a first language ever, and those that paradoxically did were worse programmers for it!
n_plus_1_acc
3 months ago
Are you saying people who learned C as their first programming language are better programmers or worse?
lelanthran
3 months ago
> Are you saying people who learned C as their first programming language are better programmers or worse?
That's both a false dichotomy and irrelevant as well.
My message is "There are multiple excellent (even legendary) developers in the short history of our field that learned programming in C. There are many more who primarily used C".
This refutes your point completely.
int_19h
3 months ago
From that perspective, something like Pascal or Modula-2 is much better - you get all the same stuff but no footguns.
throw49sjwo1
3 months ago
> And nobody uses most of it!
Everybody who does Express, React, or any other popular advanced libraries with TypeScript is using these features. Some things are simply more useful to libraries than line of business code - that's fine. The line of business code is much better thanks to it.
leetharris
3 months ago
> Everybody who does Express, React, or any other popular advanced libraries with TypeScript is using these features.
This is very true and my original post was short sighted. You could, of course, make most upstream dependencies without modern language features. However, their complex jobs get much easier with these features.
Downstream, business logic is much easier to implement without these features compared to complex, low level functionality.
anon7000
3 months ago
For sure! In a basic API endpoint, I don’t need advanced typescript features.
But if I’m writing a module that a lot of other consumers in the codebase will use, and I want to make their lives easy, I might use a lot of advanced TS features to make sure than type safety & inference works perfectly within the module. Whoever consumes it can then rely on that safety, but also the convenience. The module could have some convoluted types just to provide really clean and correct auto-complete in a certain method. But most people don’t need to worry about how that works
user
3 months ago
nosefurhairdo
3 months ago
Yeah I was confused by this point as well. Especially because many of the recent Typescript releases are just improving performance or handling more cases (without needing to learn new syntax).
tannhaeuser
3 months ago
React and Expressjs predate typescript, Expressjs considerably so.
MathMonkeyMan
3 months ago
What did Bjarne Stroustrup supposedly say? There are two kinds of programming languages: the ones everybody complains about, and the ones nobody uses.
I'll put on my Scheme hat and say "with hygienic macros, people can add whichever language features they want." Maybe Rust is a good experiment along those lines: C++ with hygienic macros.
Everything that people keep using grows into a monster of complexity: programming languages, software, operating systems, law. You must maintain backward compatibility, and the urge to add a new feature is too great. There's a cost with moving to the new thing -- let's just put the new thing in the old thing.
Shiny_Gyrodos
3 months ago
I'm an absolute beginner when it comes to programming, and I chose C# as my first language to learn.
I've been learning steadily for 8 or so months now and at no point have I felt the language was unapproachable due to excessive features.
Looking back on what each new version added, I don't think any of the additions were damaging to the simplicity of C#.
I do likely have a biased perspective though, as I use newer C# features every day.
ygra
3 months ago
> I do likely have a biased perspective though, as I use newer C# features every day
I think that is kind of the point, though. Many of those newer features help with simplifying code and making it less boilerplate-y. To old programmers it is a simple code fix in the IDE to move from 30 lines of variable assignments in a switch to a 5 lines switch expression and they can learn that way. People new to the language typically won't even consider going the complicated route because they learned an easier way first.
I do concede that having people with less C# experience on a team where modern C# is used, there will be constructs that are not immediately obvious. SharpLab has an “Explain” mode which would be helpful in such cases, but I haven't seen anything like that in IDEs: https://sharplab.io/#v2:C4LgpgHgDgNghgSwHYBoAmIDUAfAAgBgAJcB...
However, as a personal anecdote, we've had a number of developers who have written mostly Java 1.4 (technical reasons) before switching to C# about a year ago. They took up the newer features and syntax almost without problems. Most questions I got from them were along the lines of “Can we also use this feature?” and not “What does this do?”.
lelandfe
3 months ago
It doesn't help how arcane the TS documentation is. Important docs live as frozen-in-amber changelog entries; huge tracts of pages "deprecated" yet still #1 on Google.
Google "typescript interfaces." #1 is a page that has been deprecated for years. How did this happen?
hsbauauvhabzb
3 months ago
AWS has that issue too - v1 documentation takes precedence over v2, the same with bootstrap, too. I suspect google algorithms don’t quite understand deprecation / latest version prioritisation.
imbnwa
3 months ago
Can tell you right now a lot of important information about mapped types live in Github issues on the TS repo
vundercind
3 months ago
Documentation where, somehow, every single thing you can find for some particular need is “deprecated” and it’s weirdly-difficult to find a complete set of docs not full of deprecated landmines mixed in with the current stuff, is kinda a Microsoftism.
egnehots
3 months ago
Try Go. Go is really stable as a language and have a very small core feature set.
leetharris
3 months ago
This is easily the most appealing thing to me about Go. I learned Go through the "Learn Go with Tests" way and I had a ton of fun.
It is hard for me to recommend using Go internally since .NET/Java are just as performant and have such a mature ecosystem, but I crave simplicity in the core libraries.
Here's the link for anyone considering learning Go: https://quii.gitbook.io/learn-go-with-tests
claytongulick
3 months ago
I would be a huge fan of go, but json is just too big a hassle to deal with in go compared to JavaScript.
madeofpalk
3 months ago
Go is an excellent language for people who turned off C# or Typescript, for better or worse.
adamc
3 months ago
Java went through this too, although there, a lot of it is part of the ecosystem. See https://chrisdone.com/posts/tamagotchi-tooling/
intothemild
3 months ago
The java tooling is the number one thing I hate about using the language. It's all just bad.
Then. You get forced into using intelij because it seems to smooth over a lot of the toolings problems with "magic".
It's horrible.
bakkoting
3 months ago
> instead of exclusively focusing on making them easier to use or more performant, they are constantly adding features
I appreciate that this is mostly just a generic rant, but it's not really suitable here, because this is a feature which is being added with the sole goal of improved performance.
There's only so much you can to optimize the extremely dynamic regular objects in JS, and there's no hope of using them for shared-memory multithreading. The purpose of this proposal is to have a less dynamic kind of object which can be made more performant and which can be made suitable for shared-memory multithreading.
dgellow
3 months ago
Do you have examples of unreadable C#? The language didn’t change much IMHO. You have new features, like records, but C# code looks pretty much like what I started with in 2009
leetharris
3 months ago
Now that I'm thinking about it, most of it is probably .NET bloat instead of C# bloat, but a few examples would be global usings, file scoped namespaces, records, target-typed new expressions, null coalesce assignments, etc. It's nothing huge, but combined with .NET bloat it can be overwhelming when you haven't worked in .NET for a while.
francisofascii
3 months ago
This one threw me off when I first saw it:
(int x, string y) = (default, default);
rezonant
3 months ago
> One of the reasons I have so much fun working in node/Javascript these days is because it is simple and not much has changed in express/node/etc for a long time. If I need an iterable that I can simply move through, I just do `let items = [];`. It is so easy and hasn't changed for so many years. I worry that we eventually come out with a dozen ways to do an array and modern code becomes much more challenging to read.
The let keyword didn't exist in JS when Node was first released, nor did for/of, which while unstated in your post, is probably what you are thinking of when you posted this. The language has not stayed the same, at all.
carlmr
3 months ago
>The first time I ever used C# was probably version 5? Maybe? We're on version 12 now and there's so much stuff in there that sometimes modern C# code from experts looks unreadable to me.
The funny thing is if you used F# over a decade ago almost all the C# improvements seem familiar. They were lifted from F#, some of them badly.
And I know F# borrows a lot from OCaml. But it's hard to fathom why we need to use the badly adopted F# features in C# instead of just getting F# as a main Microsoft adopted language.
neonsunset
3 months ago
> sometimes modern C# code from experts looks unreadable to me
This is a culture issue and has always existed in C#, Java and C++ communities sadly (and I'm seeing this now with TS just as much, some Go examples are not beacons of readability either, I assume other languages suffer from this similarly).
In the past, people abused BinaryFormatter, XML-based DSLs, occasionally dynamic, Java-style factories of factories of factories, abuse of AOP, etc. Nowadays, this is supplanted by completely misplaced use of DDD, Mediatr, occasional AutoMapper use (oh god, at least use Mapperly or Mapster) and continuous spam of 3 projects and 57 file-sized back-ends for something that can be written under ~300 LOC split into two files using minimal API, records and pattern matching (with EF Core even!).
Neither is an example of good code, and the slow but steady realization that simplicity is the key makes me hopeful, but the slow pace of this, and new ways to make the job of a developer and a computer more difficult that are sometimes introduced by community and libraries surrounding .NET by MS themselves sour the impression.
breadwinner
3 months ago
Couldn't agree more. More features in a programming language makes it easier and more fun to write code, but makes it harder to read and maintain someone else's code. Considering more time is spent maintaining code as opposed to writing it (assuming the product is successful), readability is more important than writability.
azangru
3 months ago
> it has a huge barrier to entry
You don't have to use every feature of the language. Especially not when you are just learning.
> Now, Typescript is on version 5.6 and there is so much stuff you can do with it that it's overwhelming. And nobody uses most of it!
Exactly. But no-one seems to be arguing that typescript has a huge barrier to entry.
paulddraper
3 months ago
> Now look at modern C++, it's crazy powerful but so jam packed that many people have just gone back to C.
Geez I'd sure hope not.
If you liked C++11, you can use C++11. Every compiler, platform, and library will support it.
No one erased it and made you go back to C99.
Waterluvian
3 months ago
I also don’t know how to refine my thought but it’s something along the lines of:
The people who are in a position to decide what features get added to a language are usually top experts and are unlikely to have any reasonable perspective on how complicated is too complicated for the rest of us.
If you live and breathe a language, just one more feature can seem like a small deal.
I think it becomes much more reasonable when that one more feature enables an entire set of capabilities and isn’t just something a library or an existing feature could cover.
int_19h
3 months ago
For many languages these days, evolution happens in public, and you can look at those discussions and see how this sausage is made. If you do it for C#, if anything, the pattern is that relatively inexperienced users are the ones who propose features (to make some specific pet peeve of theirs easier), while the more experienced folk and especially the language designers who make the final call aggressively push back, point out corner cases, backwards compatibility, maintenance burden etc.
branko_d
3 months ago
And here is the obligatory quote from Bjarne Stroustrup:
"There are only two kinds of languages: the ones people complain about and the ones nobody uses."
user
3 months ago
carlosrg
3 months ago
Every programming language attempts to expand until it becomes C++. Those languages which cannot so expand are replaced by ones which can.
goatlover
3 months ago
Go will resist this as long as possible.
drclau
3 months ago
> Microsoft has a large team dedicated towards improving these languages constantly
… and the people working on these projects need to deliver, else their performance review won’t be good, and their financial rewards (merit increase, bonus, refresher) will be low. And here we are.
Edit: I realize I’m repeating what you said too, but I wanted to make it more clear what’s going on.
neonsunset
3 months ago
From what I've been told, all the nice bonuses and career opportunities are in Azure and other, more business-centric areas. You go to DevDiv to work on Roslyn (C#) or .NET itself because you can do so and care about either or both first and foremost.
dartos
3 months ago
At least typescript tooling hasn’t changed. It was a pain to set up when it came out and it still is.
At least we moved past webpack mostly.
pier25
3 months ago
> or more performant
Obviously then can't make TS more performant (since it doesn't execute) but C# is very performant and even surpasses Go in the TechEmpower benchmarks.
leetharris
3 months ago
Absolutely. I love C# and .NET, they are incredible and very fast. I just meant to say that they aren't only focused on performance, but also focused on new features.
One of the best things .NET did was adding minimal APIs in .NET 6 (I think) that are more like Express. They removed a lot of boilerplate and unnecessary stuff, making it easier to start building an API.
o11c
3 months ago
TS is pretty impressive in that its compiler is slower than C++ compilers though.
devjab
3 months ago
I think part of the reason C# has changed so much as far as the language goes, not the CLR is actually because they took so many good things from Typescript and mixed them into the language. I think part of the reason Typescript has become so cumbersome to work with is because it has similarly added a lot of the good things from C#. Which may sound like a contradiction, but I actually agree with you that plain JavaScript is often great. That being said, you don’t actually have to use all the features of Typescript and it’s still much better for larger project in my opinion. Mostly because it protects developers from ourselves in a less “config on organisational level” way.
We already use regular JS for some of our internal libraries, because keeping up with how TS transpires things into JS is just too annoying. Don’t get me wrong, it gets it right 98% of the time, but because it’s not every time we have to check. The disadvantage is that we actually need/want some form of types. We get them via JSDoc which can frankly do almost everything Typescript does for us, but with much poorer IDE support (for the most part). Also more cumbersome than simply having something like structs.
sureglymop
3 months ago
I recently tried out a very simple language called Gleam. It's a functional programming language running on the BEAM vm, it may appeal to you.
Nuzzerino
3 months ago
C# since version 2 here, so I’m probably older. You said a lot of words, but gave no concrete examples of what’s bad about these languages. Linters will let you turn off different syntax usages based on your preference on what is readable or not, and C# is the only language I’m aware of where you can build them into the compilation chain and literally cause the compilation to halt instead of merely giving a style warning.
root_axis
3 months ago
You don't have to use features you don't understand. "Complex" features exist for a reason. To the uninitiated something like generic types are quite inscrutable, but when you encounter the type of problem that they solve, their use becomes much more intuitive, and eventually familiarity yields an understanding and generics reveal themselves to be quite conceptually simple, they're just variables for types.
edem
3 months ago
just use haxe
pjmlp
3 months ago
C23 has just been ratified, and C2y has already quite a few proposals.
Programming languages are like any other software product, evolution or stagnation.
Eventually they might implode, however whatever comes after will follow the same cycle yet again.
seanw444
3 months ago
And branches [1] of C are still spawning and gaining traction, because C++ is perceived as overkill.