Exercism is a language-learning platform with an element of mentorship. Unlike Codewars, HackerRank and LeetCode etc., users have the option of submitting code for human review, leading to a strong focus on best practices and improvements via iterations. Notwithstanding, the basis of complete submissions is still the clearing of test cases.

Currently, my primary motivation for using Exercism is to understand (on a broad, basic level) how similar tasks are accomplished across different languages, and the offerings of each of these languages. To-date, I have completed the core exercises in the Bash, C++, Julia, R, and Scala tracks, and working my way through the C, Dart, Go, and Haskell tracks. I am also mentoring on the Python track.

My Exercism profile can be found here.

1. Abstraction and performance

Besides syntax differences, it is also almost immediately obvious that languages differ greatly in terms of the built-in functionalities. While lower levels of abstraction (from machine code) almost certainly means higher performance, the opposite is not always true.

Languages such as Python and Scala offer a plethora of built in functions or methods to iterate through or manipulate arrays, often leading to very concise, expressive and readable code. My implementation of Hamming distance method in Scala is as follows:

object Hamming {

  def distance(s1: String, s2: String): Option[Int] =
    if (s1.length != s2.length) None
    else Some(s1.zip(s2).count(s => s._1 != s._2))
}

In C, iterating through arrays are often accomplished using pointers and loops. My implementation of Hamming distance function in C is as follows:

#include <string.h>
#include <stdint.h>

int compute(const char *lhs, const char *rhs)
{
    if (!lhs || !rhs || strlen(lhs) != strlen(rhs))
    {
        return -1;
    }

    int hamming = 0;
    for (; *lhs != '\0'; lhs++, rhs++)
    {
        if (*lhs != *rhs)
        {
            hamming++;
        }
    }

    return hamming;
}

Python and Scala source codes are compiled to Python and Java byte codes respectively, and then executed by virtual machines. Unsurprisingly, neither of these languages come close to the performance of C – C is compiled to assembly code which is then assembled into machine code.

It is worth noting that the built-in modules of higher-level languages (like Python and R) are often written in highly performant lower-level languages like C or Fortran. Such languages also often have libraries written in or interfacing with lower-level languages and their libraries. For example, NumPy (a library for Python) is written with both Python and C.

Despite being dynamically typed (with optional type declarations) and having a rather high level of abstraction (similar to Python and R), Julia is compiled just-in-time into machine code by an LLVM compiler. As a result, well-written Julia is extremely performant, almost comparable to C code. My implementation of Hamming distance function in Julia is as follows:

function distance(a::String, b::String)
    length(a) == length(b) || throw(ArgumentError("Different strand lengths"))
    sum(split(a, "") .!= split(b, ""))
end

Another language with a very high level of abstraction is Haskell. However, the Glasgow Haskell Compiler compiles Haskell to C ultimately resulting in performance close to that of C. My implementation of Hamming distance function in Haskell is as follows:

module Hamming (distance) where

distance :: String -> String -> Maybe Int
distance xs ys = 
    if length xs == length ys
        then Just . length . filter id $ zipWith (/=) xs ys
        else Nothing

2. Language focus

Based on mentor feedback, it is also apparent that the focus or usage of each language is different. Notwithstanding, readability and simplicity are recurring themes.

There is a great emphasis on performance when writing C++ or C, and this is not surprising since these languages are used for systems or embedded programming, or performance-critical applications. Feedback received from mentors generally lead towards writing performant but readable code conforming to certain code style standards. Similarly for Julia, mentors often comment on performance or optimization.

Given that Scala is both object-oriented and functional, the emphasis is shifted towards writing functional expressions within an object-oriented paradigm. To-date, I find writing Scala code to be the most enjoyable.

For Python, I generally focus on getting students to write Pythonic code, and to follow the Python style guide. List comprehensions and using built-in methods or functions are recurring themes. After all, Python code is meant to be clear, concise and maintainable because of its simplicity. My implementation of Hamming distance function in Python is as follows:

def distance(strand_a, strand_b):
    if len(strand_a) != len(strand_b):
        raise ValueError('Length of strands not equal')
    return sum(a != b for a, b in zip(strand_a, strand_b))

Languages like Bash and R have different domains, and focus is more on scripting (properly) and vectorization respectively. My implementations of Hamming distance in Bash and R respectively are as follows:

#!/usr/bin/env bash

main () {
  # Error handling
  if (( $# != 2 ))
  then
    echo "Usage: hamming.sh <string1> <string2>"
    return 1
  elif (( ${#1} != ${#2} ))
  then
    echo "left and right strands must be of equal length"
    return 1
  fi
  
  # Calculating
  local hamming=0
  for (( i=0; i<${#1}; i++ )); do
    [[ "${1:i:1}" != "${2:i:1}" ]] && ((hamming++))
  done
  echo $hamming
  return 0
}

main "$@"
hamming <- function(strand1, strand2) {
  if (nchar(strand1) != nchar(strand2)) {
    stop("Strings are of different length!")
  }
  sum(strsplit(strand1, split = "")[[1]] != strsplit(strand2, split = "")[[1]])
}

3. Mentoring

Mentoring is another great aspect of Exercism, where one takes the role of a reviewer rather than the student. To put it succinctly, code review fleshes out gaps in reviewers’ understanding, especially when responding to complicated queries. Contributing back to the Exercism platform via mentoring also a great way to share working knowledge, and rounds out the Exercism experience.

Students are offered the option of leaving testimonials for their mentors, and it is heartening to receive testimonials like these:

Exercism testimonials

4. Other contributions

It is also possible to contribute to Exercism as a track maintainer, or create pull requests from the Exercism repository. I do not have experience in either – perhaps I might try either/both of these in the future.