After years, and many languages, I still have to say Ada. Kotlin, Rust, Julia, and Nim are my current contenders to overtake, but here's what Ada does well enough to still be my preferred tool when appropriate:
strictness: typically my code works the first time it successfully compiles with few or no bugs. Rust is almost on par in this respect.
structure: a corollary of the above is that it forces me to "plan ahead" more than just "start coding" which I find fits my programming style better, and leads to better "Unix Philosophy" product designs. I haven't found any other language that has the same effect other than maybe Haskell.
speed: I honestly find that Ada code outperforms C/C++ code most of the time. The only times C/C++ outperform Ada is after optimizations that come at the cost of readability.
multitasking: Ada's first-class tasks and protected objects are the only way I've ever been able to write bug-free concurrent programs that are more complex than async/await and/or producer/consumer structures (and I took a dedicated elective on concurrency at university!). Kotlin is almost on par in this respect with its coroutines.
hardware: The fact that Ada basically ships with a hard real-time OS built-in and can compile to e.g. AVR means that all my fancy libraries I've written or saved work just as well for a desktop game, a website backend, or an embedded microprocessor. Just look into representation clauses and interrupt pragmas to see its unique powers.
design: The whole design of the language has lead it to be the only language where I can consistently return to a multiple year old passion project with no attempt to write maintainable code, and fully understand what its doing and modify it with little effort.
tooling: While this is the biggest downside of Ada (see below) gprbuild is still my favourite build tool. I have no idea why strongly-typed build systems aren't more common. Its always a joy to work in gprbuild, once you get gprbuild working of course.
static polymorphism: Ada's generics are some of the best I've found. But they have some limitations that leads us into...
There are some situation where Ada shows its age:
static calculation: I love Nim (and Zig, etc) for the ability to run arbitrary code at compile time. It allows me to describe what would normally be an opaquely initialized data structure or code path in a clear and descriptive manner.
terseness: Ada is verbose, that's not such a big deal, but I find its just a tad too verbose which can lead to some slight difficulty when parsing code. func/proc (Nim) vs fun (Kotlin) vs fn (Rust) doesn't make much difference to me, but function X returns Y/procedure X starts to add a lot of visual noise to a file.
web compilation: The ability for both Kotlin and Nim to compile to either ASM or JS is AWESOME. If I have to write a "full stack" application, Kotlin multiplatform with ktor every day.
operator overloading: Only the built-in operators can be overloaded in Ada. It always makes me wish I could overload arbitrary operators. A small thing, but a symptom of...
TOOLING: Ada's tooling is BY FAR the hardest I have ever seen to get working. It takes the "eat your own dog food" too far. The fact that even in Arch Linux you have to install a bootstrap package, then the real package shows how hard it is to get a consistent build environment. ALR is helping in this respect, but is still not quite mature in my opinion.
Here's when I use the alternatives, and their biggest weaknesses:
Kotlin: anything where I want both one or more JS artifacts and one or more JVM/native artifacts. Weaknesses: performance, static analysis, on the fence about tooling (gradle is cool, but sometimes seems too over-engineered), Biggest weakness: IDE dependency, writing Kotlin outside of IntelliJ is a pain, which is somewhat fair given who maintains it!
Rust: so close to beating Ada, if not for two things: ugly code - so many operators and glyphs that pollute the reading experience, maybe I'll get used to it eventually, but for now I can't scan Rust code, nor pick up and revisit it nearly as easily as Ada; language scale - I find Rust suffers from the C++ design attitude of "we can add this as a language feature" it takes too much mental effort to hold the entire design of the language in your head, which you sort-of have to do to develop software. Java and C are IMHO the undisputed kings in this respect. After reading through the specifications of both languages, neither will ever have any surprises in store for you. There's no magic under the hood or special case. All the cool features are done by libraries and rely on the same simple syntax. Every time I learn a new cool thing Rust can do, its at the expense of another edge case in the compiler that modifies my conceptual model of the code.
Julia: multiple dispatch and mathematics plus clean module design and easy unicode incorporation leads to clean code for math-y/science-y code.
Nim: templates and macros are excellent, concept system gives access to Rust-style traits without all of the additional "ugliness" of Rust, excellent performance, tiny executables. I just find that the syntax can get clunky. The UFCS easily cleans up a lot of the mess that Rust creates with its added features, since it keeps the parsing the same even when using some fancy language feature.
Thank you for attending my TED talk :P. Any questions?
Excellent tooling. The package/build manager (cargo) just works, the compiler's error messaging is simply unmatched and the IDE story is excellent thanks to rust-analyzer.
Rich ecosystem. There's a crate for almost anything you could need, and endless piles of learning resources.
You get the speed and low-level control (if necessary) of C/C++ without all the pain and legacy baggage.
The community tends to care a lot about correctness and API design, which is reflected in both the core language and the ecosystem. Rust doesn't try to hide complexity and pretend things are simple (like Go) - instead, it gives you the tools to manage it head-on.
Example: if a function can fail, then it returns a Result and you have to explicitly handle the possibility that something went wrong. There's no forgetting a null check and slamming face-first into a NullReferenceException or segfault in some other part of your code.
It's expressive. Iterators, generics/traits and other language features make it easy to communicate what's going on to both the machine and other humans. Even the syntax is designed to support this - you can tell a lot just by looking at a function signature.
Obviously it's not all perfect, however.
Compile times can drag you down. (rustc is always getting faster, of course, but it'll probably never be as fast as Go or JVM/NET.)
It can be difficult to read at times, especially when code starts leaning heavily into generics and lifetime annotations.
Speed and control comes at a cost. No garbage collector means that anyone coming from a managed language (which, hello, that was me) is going to have to rewire their brain to deal with lifetimes, ownership and mutability XOR aliasing. You eventually develop an intuition for how to structure your code to play nice with the compiler, but that takes time.
New language features can take a long time to be stabilized and released. The advantage is they tend to be baked all the way through from day one, but the slow pace can be infuriating, especially when big ecosystem advancements are hung up on key additions.
Go. It's high level enough in terms of syntax that it's easy to build complex apps in, and low level enough that I'm able to control pointers, manually run the garbage collector, and benefit from the runtime performance.
Python. Works for nearly everything I need. I mostly write small helper tools (most of them shared under a FOSS license) and for my job, I developed a backend API server which sits behind a web application. I also use Python for scientific math stuff as nearly every Matlab also exists for Python.
I did use Perl a lot before but in my opinion Python took over the role of Perl. I loved Perl for having a module for just about everything but nowadays most Perl modules are unmaintained and you find the "good stuff" for Python.
It's real easy to just launch it and get a script going, no need to wait for and ide or a compiler, there's alot of nice modules, and it's really API friendly
I've spent more time in the blender python API than I'd like to admit
Haskel, It's kind of hard to do some stuff which are easy in other languages but if you find a good problem to solve with it, it's amazing how expressive you can be and how short your code gets compared to all the boilerplate code you have to write with other languages.
Kotlin. I like how versatile its features can be and how much more it adds compared to Java. I also think it’s cool how Kotlin can be used to write native apps and web apps too.
I would like to learn Rust. I heard nothing but good things about it. I however don’t have the need or enough motivation to do so.
It picked a niche and fits exactly into it. It's a language for server side web pages. It's not a general purpose language shoehorned into the task, so it wisely sets boundaries. PHP could avoid a lot of async/await/promise hell because you can work in the mindset of HTTP requests-- terms of short lived requests that are compiled elsewhere. You don't have fragile runtime environments (see: server-side JS), since it just plugs into Apache or Nginx, which are at least battle tested and known quantities to operate.
It's batteries included. Hell, it's the entire Duracell company included. The standard library is rich and centrally documented, including decades of community nitpicks, even before you go into composer repos.
It's non judgmental. You can write procedural code, or object-oriented code, based on preference and fit to task.
It makes ad-hoc easy and formal possible-- If I need an array of
[227, "Steve" => "meow", 953 => new FreightLocomotive()] I can get it, or I can enforce types where it's relevant and mitigates risk.
Python. I'm a data engineer by trade and the ability to just lay out functionality between different systems and move content fast is great. I know you can do that with many languages but python does scripting very well. And since by default I am working with remote/parallelized/containerized systems I never really lament pythons lack of speed.
Obviously python is not the only language in my workweek.
You ask a carpenter what his favorite tool is? I like languages that are fit for purpose, and I enjoy using them for that purpose.
I used bin/bash when I automated the backups at work and happy doing it. I was pulling my teeth out when I had to write code for communicating with Bluetooth devices in /bin/sh because that was what was available from factory on the router.
I picked Python for when I needed to scrape a Romanian phone book (to win an argument on the internet about something completely unrelated to programming). I once tried doing parallel programming and threads, it did not work out very well and I switched to some other language before I got too deep into it.
My guilty pleasure is the voodoo magic of C. I don't really have a use for it in my job so I never get around to really do anything with it.
It just feels extremely natural to me, so it's difficult to pinpoint specific features I like. But two such features stand out: the parantheses-based syntax and the extreme interactivity.
Probably the most unpopular opinion here but PowerShell.
My main reason is that it's extremely easy to learn and is a good intro to object orientated programming.
People bash it but it's extremely easy to inspect objects, get any properties and methods associated with that object or class, walk through all the properties of the object and transform that into whatever you need.
It has a very fast turnaround time when developing code as you can run tiny snippets at a time and understand their outputs before moving to the next bit.
I'm not a Dev and end up having to write python from time to time and I hate it. At one point I just needed to understand an object in a variable and I couldn't do it, the command dir exists but it didn't give me any of the info I needed. There's a function in PowerShell called Get-Member (alias: gm) that you can pipe anything to and it will show you all those details of the object.
It helped me tremendously when I was just starting out.
Its super powerful, it can do anything C# can do because it's built on it, you can also run inline C, C# and C++ code with on the fly compilation.
I've never been happier and more productive than when I was working in Perl. It's a language that, at its apex, had a community of incredibly smart and creative people evolving it and its ecosystem. It's a practical, powerful, multi-paradigm language that let me get work done with a minimum of fuss.
Perl was a language that felt like an extension of my thoughts, like it was working with me and for me. Most other languages feel like I am working for the compiler rather than the other way around. Or at the very least, spending unnecessary effort satisfying some language designer's personal pet peeve, which constantly takes me out of the flow of the job I'm trying to do.
It's difficult to pick only one, but I'd have to say Ruby. The syntax is wonderful to work with, I can often implement the same logic in fewer lines of Ruby than other scripting languages I find, and it has constructs that make for elegant code like metaprogramming. It's certainly not the fastest language out there and those same concepts like metaprogramming can be abused, but ultimately I find it to be an excellently designed language that's a lot of fun to work with.
JavaScript. Stay mad but it's fun to write, easy to get into, easy to do both visual (e.g. web) and CLI-style code, and it's awarded me a cushy life, house, and car.
Good old C. Simple to use, minimalistic, stays out of the way and allows me to do what I want while programming. My only problem with it is that is no longer really a low level language to due auto vectorization in modern compilers and kind of requires a PDP-11 style flat memory model to have full control. Although if I ever want full controll in the language I can drop down to inline assembly.
I hate them all... But I like the looks of Go, just wish it hade the properties of Rust. And I don't mind Python for scripting. And I know too much and too little C++ for my own good.
I've used over a dozen languages, from BASIC to Haskell to C++.
If I were starting a new project today, it would probably be in Go, or in Python with static typing using mypy. Unless the project was itself a language or something language-like, in which case I couldn't stay away from Haskell and monadic parsing.
If I were looking to learn a language that I haven't worked in before, it would probably be Rust or Clojure.
Go is really fast, works well with "the Unix philosophy" (although maybe I should say "the Plan9 philosophy"), and has pretty excellent tooling.
Python is everywhere and there are libraries for everything. However, Hindley-Milner has been part of the CS canon for my entire life and there is zero excuse for a language not having type inference today.
Haskell gives access to the best goddamn parser library ever: Parsec. Screw the category theory; combinators are the Correct formalism for parsers.
(If you're still reading this: Read Graham Hutton's Programming in Haskell, second edition.)
(I made the mistake in my last job of getting 80% of the way into writing a new tool — a "configuration as code" utility for configuring load balancers — before I realized that it was, in fact, a compiler and would have been much cleaner if architected as a compiler instead of as a glorified ETL tool.)
Rust is what the Lemmy backend is written in, and I have terrible ideas of trying to stick my fingers in there and hope they're not bitten off.
Clojure is what a few of the most productive programmers I know work in, so there must be something good in there. Also, it's been almost 20 years since I last used a Lisp for serious work.
It's a tie between Julia and Nim for me. Both have a high-level, readable syntax while also being natively very very fast.
Julia is great for exploratory numerical/scientific computing, e.g., AI, simulations, etc. It especially has amazing math syntax and unicode character support, making for really elegant math code.
Nim is a systems programming language, and I've been starting using it for embedded systems lately. I think it could be really good for running machine learning on embedded devices, as C/C++ are kinda miserable for that, but MicroPython is way too slow and not well suited for production embedded systems imo. Plus it compiles to C and C++, so you can compile it and run it on any device for which you have a working C or C++ toolchain.
Kotlin: compatible with Java, JS, Wasm, Swift and even C++, ability to share code across all those platforms, way less verbose than Java, lots of useful functions in the standard library... I still don't understand why some people are saying it's just Java but worse
Can't believe I scrolled all the way down and didn't find Scala. It's the only language with decent traction that beautifully and elegantly combines functional programming and object oriented programming. Scala makes it such that the language does not limit you into a certain paradigm. You can translate your algorithm in your mind into code regardless of how you thought of it. Incredibly flexible where you need it to be.
Oh my favorite is Crystal. It's a statically compiled dialect of ruby.
It supports:
Most of the ruby goodness: custom DSLs, patching classes/mixins (monkey patching instances is not supported)
Compile time type checking (but it also uses duck typing)
Coroutines / fibers that work across multiple threads (multi-thread support is still experimental, but from my experience works well)
Possible to create small self-contained binaries (like go-Lang apps).
As much as I love the expressiveness of crystal, there are a few cons:
It's slow to compile. Due to the dynamic nature of the language, the compiler needs to parse a lot of files (think C/C++) before it creates a binary.
The number of libraries is very immature at the moment. Crystal is a young language and is missing support for things like aws.
The library management mechism (called "shards" akin to ruby gems) is not great (in my opinion). There are helpful tools to create the scaffolding, but if you're pretty much stuck with the defined structure. For example you cannot have a single git repo that provides a library and an application that uses it.
Other than that, the type checking but with ruby-like syntax is awesome!
I'm probably the black sheep here, but I love Kotlin. It has the best parts of strong typed, object oriented languages and functional languages. Though I feel like it being designed to be bytecode compatible with Java really limits its applications. Even though they have a scripting language version of it, it really doesn't perform well as a scripting language because you need to compile it. I find myself always using Python for scripts instead.
matlab 😈 because I love figuring out how to vectorize code! I've used it for various art projects (see below) and it manipulates images beautifully. and the documentation and error messages are easy to follow.
No one else said it… I like Java, and more than the language all the tools available around it. They have been adding to the language to cut down on the traditional verboseness, and it can even natively compile now** some of the time.
The tools are also great, with Springboot for web services and jOOQ for databases, you can very quickly have a web app with strong typed database objects.
I try to stay language agnostic but if I'm honest JavaScript is my favorite because of the speed it provides. Also I like to build we based things so it's always in the stack
Clojure. I not only get to use a functional language but also get to use all the libraries written for an actually popular language (Java, or JS for ClojureScript).
Altough I'd choose something else if functional programming should ever catch on.
FORTH, but not because I actually use it regularly. A stack-based zero-operand postfix language? Every routine/word you define is like solving a puzzle.
I like writing mostly just script. I enjoy writing stuff in bash and lua. Its simple and quick. I have been trying to learn some C to do things with mirocontrollers but its a slow process....
Favorite? Kotlin generally speaking, but I use Python the most and like it quite much as well. Can't beat Python's time for zero to something useful running and you will find bindings and frameworks for anything.
C++ for anything performance sensitive, or running anything on my Synology NAS.
Bash for quick scripts, Ruby for some smaller scripts, Golang has been a favourite as of late due to integration into the ecosystem with k8s,p8s, envoy..
It's like C with better syntax and without memory management annoyances. It also comes with a decent standard library and making concurrent programs is a breeze. As a bonus it generates static binaries which, granted, are big but in most cases can be copied to any other Linux workstation and executed directly.