It's a tough call between C# and Dart. But I think C# has the edge.
The good
Boring and predictable
Great support from Microsoft, with new language features on a regular basis
Concise, expressive syntax
LINQ (the built-in functional-style collection extension library) has everything you could ever want and makes you feel like a genius
First-party support for web APIs, no third-party framework required
Very fast for such a high-level language
The bad
Only portable in theory. In practicality you're locked into the Microsoft stack by convenience and defaults: .NET Framework, Visual Studio, SQL Server, Azure, Windows. Again, you can break out of this, but you'll be carving your own path through the forest.
Hot reloading is also purely theoretical. Most of the time it's a stop-and-recompile development cycle.
The configuration for .NET Framework apps is XML-based and it's a bit of a black box because the documentation is very spotty and frequently out of date. Messing around with config files is always a bad time. Contrast with Node.js, where everything is JavaScript and if something is configured a certain way, it's because you coded it that way. The difference is night and day.
Autoformatting/pretty-printing isn't a first-class feature and I haven't ever gotten it to work as well as Prettier works on the front end.
Occasionally you get fatal errors with no debugging information other than a hex dump (no, not even a stacktrace), and figuring them out can take days. I've never seen errors this opaque in any other runtime.
Visual Studio is much better than any other IDE for writing C#, but it's slow as hell even on a top-of-the-line development machine.
He/Him; Senior Software Developer, IT Swiss-army-knife.
Lots of coding, some hardware, some devops & sysops, some micro-controller electronics.
I used Arch BTW :)
I don't know if I have a favourite programming language... For sure I have ones I use more often than others and some that are my go-to for specific project types or even just the hacky-get-something-processed-quick-and-throw-away-to-the-misc-folder projects.
That being said... I will pick the top one I do the most work in these days: The Dread-Language: JavaScript!
Good Bits (not the book)
It's the closest thing to a Run-Anywhere language I think we have now... Browsers, Servers, Apps, Phones, In-Line processing... it is in so many places.
It's a living language. JS & ECMA Script is actively getting new features, standards and generally keeping up.
Low barrier to entry. (nearly) Everyone has a runtime in the form a browser on their system to get started learning the basics.
High ceiling of capability: People and Orgs are doing a TON of stuff with JS. Major platforms utilize it to great effect as well as utilities and smaller apps & tools.
Large Community to support and contribute knowledge and libraries.
Execution sandbox should result in a higher level of safety than most compiled languages.
Duck-Typing helps to make a very flexible language where some very neat things can happen.
Not to very good parts
Some legacy parts of the language are just not correct for a modern language. I won't link to the details as I'm sure there are innumerable listicles identifying the peculiarities of JS.
Competing engine and execution implementations may not be compatible enough depending on what you're trying to do.
Strongly tied to consumer-hostile vendors such as Apple and Google who influence their browser's implementation. As behemoths in the market, they are like the tail that wages the dog. This may lead to wider splintering of capacities and features.
Speed... as an interpreted language (or JIT compiled in modern engines) it is not quite as close to the metal as a fully compiled language wold be, and thus imparting a speed penalty.
Confusion around core concepts like the this reference, how var differs from let not only in allowing redefinition, but in hoisting behaviour.
node_modules potential for explosive size on even medium projects. (not really a problem of the language but of that the mechanics of that specific ecosystem)
The type system plays at being duck-typed, but... there are, as always, some weird exceptions. Mostly these exist under the hood in the various engines and could end up with some hidden effects in the form of speed penalties or possibly even unexpected results.
Seen as a bad language, no matter what fixes will be enacted.
Often I jump to JS to do some quick processing of lists or data or try out an algorithm, or some meta-programming task.
Is it a favourite? Not really, there are a ton of flaws and reasons to choose something else. But it is handy, its there and it's good enough for most of the stuff I use it for.
Backwards compatibility has got to be the best and worst thing about JavaScript (and the web in general). On the one hand, if your website worked in 2008, it will probably always work, with minor exceptions for non-core technologies like Flash and ActiveX. On the other hand, our grandkids will probably still be seeing "use strict"; and wondering why NaN !== NaN.
When you spend time working with any other platform, you come to appreciate "don't break the web." But then you come back to JavaScript and start to wish we could break just one or two old websites by getting rid of things like "null and undefined both exist and don't mean the same thing" or "0 is falsy, so you can't null-guard a number using !".
Borrow checker that ensures you won't shoot yourself in the leg like you can with C and C++.
Powerful type system which is much more powerful than what other static typed programming languages can offer (except few exceptions like Haskell). I would quote No Boilerplate's amazing explanation on this - It's not C++, but better. It's Haskell standing on LISP's shoulders, hiding in C's coat to sneak into production.
Everything is immutable by default.
There is no null.
There are no exceptions - every function that can fail returns Result<T, E> and ? operator allows you to easily propagate errors (so you get best of the both worlds). Edit: there is a panic! which is similar to exceptions in it's behavior but it's used for non-recoverable errors only (see my comment below)
Hands down the best official documentation I've ever seen - the book, rustlings (small interactive exercises allowing you to learn how to write idiomatic Rust) and the reference is everything you need to become proficient pretty quick.
rust-analyzer is pretty great and gives you the experience of an IDE in VS Code and other code editors.
The bad
Compile time. Because of the various checks that need to be done, every crate (library in the Rust world) needs to be compiled.
Because of the borrow checker, it's much harder to do some things which are quite easy in other languages (recursive data structures are one of the most notorious examples).
Because of the guarantees borrow checker gives us, asynchronous programming in Rust is much more complicated than in other languages.
It can become very verbose very fast. Check this example which shows how to set up tracing in an Axum web app.
I'm a bit of a Rust newbie, but some of the "good" things seem like semantics. Maybe you can correct my thinking here?
There are no exceptions
The compiler throws a ton of exceptions, Rust is famous for it. And there's panic!, which in my experience is more common than advertised.
There is no null
But there is None, which doesn't seem that different to me. Is there a difference in the way you handle a nullable value in another language (say int?) and the way you handle optional values in Rust (like Option<isize>)?
I agree with your other points. Rust is my favorite language for performance-sensitive scripts, and I'm always happy to see things being rewritten in it.
What I wanted to say is that there are no exceptions in the same sense there are in other languages (like Java, C++ or C# for example). panic! exists but is used for non-recoverable errors (and while technically it is possible to catch a panic with catch_unwind it's not guaranteed you'll be able to do it). Basically, try / catch mechanism has been replaced by introducing error handling by Result.
Returning Result allows you to have information about functions that could fail ingrained into the type system, forcing you to act on it. But I understand that this could lead to confusion for beginners so I'll edit my comment.
None and null are not the same thing. Option<T> type is in fact an enum which could only be Some<T> or None, therefore everything that could be done with other enums could be done with Option<T> - you can match on it and there are several built-in functions like and_then or unwrap_or for more granular control.
null on the other hand basically means null pointer or a pointer that does not point to any valid object. While modern languages like Kotlin do introduce optional types, they won't prevent you from having uninitialized variables, because you need to use String? instead of String to ensure you don't end up having null. In Rust, this is prevented by ensuring every variable must be initialized before it's used. Whether you have an Optional<i32> or i32, you need to initialize it first.
So, while they may seem as the same thing, null and None are not the same.
Keep in mind that things I wrote are focused on the safe Rust. Unsafe Rust, on the other hand, is a different beast and topic for itself; there is for example std::men::MaybeUninit for wrapping possibly uninitialized instances.
Depends on your perspective. It helped with giving Go a huge community (pro), but there are plenty of people trying to "DeGoogle", which means for them, it's a con.
Software engineer, lifelong learner, language enthusiast & avid reader — Get my free 7-day email course to refactor your coding career: bit.ly/csarag-lessons
Location
Colombia 🇨🇴 (not Columbia)
Work
Content, Courses & Training for .NET teams — Helping teams to write maintainable & performant code
A young man who decided to choose a career as a software engineer from previously social media content, digital marketing, video editor, and product owner.
It's a tough call between C# and Dart. But I think C# has the edge.
The good
The bad
I'll start with Ruby
The Good Parts
The Bad Parts
I don't know if I have a favourite programming language... For sure I have ones I use more often than others and some that are my go-to for specific project types or even just the hacky-get-something-processed-quick-and-throw-away-to-the-misc-folder projects.
That being said... I will pick the top one I do the most work in these days: The Dread-Language: JavaScript!
Good Bits (not the book)
Not to very good parts
this
reference, howvar
differs fromlet
not only in allowing redefinition, but in hoisting behaviour.Often I jump to JS to do some quick processing of lists or data or try out an algorithm, or some meta-programming task.
Is it a favourite? Not really, there are a ton of flaws and reasons to choose something else. But it is handy, its there and it's good enough for most of the stuff I use it for.
Great summary.
Backwards compatibility has got to be the best and worst thing about JavaScript (and the web in general). On the one hand, if your website worked in 2008, it will probably always work, with minor exceptions for non-core technologies like Flash and ActiveX. On the other hand, our grandkids will probably still be seeing
"use strict";
and wondering whyNaN !== NaN
.When you spend time working with any other platform, you come to appreciate "don't break the web." But then you come back to JavaScript and start to wish we could break just one or two old websites by getting rid of things like "null and undefined both exist and don't mean the same thing" or "0 is falsy, so you can't null-guard a number using
!
".Rust
The good
null
.Result<T, E>
and?
operator allows you to easily propagate errors (so you get best of the both worlds). Edit: there is apanic!
which is similar to exceptions in it's behavior but it's used for non-recoverable errors only (see my comment below)The bad
I'm a bit of a Rust newbie, but some of the "good" things seem like semantics. Maybe you can correct my thinking here?
The compiler throws a ton of exceptions, Rust is famous for it. And there's
panic!
, which in my experience is more common than advertised.But there is
None
, which doesn't seem that different to me. Is there a difference in the way you handle a nullable value in another language (sayint?
) and the way you handle optional values in Rust (likeOption<isize>
)?I agree with your other points. Rust is my favorite language for performance-sensitive scripts, and I'm always happy to see things being rewritten in it.
What I wanted to say is that there are no exceptions in the same sense there are in other languages (like Java, C++ or C# for example).
panic!
exists but is used for non-recoverable errors (and while technically it is possible to catch a panic with catch_unwind it's not guaranteed you'll be able to do it). Basically, try / catch mechanism has been replaced by introducing error handling byResult
.Returning
Result
allows you to have information about functions that could fail ingrained into the type system, forcing you to act on it. But I understand that this could lead to confusion for beginners so I'll edit my comment.None
andnull
are not the same thing.Option<T>
type is in fact an enum which could only beSome<T>
orNone
, therefore everything that could be done with other enums could be done withOption<T>
- you can match on it and there are several built-in functions likeand_then
orunwrap_or
for more granular control.null
on the other hand basically means null pointer or a pointer that does not point to any valid object. While modern languages like Kotlin do introduce optional types, they won't prevent you from having uninitialized variables, because you need to useString?
instead ofString
to ensure you don't end up havingnull
. In Rust, this is prevented by ensuring every variable must be initialized before it's used. Whether you have anOptional<i32>
ori32
, you need to initialize it first.So, while they may seem as the same thing,
null
andNone
are not the same.Keep in mind that things I wrote are focused on the safe Rust. Unsafe Rust, on the other hand, is a different beast and topic for itself; there is for example
std::men::MaybeUninit
for wrapping possibly uninitialized instances.Go
The Good
go fmt
orgofmt
)The bad
why backed by Google are both Good & bad?
Depends on your perspective. It helped with giving Go a huge community (pro), but there are plenty of people trying to "DeGoogle", which means for them, it's a con.
You Know, google has many failed or forgotten projects.
I wrote this about Java. I think a lot of people write bad stuff about Java so it's important to highlight some of the good stuff.
C#
Good parts: LINQ and async support. Love it
Bad parts: Many alternatives for the same task :/ For example,
Worst thing: there are not many jobs for juniors. The language: Elixir.
Microsoft Stack (VB.NET, C#)
Pro:
Cons:
Of course it's javascript, what else could it be?
PROS
CONS