Programming Languages to Learn in 2021 and Why

Jochen H. Schmidt
Feb 28 · 6 min read

Knowing just one or two programming languages misses out many concepts out there. There is not one single language that is enough for anything. Knowledge you gain through the concepts of a new language can often apply to many other languages too. This article lists a number of languages you could learn and makes clear what you should take from it.


This language still has a bad reputation with many closed-minded developers. In a nutshell, it is a typical example of a dynamic language with very flexible runtime features. You can put together different object shapes — even incrementally — in any way you want. Using a garbage collector you do not have to concentrate on fine-grained deallocation of resources. Its runtime flexibility makes it possible to extend the language in many unexpected ways — recreating features of other languages.

Programmers with a more static typed mindset can learn skills about how to develop complex programs in a dynamic language. The bad reputation here is not a lack in the language, but a lack in language skills of many programmers. With first class functions it is a good candidate to apply techniques from the world of functional programming — e.g. controlling side effects and using immutable data structures. Using such techniques is an important step to make dynamic programming work for complex problems.

Additionally, JavaScript is nearly omnipresent: It is the language of the Web, by being included in any Web Browser. It also is a capable language to implement backends using runtimes like Node.js or Deno. You can use it to implement hybrid and native mobile apps or desktop apps. Leaving out JavaScript leaves out a big pie of the modern computing world. Its pervasiveness also drives more and more optimized takes on its many runtime implementations with high speed JIT compilers and sophisticated memory management. Being part in nearly any consumer device is a big motivation for such developments.

As an ecosystem, JavaScript more and more relies on compilation strategies. It’s common to create compilers in JavaScript which translate new language features down to plain JavaScript for consumption in runtimes without such features. This can be either features of more modern JavaScript or features like JSX-Syntax, static type annotations or compile time components like in Svelte. Meta programming is huge in the JS ecosystem.


Not really a language on its own — it’s an application of the meta programming that takes place in the JavaScript ecosystem to include a sophisticated static type system. TypeScript is just JavaScript with static type annotations and a type checker that can check your programs. While its first versions looked more like someone trying to make JavaScript look more like C#, its direction did change radically. It has a very innovative stake on how static types can get bolted on a dynamic language. The result is a language that is neither a clear-cut dynamic nor a clear-cut static language, but something pragmatically useful in between.


While many people think that the world is ruled by languages like Java or C# — there still are huge ecosystems which are completely unimpressed by that take: System programming and Games are still domains for languages like C or C++.

Laypersons often assume it’s all about execution speed, but that isn’t strictly spoken the real compelling reason to use a system programming language like Rust. Even languages like C#/Java or JIT compiled JavaScript can execute code in very high speed. Much more important is complete control about how to lay out data structures in memory. Having nearly complete control of the machine down to the metal. Runtime features like a garbage collector or even reference counting is often seen as expensive and is only applied if nothing else will work, while they are mandatory features of other languages.

Rust is often seen in competition with C++: a language that has grown massive over the last few years and is very difficult to master. One of the most innovative features in Rust is its memory management: The „Borrow checker“ is a part of the compiler that follows the flow of ownership of your data through the whole program ensuring that it is always clear who is responsible to free it when it’s time. This feature was already portrayed as some kind of „static“ (compile time) garbage collector which makes it possible to write programs which get the memory safety of a managed runtime language like C# without introducing expensive runtime features.

Rust enables move semantics on value types (like modern C++) which means that it can automatically move the ownership of stack allocated data to the caller when returning or into a function when giving it as a parameter. This reduces the amount of copying data while it flows through your program while ensuring safety through coherent tracking of ownership at compile time.

This innovative memory management makes Rust an ideal candidate as a compile-target for WebAssembly, which is at least one reason why this language is used in this ecosystem a lot.

This isn’t the only thing to learn from Rust: Similar to languages like Common Lisp, Rust has a macro system which enables compile time meta programming and enriching the syntax of the language in flexible ways; again without introducing expensive runtime features.

Rust has a very interesting take about applying features from object-oriented programming: While it leaves out inheritance, it employs a type system with so called „Traits“ which are similar to interfaces, but can get implemented on any type even if those types are already defined. This means you can actually extend other types with new functionality. This is not possible in the same way in interface based OOP languages like C#.

With its enum types being actually discriminated unions it leans towards a feature set typical for static functional languages while not really being a functional language. It clearly still supports imperative programming without compromising safety. Similar to TypeScript, Rust is another take of modern languages which refuse being characterized to certain fields of programming (functional, OOP, imperative…) and instead cherry-pick features to combine them in a new and innovative way.


Swift certainly came as a surprise when Apple uncovered it at WWDC 2014. At that time, coding native iOS, iPadOS, macOS, watchOS and tvOS apps was nearly always a task for Objective-C — a dialect of C extended with Smalltalk inspired object-oriented programming features.

The language tries to be a balancing act of being compatible with the grown ecosystem of Apple’s frameworks and platforms while being a new take regarding general purpose or even systems programming that is in part similar to that of Rust.

The memory management of Swift uses compiler supported Automatic Reference Counting for class instances, which is similar to Rust, when using heap allocation. Similar to Rust it also encourages using value types and many core types like String are actually value types. One key difference though: If a value type is actually boxed (heap allocated) or on the stack is mostly an optimizing decision of the compiler. This shifts Swift’s ease of use a bit more towards managed languages like C# but also takes away some certainty and control a Rust programmer may have.

Without a Garbage Collector and based on LLVM, Swift is one future contender as a frontend for targeting WebAssembly. It’s not as far though as Rust is in this field — but huge steps further than Microsoft with C#.

As a replacement for Objective-C, Swift implements the concept of Protocols. Similar to interfaces, they stand out having the feature to allow extending existing classes. Unlike extension methods in C# this even allows polymorphy.

Meanwhile, Swift and its Foundation library got ported to Linux and Windows, laying the groundworks for a new cross-platform programming language. With SwiftUI Apple created a radical new approach to create user interfaces, which makes use of the particular features of its new language. Unfortunately, Swift is still an ecosystem mainly driven through Apple’s platforms. It would be good for Swift as a language if Apple could enforce a similar cross-platform stake like Microsoft did with e.g. .NET and C#. Swift could sit in a sweet spot between managed runtime languages like C# and more low-level languages like Rust. When Google can so easily take the cross-platform App domain with a Dart-based Framework which re-draws native Views using Skia, Apple could have a killer tool by supporting SwiftUI for Android and Windows Apps. Even if they take the easy route like Flutter, it would still be a first class citizen on Apple’s platforms.

Wrapping it up…

There are now many interesting languages besides of the somewhat old languages like Java, C#, C or C++. A more and more common scheme seems to be that languages are not clearly categorized into being „object-oriented“ or „functional“. Modern languages cherry-pick concepts and apply them in new ways. Time to get started with some of them…


Everything connected with Tech & Code

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store