Ask HN: What is your best way to learn a new programming language?
I know the good old answer, practice.
But are there any tricks that work for you while learning a New Language or you just get better.
I want to learn Swift as my new language so how do I approach it.
I know a lot of different languages but they have basically same syntax (C, C++, Java, JavaScript) but it takes me a lot of time to get a good grip of it and I am not sure if experienced developers feel the same or do they learn it faster.
So what's the best way to learn it and maybe the fastest?
44 comments
[ 3.0 ms ] story [ 84.9 ms ] threadHere's a project I'd do for Swift.
1. Write a chat server / client. (this will quickly let you see how async/threads/channels works and how good the networking libs are). You can easily go further and add a GUI to see what thats like. Add Sqlite for managing contacts/settings to see how the db layer works.
2. extract things into libraries/modules/packages i.e.whatever swift calls it, to learn how their pkg and version mgmt system works.
3. As soon as you have something working push it to a server and get it running. Add a bash script to do this automatically. The goal here is to learn how to actually release and deploy using swift.
It doesnt have to be a chat app, I usually do something thats like a problem I'm currently working on, and its best if you can actually use it to solve some real world problem. It just needs to be something that has a lot of places where you can explore parts of the language i.e. db,networking,async,etc.
My go to way of getting my feet wet is rewriting a library or a part of one I've developed before. I know the problem domain and can figure out how to tackle problems in the new language. Understanding the dependency management and publishing tooling is also always great fun!
So I got a copy of Stroustrup "The C++ Programming Language" and started to do his exercises, but the author clearly had never done them himself, some were quite long and tedious and did not teach me anything (never put exercises in a book that you have never done), so I gave up on doing his exercises.
In my exasperation I just made up my own exercises: I just started at the beginning of the book and for each feature the book mentioned I wrote a little program that used it. The book said you can throw any kind of object, including, say, an int, so I wrote a program to throw and catch an int. I have never done that before or since, but I did it. I wrote a little program for every feature of the language. It was incredibly tedious, but it worked.
I also compiled every program with two C++ compilers and ran them and compared the difference. Many of my little programs did different things in the two compilers (!). I coded for 10 hours a day for two weeks; when I was done, I could code in C++, I could think in C++. Don't despair if it takes you longer: recall that I was already an experienced programmer.
SECRET SAUCE HERE: The key here was to actually write the program even if I was sure I had nothing to learn from it because the feature in question was so conceptually simple: you think you know something, but then when you go to actually type it in, you find out whether know it was well as you thought you did. The tiny improvements you make while doing this copy-check-repeat feedback loop is the essence of learning the skill.
Note that no mistake is too small to be worth correcting. It is critical to not say you have passed the exercise until you can produce the result exactly and reliably, as a matter of course. If you just wrote a program and it was easy, then hide it and write it again.
At one point I was embarrassed that I could not write makefiles, so instead of copying them and hacking on them, every time I needed one I wrote it from scratch; now I am a master of gnumake. I repeatedly write fizz-buzz, binary search, heapsort, hashtables, etc. over and over, just to make sure I can do it correctly and without effort.
One of Richard Feynman's wives left him, legally accusing him of spousal abuse because he did too much c1alculus: https://www.theguardian.com/science/2011/may/15/quantum-man-... '"He begins working calculus problems in his head as soon as he awakens," Bell complained to a divorce judge. "He did calculus while driving, while sitting in the living room and while lying in bed at night."'
Ben Franklin describes using this method in his autobiography of how he taught himself to write. He dropped out of second grade and ended up as one of the best writers in American history (not to mention scientist, statesman, engineer, etc.) He says he found writing he liked and practiced copying it and then checking that he had copied it correctly; see his autobiography for more.
Woz used this method to teach himself how to build computers: he had the designs of computers from Silicon Valley firms and he just practiced rote copying the designs over and over.
I tell you this as a former graduate student in Mathematics at Berkeley: The secret to learning is not reading a bunch of abstract ideas. The secret is just running a huge number of examples through your brain; your brain then abstracts them for you. There is no need to study a bunch of abstract rules. After you have learned the skill this way, doing a "master class" with an expert where you return to what you have learned and examine it, thin...
Technology and languages change. They have definitely changed a lot since my first combination of hobby AppleSoft Basic, 65C02 assembly language programs in the mid 80s. But concepts remain. I've gotten to the point in my career where most interviews don't focus on technical minutae of the language I code in. They focus on high level architectural concepts, best practices, and leadership skills (I'm still a hands on coder but these days I'm usually either officially by title or day to day in reality an architect).
In reality, all of the popular languages in the industry are "C like". I can watch a video while I'm working out to get an overview of the language and then just start coding and know what I don't know.
This is what I've done in my admittedly small time of programming. I have Learn Python the Hard Way and whenever I'm in between my personal projects, I grab one of the beginning chapters and just redo it. Rote memorization is not easy for me, but the more I do something over and over, the more engrained it is and the easier it is for me to recall and build on later for different things.
However this doesn’t really work when you’re switching to a different paradigm. When I switched to Haskell, I realized that even the way you think about things must change and diving into a project just isn’t the way to do this. You’ll keep stumbling the entire time if you bring your imperative mindset with you and attempt to leverage off them to get a quick start.
If you don’t have some functional programming experience under your belt, first spend some time familiarizing yourself with the language history and try to figure out why some design choices were made. Try and soak up as much theory as you can by getting the best books on the language. This is much slower but you have to bear in mind that sometimes you have to unlearn several things that may be considered a bad practice in the previous languages you’re familiar with.
I try to treat learning a new programming language like learning a new human language. I know quite a few and it’s always easy to fool yourself into thinking that once you know the syntax and grammar for a similar language you can port them over to the new language. You’ll be surprised to know some languages don’t have some words at all based on their culture and have no way to express something that is easy to grasp in English.
So long and short, history and some theory about the language first, then dive into a small project, pick up another book along the way and then more theory.
I guess I should start reading the docs because sometimes the answer I find Googling is already present in the docs :)
Perhaps it comes with experience. My first few languages were learned ad-hoc like most people learn. Only after experience with a few languages did I start reading the manuals and getting an even better understanding of them. You learn a lot even when you previously thought you were already fluent with a particular language.
I find it really helps to write a parser for the language (Assuming the language can be parsed with a LL/LALR Grammar or PEG). It doesn't need to be a robust parser which handles all errors, but just a trivial one which can help you to understand all of the edge-cases in the syntax. A parser you wrote yourself makes a good reference. Depending on the complexity of the language this can take a few hours to a few days to write.
Once you have mastered the syntax, begin to tackle the standard/common libraries bit by bit. Try to write small but useful applications to utilize particular parts of libraries. Name them well so they're easy to refer to again later, so when you come to need a particular library feature you can look up how you done it last time. (Although you'll usually look at these and be like "What the hell was I thinking back then?")
So if I were to be learning Swift, I'd grab the ePub from here: https://swift.org/documentation/#the-swift-programming-langu... and skip directly to page 917 which lists the language's context-free grammar. This is essentially a 42 page cheatsheet for the entire language syntax (could probably be condensed to about 15 pages if split into two columns and whitespace removed). This epub is a great example of well-written documentation. It's broken into groups of production rules with good cohesion, and every terminal and non-terminal symbol in the grammar is hyperlinked to the part of the document which describes it in more detail.
I'd read through the grammar and perhaps even rewrite it side-by-side as I'm going through it. (There are some good tools for writing and testing grammars interactively, which I would definitely make use of). I'd guess since the language borrows from C#, Java, Haskell et al, which I'm already familiar with, that I'll be able to understand the majority of it without looking up details - but when i do encounter something I'm not sure of it's just a click away.
1. Write a program in the language that I've done before just to get familiar with the tooling. My go to for years was a better Eliza clone. From 1991-2008, I wrote it in AppleSoft Basic, GW Basic,HyperCard, VMS DCL, Visual Basic, C#, PHP, and JavaScript.
2. On the job. I hate hobby side projects. I'm not creative enough to come up with anything interesting and I feel like it's a waste of my time to build something that will never get used. I would rather just work on a proof of concept related to my job after hours and show it during a lunch and learn. I get real feedback from peers and if it's implemented, I get to "productize it" and see it in the real world.
3. On the job (part 2), I'm at a point in my career, where companies will hire me if I only have half of the required experience in the technologies they use because I've worked at a lot of small companies where I've led projects either officially as a team lead or unofficially because the team was so small I could take the lead. I can usually get a job based on what I know well and they give me the opportunity to learn what I don't know while doing a project. I'm more than willing to put the time in to get familiar with a technology I don't know.
4. PluralSight - I'll watch videos to get an overview of a technology usually before I go to work in the morning while working out in my home gym.
5. Certifications - I don't believe most certifications are worth it from a career standpoint and when I'm hiring, I take many of them -especially developer certifications - as a negative signal. I wanted to learn C# in and out in 2008 when I was transitioning from 12 years of C/C++, did a combination of 1-3 and did the highest level of MS developer certification that required 6 tests. I never put the cert on my resume or talked about it during an interview, but it forced me into an organized learning path.
I'm working on my AWS certifications now for the same reason - to force me into an organized learning path. But I will put these on my resume, they seem to carry weight - especially at consulting companies.
I found that using the new language as though it's the familiar one makes you quickly understand the limitations. As you try to bend the new language into supporting your own familiarisation, you accidentally learn the lower level details.
For me I have a couple:
1) A nonlexical phrase extractor. Read in a lexicon of words, read in a narrative document, subtract words from the lexicon from the document, collect all remaining strings with word length > 2. Voila, most of them will be names of people.
2) Build an on disk bloom filter. Pretty straightforward, the most complicated part is finding suitable hash functions and figuring out how the local mmap library works and working out the arithmetic for bit flipping amongst a big array of bytes.
Neither of these are very complicated or require lots of work to set up. But when you're done you'll know most of the operators, how to read in and write out things, how to interact with the standard library, control flow and so on. I can usually hammer both of these out in an afternoon.
A few people I know have more advanced "simple" projects, like ones that require figuring out the local threading system, sockets and so on: e.g. write a simple web server. It kind of depends on what kind of work you generally do.
Problems and friction are exposed pretty quickly, but you have to push through those to see if the good parts of the language make up for them. I find that if, after a short while, I don't have to force myself to write the code, and if I can dream up ways to solve any problems I encounter without turning to the documentation, then I've found a really good fit. Sometimes you find that the initial friction was largely just a matter of coming from another language's mindset.
If you find instead that you're not wanting to write code, that you're spending a lot of time fighting it or scowering the documentation or getting the build to work, then my opinion is that the language isn't worth learning anyway so it's best to move on.
Do your damndest to find a person more experienced with you in the language that can offer a code review after you create a mini-project or otherwise contributed to a codebase. I've learned alot on my own but having an objective person who understands the language better & can point out things like 'that thing you did in 3 lines of code can be done in 1 with this syntax in this language' has been invaluable to me.
Tap your professional network if you've got one, find a way to get this as part of your learning. I doubt you'll regret it.
Then I pick a simple project that will teach me both the basics and use whatever it is I'm interested in with that particular language.
Additionally, I start a new repo with code snippets. When I need to learn something I write a simple program with an example of it and maybe some variations. So I might have a file named equal.rb and compare equality with ==, eq, nils, "", etc... This helps me learn a specific aspect and later becomes my reference when I say "I know I did this before", it's a lot easier to find in my repo than find a location in a book and remember.
Open Xcode and start dropping controls over the initial form, then run it, close it and make buttons click, textfields do some calcs and tables show some records. If you can do that there is nothing you won't be able to do.
There are lots of aspects of that learning experience that I think are worth repeating:
- social: we all had to figure out GOPATH together!
- playful: it's clearly a toy which means you have the freedom to explore, goof off, stretch yourself, and be creative
- comprehensive: it actually covered a ton of pertinent Go knowledge: goroutine, networking, interfaces, chans, select, etc
I try to avoid example code snippets, since I want to figure it out myself.
Oftentimes when reading those examples everything seems to make sense, but when I'm faced with repeating what was shown I get stuck.
So now I avoid them completely and try to figure if out myself.
Of course I forget all the details, that's what books are for. It does seems more effective than just trying to map what I know from other languages into the new one.
This where I write a few paragraphs about the various languages I learned, realize none of you people have time for reading this and delete it in favor of getting straight to the point:
Not having enough problems(challenges) to solve is usually a major hurdle. Ask yourself why do you want to learn this specific language? Does it solve a specific problem you have? If so, try to solve that problem using this language.
Recent example: I wanted to process audio in realtime and my default approach(JavaScript) just didn't cut it. I stumbled upon Rust and it proved to be a great language for such applications.