Hacker News new | past | comments | ask | show | jobs | submit login
Practicing Elixir or any programming language (ericdouglas.github.io)
173 points by ericdouglas on Aug 24, 2017 | hide | past | favorite | 58 comments



I always find it interesting how people learn so differently. Personally, I learn a language by building something in it. I want a feel for it, before digging deep and learning about theory. I only do that stuff much later, after I'm relatively proficient in the language.

This is probably why I wasn't very good at picking up musical instruments. I was never satisfied learning at a slow pace and only being able to play "twinkle twinkle little star". Programming is perfect for me because you can build things before you really know what you are doing.


Spoken languages are like that too. A 3 year old doesn't know what verbs are. They just speak.

Another interesting thing is how people forget their path to personal journey regarding learning. "I did `y`, but you should do `x` because now that I look back I should have done `x`." "But, but, you did `y`! "Yes, but `x` is the way to go."

You mentioned musical instruments: great topic. The very best musicians have always been around music, sometimes not even being able to read music. There is no clear path, the only clear thing about this is the time + effort regarding learning something well: just have to put in the time.


> Spoken languages are like that too. A 3 year old doesn't know what verbs are. They just speak.

Not sure how you meant this to be understood, but a 3 year old definitely knows that there are different word classes that behave differently. They don't know that they're called verbs, nouns, adjectives, etc. but they do correctly (to a large enough extent) use grammar applying specifically to the different word classes.


Most programmers I know are like yourself. I'm the opposite, I'm the person you say you can't be, I will study and read until I feel I have a good handle on some nitty gritty before I ever put hands to keyboard

At some point in my career i became a team lead and that's where this difference became obvious. It took me a long time to adapt to the fact that everyone but me on the team learned by doing


Yes, I'm the same.

With Ruby, I actually learned Rails first, and built a few apps with it (one of which is in production and going well). Then I went back and took the approach in this article to learn Ruby better. I still wouldn't call myself an idiomatic Ruby programmer, but I know enough to do any task I'm faced with without writing complete rubbish.

With the little Elixir I've done I took the same approach: dived in with Phoenix and started porting one service from a large, complex API from Scala to Phoenix. I picked up some Elixir on the way, and later took some more time to look at Elixir, the language.

Building by doing is great. It gives you motivation and concrete rewards, which keep you inspired to learn more.


Very interesting.

The big point should be: do some practical stuff to keep you motivated while you are learning!


I am reading Haskell Programming from First Principles right now. If I did not know how the language works from doing this reading, then I do not see how I could make anything useful without quickly getting annoyed by the compiler


But in Haskell your "do, see reaction" loop is the compiler. Most of the interesting bit of it is incrementally defining types and functions for your program and verifying that it's still legal. That way, when the compiler responds with something very confusing looking you know what caused it and that can help a lot with understanding what it's saying. And when it still doesn't help, you can ask on one of the various forums and gain some important new understanding that I don't think I would ever associate or understand from a book reading.


I actually started the same way. In the article I focused more on step 4, but in step 2: "Familiarize with the syntax and semantic of the language" I watched a video course and built two mini projects.

To practice the language specifically though, coding challenges are pretty effective, funny and more focused IMO


personally i think algorithm or hacker rank-like problems are probably a poor way to actually pick up a new language.

pass one for me is usually "read all the books that are needed to cover the main parts of the language, toolchain, frameworks, idioms, etc and make sure to type in the code as you go." for elixir this means all the pragprog books and probably one book on OTP/beam.

second pass is once that surface level knowledge has been exposed and digested immediately start trying to solve real problems with the thing, using said books and code written above, in addition to language docs, as a primary reference, the internet (stack overflow, etc) as a secondary reference only when absolutely necessary.

if you don't have the first part of dedicated learning and wide exposure (without a motivating problem per se) you inevitably end up doing the lazily evaluated "stack overflow driven development" since you haven't been exposed to the breadth of the language, frameworks, etc systematically. in other words, you don't know what you don't know. the first part also sets you up to have some working examples you built yourself (with the help of books and documentation) as handy references that you are comfortable with since you've been in that code.

if you don't have the second part of solving a real problem you never actually form the skills that come from applying the tool to a real problem with no hand holding.

i think academic algorithmic problems are kind of the worst of both worlds. they don't really give you a systematic way of being exposed to the APIs and language quickly, and they also aren't real motivating problems so you end up probably only really learning a narrow scope of things that are practically useful for building stuff.


> "if you don't have the first part of dedicated learning and wide exposure (without a motivating problem per se) you inevitably end up doing the lazily evaluated "stack overflow driven development" since you haven't been exposed to the breadth of the language, frameworks, etc systematically. in other words, you don't know what you don't know."

Totally agree. I'm doing exactly this. But instead of only read books and type the code, I'm also after each section of the resource (doc || book), practicing code challenges :)


I actually really enjoy doing katas on https://www.codewars.com/, especially when I'm ramping up on a language.

You solve a short problem, and then immediately see how other people solved it. I'll frequently write something and then see a solution that uses a library function I wasn't aware of, or a solution that's similar but better follows the language conventions.

It's really helpful to solve something short and get immediate feedback on it. You aren't learning how to write big programs with the language, but it's still useful at first.


Agree, I have learnt both Clojure and Haskell on codewars when I was bored in lab. Another advantages is that the typical problems in codewars often does not involve learning extra libraries or IO, which often distracts me from learning the language itself.


I do that with Exercism and Elixir. It's pretty awesome.


been meaning to try exercism for a while, thanks for the reminder


I learn programming languages today the way I learned my first one. I have (what is now an ancient) copy of the old DEC book, "101 BASIC Computer Games" and I port some of those games to the new language. Sometimes I add bells and whistles and it's not porting attempting to be true to the original; but they offer small enough problems to get at least the syntax under my fingers and some of the larger ones can start to give me a sense of how I'll need to think should I try something serious.

And the first language I learned was... well BASIC... but it was on the VIC-20 & later C-64; but that still required a translation as the PDP-11 BASIC was rather different that was was on the Commodore machines.


I would like to mention http://exercism.io . It has unit tests written also


Yes, I've used exercism to broaden my knowledge and I've recommended the site to friends and colleagues who wanted to learn programming.

You mentioned tests: on exercism you don't write unit tests by yourself, the tests are only for you to check your solution. It certainly helps to see how tests can be written in any language, but you aren't forced into a strict TDD style.

The best feature on exercism for me is to be able to see the other solutions and learn from them.


In HR you can see other solutions as well


Yes, great option.

One thing I like to have to write tests is actually practicing writing tests :)


For Clojure I'd recommend ... http://www.4clojure.com/

Follow some of the top-code-golfers, get all the tests passing, and then marvel at how concise other people were able to make their solutions. Fun and educational.

Edit: bonus, got nerdsniped.. Clojure solution - https://gist.github.com/minikomi/4e42de3643118b5381c4d7e70a1...


Great article, thanks!

I'm not an expert Alchemist by any means, but whenever I see a `cond`, I try to see if it can be refactored out using pattern matching (after I was picked up on the same thing during an interview!)

   defp formatted_hour("AM", "12"),  do: "00"
   defp formatted_hour("AM", hours), do: hours
   defp formatted_hour("PM", "12"),  do: "12"
   defp formatted_hour("PM", hours), do: 12 + String.to_integer(hours)


I agree though one thing I would caution is it is good practice to always return the same type from a function even though it is an untyped language. The whole thing can be boiled down even more if pattern matching is used in parsing the initial string.

  def convert(<<h::bytes-size(2)>> <> ":" <>
              <<m::bytes-size(2)>> <> ":" <>
              <<s::bytes-size(2)>> <> <<period::bytes-size(2)>>) do
   "#{formatted_hour(h,period)}:#{m}:#{s}"
  end

  defp formatted_hour(hours,"PM"), do: "#{String.to_integer(hours) + 12}"
  defp formatted_hour("12","AM"), do: "00"
  defp formatted_hour(hours, "AM"), do: hours


Good point! If you're going to pattern match in the initial string then who even needs the second function?

    def convert("12:" <> <<m::bytes-size(2)>> <> ":" <> <<s::bytes-size(2)>> <> "AM") do
      "00:#{m}:#{s}"
    end

    def convert(<<h::bytes-size(2)>> <> ":" <> <<m::bytes-size(2)>> <> ":" <> <<s::bytes-size(2)>> <> "PM") do
      h = 12 + String.to_integer(h)
      "#{h}:#{m}:#{s}"
    end

    def convert(<<h::bytes-size(2)>> <> ":" <> <<m::bytes-size(2)>> <> ":" <> <<s::bytes-size(2)>> <> "AM") do
      "#{h}:#{m}:#{s}"
    end

Whether that's an improvement or not is another matter :)


Crazy stuff! :D

I'm wondering how our future-self would feel about such cleverness haha


I really liked this:

    "#{String.to_integer(hours) + 12}"
Used it now refactoring the code, many thanks for your suggestion!


I personally like recursive pattern matching

    defp formatted_hour("AM", hours), do: rem(hours, 12)
    defp formatted_hour("PM", hours), do: 12 + formatted_hour("AM", hours)


Nice!


Pattern matching is awesome and we should make use of it whenever appropriate, but not every situation is appropriate. For instance, if your formatted_hour functions were larger, or shared some amount of code between them, then cond might be a great option instead. Or case, or even the dreaded if statement. As a community, sometimes we overuse our cool special features just because we have them! Personally, I like the case statement as a middle ground for lots of scenarios. You still get pattern matching and it's pretty readable.


If the formatted_hour functions were larger or shared some amount of code, I wouldn't have suggested it ;)


Awesome! Many thanks for the tip. I'll refactor the code :)


I am a fan of http://www.rubykoans.com for Ruby. I am thinking about developing something similar using the Go playground for that language, and maybe an alternative for Rust.

Where I'd want to stretch it is some data structure and algorithm exercises, maybe even some design patterns. I'd love to be able to have a common environment where I can start to learn any one of multiple languages using similar exercises.


I would love something like that for Go. Just recently completed Python Koans and it was a good way to get into TDD.


for me, when I'm learning some new language or tech I start off with whatever basic info / tutorials that are available, play around with a few mini projects (like algorithms), but the most important thing, LET OTHER PEOPLE SEE YOUR CODE, for me that often involved trying to answer questions on stackoverflow and posting on codereview, for instance when I was learning ramda I posted a simple solution for fizzbuzz - https://codereview.stackexchange.com/questions/108449/fizzbu... for review and followed up on other peoples variations and it helped a lot.

when I thought I was too rusty on regex I went and tried to answer as many regex questions on stackoverflow

The great thing about stackoverflow is it presents real world problems that are often not straightforward. Even if you can't solve it, someone else more than likely will and you will have an "aha!"


So his approach is to go through hackerrank exercises to learn the language.

Anyone familiar with hackerrank able to comment on that vs say project Euler?


I would say that Hacker Rank helps with learning syntax of a language. I'm not sure if it helps greatly with learning how to implement framework type ideas or large programs.

Hacker Rank is best at teaching algorithms & problem solving. I did a couple the other day & at first I thought they looked difficult. After breaking them down & thinking about them, they surprisingly weren't all that hard.


The very definition of software :-)


The approach is actually learn enough about the language (through docs or a book) and practice such knowledge solving code challenges and writing your on tests first to get exposed for a more real environment.


Last time I tried hackerrank i wasn't impressed - the problem specification was lacking, input/output wasn't defined well enough. Quality varied wildly between problems.


I'm mildly familiar with both. I'm of the opinion that hackerrank would be better for learning a language, whereas Euler might be better for math problem solving.


I don't practice nor learn languages. I prefer concepts. I get "the book", skip the very first chapters that only talk about syntax, go straight for the unique features that make the language interesting (for a Clojure book, I'd go straight to protocols, agents, etc.), wrap my head around them and then maybe skim a popular repo hoping to read some idiomatic code.


Semi-OT, but I really want to steal whatever slick CSS you used to get that full page load then slam-in sidebar.


Here is a link to the actual CSS used on the blog post. https://github.com/ericdouglas/ericdouglas.github.io/blob/ma...

I'm gonna try pointing to the relevant CSS, but be warned, I am not a CSS wizard. I am also probably not a smart man, posting about CSS on HN while not being a wizard.

The relevant classes seem to be .sidebar, .sidebar-toggle, .motion-element, and .posts-expand, the last of which seems to control the transforms and durations. This is where my knowledge breaks down, since I'm not sure how they .sidebar or .motion-element trigger .posts-expand or any of the other animation CSS. Hopefully someone can help fill in the rest! ¯\_(ツ)_/¯



Three quarters OT, but I really don't. Yet another ill-informed, misguided piece of flashy form before content. I have given the text a miss. I generally do if it can't be arsed to show itself without a load of js trickery.


Apparently it's this theme: https://github.com/iissnan/hexo-theme-next


How hard is it to design your page without javascript needing to be enabled?

I now can't be bothered to see what you have to say. It is not worth my while.


That 'reveal' is definitely overkill - in a world where shaving off 10s of milliseconds in load time helps engagement, adding 100s of milliseconds of unnecessary pause before content does seem a little silly.

That said, 'has javascript' is a reasonable assumption for most websites these days. Most people outside the HackerNews echo chamber wouldn't dream of turning it off, but then I suppose this blog is aimed at the HackerNews audience (among others).


Thanks for your comment. I'll fix this.


Just changed the blog theme - it now works perfectly with JS disabled - serious, huge thanks for telling me this, I wasn't aware of that issue.


Many thanks for your comment. You are totally right.

This is a theme from the Hexo platform I use.

I'll probably create a theme to address this and other issues.


> Why algorithms?

> Because this kind of problem is an interesting way to put yourself searching all the API of the language in order to solve the challenge in the more elegant/concise way you currently can.

Bullcrap. APIs are either going to be irrelevant for solving an algorithm, or will simply do the job for you. "Implementing an algorithm" usually means writing it from scratch using simple data structures, primitives and basic flow control constructs.


I agree with you.

But I believe that solving this kind of challenges forces one in a good way to know more about what the language has to offer, while keeping motivated to learn its constructs before being able to create real apps.

The goal is practicing a new language.


I'm using the [cryptopals challenges](https://cryptopals.com/) to learn java ATM, seems like a good approach because they pretty quickly force you to do stuff that expose important parts of the language ("how do I get bytes out of a string?" "how do I do i/o?" "how do I xor two strings?" "how do I find a crypto library and use it?")

I think this kind of thing is more useful than hackerrank or euler-style problems, at least if you're learning a language in a paradigm you already know? If you can hack together a binary search in one functional language you can probably do it in another one pretty easily. Though might be more challenging moving from one paradigm to another.


It's important to be able to look at a problem and think "i bet I could find a function in the standard library that could help me solve this problem" or "I should just solve this from scratch with the basic functions I know, like map/filter/reduce/etc. So I disagree somewhat here.


Yeah, that's the point: "i bet I could find a function in the standard library that could help me solve this problem"


Yeah, in my opinion that's an important skill to have when learning a language. I already know how to write quicksort, writing it in Elixir will give me some sense of understanding of the language, but knowing how to find it in the standard library will make me more efficent of a programmer in Elixir.


Totally!




Consider applying for YC's W25 batch! Applications are open till Nov 12.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: