Source Diving in Other Languages

Written by on Jan 25 2017

I recently wrote about exploring source code in Elixir. The post looked at Elixir’s List.insert_at/3 function.

Exploring how list insertion gets handled revealed fundamental concepts of the language. Recursion and pattern matching are the keys used to break the problem down. This is common in most functional languages.

In this post I’m going to compare this exploration of source code to other popular languages.

Ruby

Let’s find a comparable type of operation in Ruby. (Note. I like Ruby a lot, it’s paid the mortgage for a while)

Array.push is a similar kind of operation. It will add an item(s) to the end of an existing array (list type object).

a = [ "a", "b", "c" ]
a.push("d")
#=> ["a", "b", "c", "d"]

Pretty straight forward, adds “d” onto the end. Let’s take a look at the source code.

static VALUE
rb_ary_push_m(int argc, VALUE *argv, VALUE ary)
{
return rb_ary_cat(ary, argv, argc);
}

Don’t know C? No problem, it’s still clear what’s happening. The rb_ary_push_m function wraps a call to the rb_ary_cat function. The workings of the inner function though are opaque without exploration. To do so takes us a long way from the Ruby we are writing.

There’s nothing to further your understanding of Ruby. No insight into how the language authors structure their code. You won’t read this code and get inspiration on how to tackle similar issues.

PHP

Focusing on adding to an array we can use array_push, one of its Array functions.

$stack = array("orange", "banana");
array_push($stack, "apple");
/**
* Array
* (
*    [0] => orange
*    [1] => banana
*    [2] => apple
* )
**/

PHP is another language written in C. The source code reads,


/* {{{ proto int array_push(array stack, mixed var [, mixed ...])
  Pushes elements onto the end of the array */
PHP_FUNCTION(array_push)
{
zval   *args, /* Function arguments array */
  *stack, /* Input array */
   new_var; /* Variable to be pushed */
int i, /* Loop counter */
argc; /* Number of function arguments */

ZEND_PARSE_PARAMETERS_START(2, -1)
Z_PARAM_ARRAY_EX(stack, 0, 1)
Z_PARAM_VARIADIC('+', args, argc)
ZEND_PARSE_PARAMETERS_END();

/* For each subsequent argument, make it a reference, increase refcount, and add it to the end of the array */
for (i = 0; i < argc; i++) {
ZVAL_COPY(&new_var, &args[i]);

if (zend_hash_next_index_insert(Z_ARRVAL_P(stack), &new_var) == NULL) {
if (Z_REFCOUNTED(new_var)) Z_DELREF(new_var);
php_error_docref(NULL, E_WARNING, "Cannot add element to the array as the next element is already occupied");
RETURN_FALSE;
}
}

/* Clean up and return the number of values in the stack */
RETVAL_LONG(zend_hash_num_elements(Z_ARRVAL_P(stack)));
}
/* }}} */

Oof. There’s a lot to parse. Again, long story short, nothing there reveals anything about the nature of PHP.

What’s my point?

You can solve almost any problem in almost any language. Some will say none are better than another. Some will fight you to the death to prove they have chosen the One True language.

I’ve found reading source code without a “Level 9 Neckbeard Certification” to be amazing and allows for,

  • Insight into the design of the language.

  • Insight into how the authors are writing their code.

  • Hints at organization techniques.

  • A valuable reminder of how effective simple code can be.

When code is outside the ‘black box’ it’s easier to reason about. I’ll take that all day long. Take a look at Elixir, take a look at its source. Careful though, it’s addictive.

Meet
Adam

Hi I'm Adam,

I wrote the article you're reading... Adam is a father of two sons and has a beautiful wife. He's British, runs marathons, avid crossfitter, & vegan. Yes he's a better human being than you are.

Get Blog Updates