Hacker News new | ask | show | jobs
by tester756 1339 days ago
I do believe that learning many programming languages is overrated

Learn concepts, obtain foundational computer science knowledge, write complex projects

not just get familiar with somebody's interpretations that they implemented as a language.

Languages that I used besides my job language barely gave me anything, in most cases they made me appreciate more for sane environment (package managers, IDEs, debuggers, strong standard library)

edit. just to be clear:

I don't see value in learning C#+Java+PHP, but C#+Erlang? yea

I do see value in learning Rust after C

but still - concepts are more important, you don't have to learn langs in order to be familiar with concepts

Learn software engineering - it's broad as hell and you can easily do that using one language

10 comments

Concepts can often be simulated in many languages, but only clumsily, and the lack of ergonomic affordances in syntax, control flow and type systems can lead one to believe that a different paradigm doesn't work very well - it can be hard to see the wood for the trees.

It's hard to write a declarative querying library in C. SQL is not an ideal language, but as a way of expressing intent rather than a physical query plan, it's a long way away from C.

It's hard to appreciate the power of interactive debugger REPLs like binding.pry or JS's debugger without experiencing them. A C++ debugger, even a Java debugger, is a pale imitation, and it's not easy to simulate the experience without building a dynamic language inside the static language.

If all you've ever known is statically typed languages, you can suffer from a myopic parochialism with respect to dynamic typing. IMO the most popular statically typed languages only work well because they have runtime polymorphism holes in their type systems. More powerful statically typed programming languages tend to grow ever more esoteric typing constructs to enable static types to follow dynamic control and data flow - there's an inherent tension there and if language complexity isn't carefully managed, it becomes harder to express intent and error messages get more vague and cryptic.

Algebraic data types and pattern matching tends to be under-appreciated if one is schooled in object-oriented languages. Object orientation has a big hammer for switching control flow based on data values, dynamic dispatch, and architectures tend to leverage dynamic dispatch where they would be much better off with switch statements. If the set of variants is known up front, you're probably much better off with sum types and pattern matching than with interfaces, abstract classes and virtual methods.

It's interesting you bring up REPLs. I never in 20 years working have ever worked with one. I switched jobs and a few people are coco in love with them.

This probably more than anything else comes down the programmer style. I had to use Jupiter notebook to help my wife learn programming Python and it was horrific. I could never imagine that real work was done in this way, but I know many good programmers that swear by it. I suppose that when I need something like a REPL, I tend to use my debugger instead.

Well, there you go. Jupyter isn't very much like binding.pry, because it lacks the debugger-ness.

REPLs without the debugger bit aren't nearly as good. That's why I mentioned debugger for JS and binding.pry (implicitly, for Ruby).

binding.pry pops you into a terminal REPL with the local binding in scope, just like the eval function of your debugger; except you can start writing loops, define new variables, and more rarely, new functions, right there.

When writing code with a test-first model, you set up the data fixture then pop a binding.pry in the implementation, right where you expect to start implementing it, and run the test. You can then implement the logic in the middle of the test execution - in the middle of your debugger session - and because the REPL is so expressive, you can do a lot. You then copy & paste out those lines and save them in the implementation logic, and shuffle the binding.pry on to the next spot.

Or in a hobby project, you can fly by the seat of your pants, and write code live on the server. There's a remote version of Pry if multiple workers sharing a terminal start fighting each other to own keystrokes.

I agree with your sentiment about REPL's, but there are two use cases where they're very useful.

1. When you need to explore behavior.

For example, C# has slicing syntax now. MyString[..15]. What happens when the string is only 8 characters long? Lets hit the REPL and find out.

2. Poking at systems using the same code as the rest of the codebase. For example, RoR. Being able to load up the RoR framework and poke at the ActiveRecord objects can be hugely helpful for tracking down an issue.

This is pretty much the point of the article.

I have a few reasons to work in (not just learn) close languages. The languages might use roughly similar concepts and syntax and solve similar problems (think, C++, C#, PHP, Java, Go), yet their community, practices, tooling, frameworks are wildly different.

If as a C++ developer in 2005 you never experienced how smooth debugging and profiling could be in Java, how fast things could compile, how easy it was to drop a jar and deploy to your server farm, you were missing out.

Similarly, if as a Go developer you don’t know how quickly you can install WordPress, write a 200 line PHP plugin, and get an entire business off the ground, you are missing out.

Most transformational for me was to be a Common Lisp developer, and find the language that allowed the ideas and concepts in my brain to be turned into prototype at the speed of thought. It’s a challenging language to use in the real world, but it really brought the point home that a language is just a vessel for ideas.

> Learn concepts, obtain foundational computer science knowledge

Well yeah learning a wide variety of languages is a good way to do that. People write new languages because they want to implement new concepts.

>Well yeah learning a wide variety of languages is a good way to do that.

Well, depends what concepts are you talking about.

Computer science is huge as hell, concepts that you may learn from programming languages are just subset.

There's a lot of interesting and hard stuff that does not touch those (I'm not focusing on some domain-specific-languages that nobody know about)

But learning languages is a great way to learn many concepts. Obviously it doesn’t teach you everything - nobody claimed that.

Want to learn concurrency? Try a concurrent language.

Parallelism? Learn a parallel language.

Data flow? Learn a data flow language.

Pattern matching? Learn a language with pattern matching.

Etc for a thousand useful subjects to learn.

These are great ways to learn so many software engineering concepts. Use other techniques to learn other things sure.

Are you actually learning X when your lang has strong and easy to use primitives for that, so you dont have to understand how does it work?

eg async await

You are just learning tool like Excel

Yeah for example I can’t think of a better way to teach yourself to understand and use structured concurrency than a language like Cilk which naturally drives you in that direction. I actually started a PhD on how language design shapes the way you think about concepts (but finished it on implementation instead.)
And god forbid if you want to learn things outside CS, too. Like you know, most people.
>but still - concepts are more important, you don't have to learn langs in order to be familiar with concepts

You kinda do. Concepts are often exclusive to languages. And often concepts can't be internalized without practice of that lang.

Your own examples in your edit literally contradict what you say as you chose langs with extremely divergent concepts. C# and Erlang, Rust and C. You missed haskell and lisp.

>Your own examples in your edit literally contradict what you say as you chose langs with extremely divergent concepts. C# and Erlang, Rust and C. You missed haskell and lisp.

How so?

You can learn and understand concepts implemented in Rust without learning Rust

Concepts aren't just "learned" by reading about it. True learning requires internalization. Internalization requires practice. Practice requires the concepts to be applied. Application requires real world tools. Usage of tools requires one to learn about the tools.

If the only tool available is rust, then one must learn rust to truly learn the concepts related to it.

100% agree. And the Rust compiler is a great way to internalize those lessons since it shows what you got wrong, where you missed an ownership assignment, and often telling you how to fix the problem in plain English. It's as close as I've found to an actual teacher while writing code.

When the compiler stops yelling at you all the time, you'll get your feedback that you've actually learned those lessons.

When I was in undergrad our professor had us learn Java, but also Lisp and Prolog, and that was very valuable to my growth as an aspiring (and now thankfully employed) programmer :)
Don't get me wrong, I'm not saying that there's no value in programming languages

I'm saying that programming languages aren't they only way to get familiar with concepts

Nobody said they're the only way. But they _are_ a very good way, for a variety of reasons (which have already been discussed here).
I agree, but certain concepts exist strongly at the language level. Like functional programming, Haskell for example: the power of static typechecking along with good type inference, or functional/immutable patterns, or programs as data (IO monad).

Or Prolog and logic-based declarative programming.

Or any GC'd language.

Or a Lisp and its metaprogramming.

I daresay these ideas would be very difficult to see the practical use of, or "impractical" beauty of, without touching the languages.

+1. I once wrote an article exactly describing this[1]... but I think that learning concepts involves learning different languages because the concepts are not implemented the same way in every language and seeing different implementations helps understanding the nuances and differences a lot.

[1]: https://pilabor.com/blog/2021/05/learn-concepts-not-framewor...

It's overrated in a sense that it isn't that much of a chore, learning a new language is easy if you're already good at software engineering.
My name is Dave, and I'm an addict.

Charlie Watts wasn't just into jazz, he was into all music. George Harrison understood that jazz could deepen him as a musician, but found Indian music.

If one wants to write a language that is truly original, that might actually influence the future, not just smearing around familiar weightings for features found useful "in the trades", then one wants to have some grasp of languages representative of every language in use. Then, only proceed with a compelling vision of what's missing.

For the rest of us, being a language junkie can be a problem. Without being judgmental, it is possible for a person to be too promiscuous. Same with languages. I wish I could just stick to Haskell and get work done.

I agree that it is way more valuable to know / being able to invent concepts, algorithms, architectures. That is what interests me most when I design software products for my clients and for my own company.

Languages for me are just tools, like screwdrivers. I use / used many and do not get hung up. And no I do not learn languages just for the fuck of it. Only if I see some positive ROI.

How are you supposed to learn concepts like higher-order functions if you only know C, for example?
If mathematicans did it, then why we, computer people wouldnt?
In my opinion, having it baked it into a language you use allows a sort of internalization of the concept by practice/use. You don't just get the idea, but get a feel for it.
Read about them?
What is that good for if you can't use them for anything?
What is that good for in other language if your day job is in C?
You know, there are programmers that don't code only as their job, or don't even have a (programming) job.