Wednesday, December 14, 2016

Hiatus, JSON

After another long hiatus due to work travel, I've started looking at content on Coursera and Udacity again. It seems like the breadth and depth of classes has expanded significantly in the past year -- with a much stronger monetization push in the "modular credential" model. Are people actually paying? It would appear that recent valuation puts Udacity's value at $1BN... which factors in significant growth expectation based on a rumored run rate of around $25MM.

Meanwhile, I worked on a small command-line utility for browsing JSON files recently, after getting frustrated by large JSON files that have no line breaks (taking a peek by calling head is not at all useful!).

Tuesday, May 24, 2016

New Coders Survey 2016

Brief analysis of the dataset from the Free Code Camp's New Coders Survey 2016:

TLDR; coding schools / bootcamps yield mixed results, but there are lots of folks interested in coding and lots of resources available beyond Udacity and Coursera.

Wednesday, March 30, 2016


I've decided to work through SICP. So far, its reputation as a classic text that has withstood the test of time seems well deserved. I've been targeting one sub-chapter a week, so factoring in an extra 50% for distractions and presumed difficulty of later chapters, it will take me the remainder of the year to finish.

This post was incredibly useful in terms of setting up a good vim / tmux working environment with Racket as the language of choice: It seems like emacs may have better indentation support, but learning a new editor still escapes me.

Saturday, January 30, 2016

Python Sudoku Solver

Inspired by Richard Bird's sudoku solution in Pearls of Functional Algorithm Design, I wrote a Python solver.

Since the rules of Sudoku involve row, column, and box-wise operations, it makes sense to have a solution for iterating over each of the three ways of dividing up a board. One possible solution is to write functions that all have custom logic for row, column, and box-wise operations (perhaps based on indexing or dictionary lookups, depending on the board implementation). Another, more functional solution is to write helper functions that transform the board, such that all functions can iterate over the board in the same way, regardless of whether it is a row, column, or box-wise operation. Ideally, the transformation functions are involutions, such that it is easy to return the board to its original arrangement (e.g. cols(cols(board)) == board). The latter is adopted in this solver:

Sunday, January 24, 2016

Explicit Type Annotations

In languages with good type inference, it's often quick and easy to omit type annotations. As a student prone to typos, I've found that this can lead to pernicious bugs when the function parameters are not obvious.

In this example ported to F# from Richard Bird's book, glue is supposed to take a digit and a tuple of (Expression, Values) and return a list of (Expression, Values) tuples. But there is a syntactic bug that cannot be inferred without more context (n.b. the list delimiter in F# is a semi-colon rather than comma):

type Digit = int
type Factor = Digit list
type Term = Factor list
type Expression = Term list
type Values = (Digit * Digit * Digit * Digit)

let glue x ((xs :: xss) :: xsss, (k, f, t, e)) =
        [(((x :: xs) :: xss) :: xsss, (10 * k, k * x + f, t, e)),
         (([x] :: xs :: xss) :: xsss, (10, x, f * t, e)),
         ([[x]] :: (xs :: xss) :: xsss, (10, x, 1, f * t + e))]

In an IDE, the type checker makes the error obvious once annotations are added. Editing for the correct list delimiters, glue is defined as:

let glue' (x: Digit) (ev: Expression * Values) : (Expression * Valueslist =
    match x, ev with
    | x, ((xs :: xss) :: xsss, (k, f, t, e)) ->
        [(((x :: xs) :: xss) :: xsss, (10 * k, k * x + f, t, e));
         (([x] :: xs :: xss) :: xsss, (10, x, f * t, e));
         ([[x]] :: (xs :: xss) :: xsss, (10, x, 1, f * t + e))]

Just another reminder that "explicit is better than implicit".