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.
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.
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.
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.
If you wanted it to build a product you’d find a way to get time to work on it. If you really wanted to start that new hobby you’d sacrifice something to find the time and money to do it.
I'll define a "Wannabe Entrepreneur" as someone who has never made money from their businesses. Here are the different types of wannabes.
In the past few years I've built go-carts, built a 200+ sq ft workshop, written several eBooks. How do I create a life where I have time to work on side projects?
Receive 5 Software projects mistakes we have made over the years and how to avoid them.