Joe Yates' Blog

Programming and DevOps

Trying Flow

I’m interested in the possibility of running type checks on Javascript code.

Proponents of type checking believe that bugs can be avoided by indicating the intended type (i.e. String, Number) of values (variables, functions and classes), opponents say it adds work but doesn’t significantly reduce bugginess.

I read through the intro to Typescript and it certainly seems like a lot of work.

An alternative is Facebook’s flow, it allows gradual typing - you add only as many type annotations as you want. Here, I’m giving it a spin by creating flow-hello - a “Hello World!” Example.

Installation

The type checking system is written in OCaml, and you need to install a binary or compile from source.

I opted to use npm to install the binary globally:

1
$ sudo npm install flow-bin --global

Project setup

Configure flow:

1
$ flow init

A Bug

Here’s a Javascript with a bug:

File: src/01-buggy.js
1
2
3
4
5
6
function logLength(x) {
  console.log(x.length);
}

logLength("Hello");
logLength(1);

This code logs undefined when the number 1 is passed to the function logLength, as 1 does not have a length attribute:

1
2
3
$ node src/01-buggy.js
5
undefined

As is, flow does not analyze the file:

1
2
$ flow check
Found 0 errors

Activate flow

Flow is activated by adding @flow to the first comment in any file:

File: src/02-with-flow.js
1
2
3
4
5
6
7
8
/* @flow */

function logLength(x) {
  console.log(x.length);
}

logLength("Hello");
logLength(1);

1
2
3
4
5
6
7
8
$ flow check
src/02-with-flow.js:3
3:   console.log(x.length);
                   ^^^^^^ property 'length'. Property not found in
3:   console.log(x.length);
                 ^ Number

Found 1 error

That’s good, as it explains how we get undefined in the output, but it’s not clear that this happens due to the second invocation of the function.

Annotate function parameters

Now, let’s indicate the intended type of the x parameter so that calls with parameters of the wrong type will be pointed out.

File: src/03-parameter-annotations.js
1
2
3
4
5
6
7
/* @flow */
function logLength(x: string) {
  console.log(x.length);
}

logLength("Hello");
logLength(1);

As flow check checks all the .js files it finds, I’ll run pass the file contents to flow via stdin:

1
2
3
4
5
6
7
8
9
10
$ flow check-contents < src/03-parameter-annotations.js
7: logLength(1);
   ^^^^^^^^^^^^ function call
7: logLength(1);
             ^ number. This type is incompatible with
2: function logLength(x: string) {
                         ^^^^^^ string


Found 1 error

That’s good - we know which call caused the problem.

Stripping type annotations with Babel

Unfortunately, we can no longer simply run the code:

1
2
3
4
5
$ node src/03-parameter-annotations.js
function logLength(x: string) {
                    ^
SyntaxError: Unexpected token :
...

We can use Babel to remove type annotations when we want to run the code.

Setting up Babel requires a bit of work:

File: package.json
1
2
3
4
5
{
  "scripts": {
    "babel": "babel ..."
  }
}

1
2
3
4
$ npm install --save-dev babel-cli
...
$ npm install --save-dev babel-plugin-transform-flow-strip-types
...
File: .babelrc
1
2
3
{
  "plugins": ["transform-flow-strip-types"]
}

Now we can run babel:

1
2
3
4
5
6
7
8
$ node_modules/.bin/babel src/03-parameter-annotations.js

function logLength(x) {
  console.log(x.length);
}

logLength("Hello");
logLength(1);

We get normal Javascript as output.

Conclusion

So, I got what I wanted: help with figuring out an error cuased by calling a function with a parameter of the wrong type.

But, it’s truly a “Hello World!”, there is a whole type specification system yet to learn and try out.

I like the idea of being able to annotate just as much of my code as I like, so I think I’ll be using Flow on my next Javascript project.

Create a Mix Task for an Elixir Project

Mix tasks are helper tasks in Elixir projects.

In this post, I’ll create an empty project and a “Hello World!”

I can create a new project with

1
$ mix new mix_task_example

Now, inside the new mix_task_example project directory, running

1
$ mix help

shows which mix tasks are available and in this newly created project there are already more than 30.

Now I create the directory for tasks with

1
$ mkdir -p lib/mix/tasks

and create a file with the name of the task, e.g. mix_task_example.salute.ex with the following contents:

1
2
3
4
5
6
7
defmodule Mix.Tasks.MixTaskExample.Salute do
  use Mix.Task

  def run(_) do
    IO.puts "Hello World!"
  end
end

This far, the task is not yet available, I need to compile the project

1
mix compile

And now I can run it with

1
2
$ mix mix_task_example.salute
Hello World!

The task doesn’t show up in the listing with mix help. To make it show up I need to add @shortdoc

1
2
3
4
5
6
7
8
9
defmodule Mix.Tasks.MixTaskExample.Salute do
  use Mix.Task

  @shortdoc "Give a short salutation"

  def run(_) do
    IO.puts "Hello World!"
  end
end

If the tasks are part of a library, they will be available to project that include it as a dependency, so it’s important to use the library name (e.g. MixTaskExample) in the module name in order to keep tasks in a collective namesapce.

As a final touch, let’s accept a parameter

1
2
3
4
5
6
7
8
9
defmodule Mix.Tasks.MixTaskExample.Salute do
  use Mix.Task

  @shortdoc "Give a short salutation"

  def run(name) do
    IO.puts "Hello #{name}!"
  end
end
1
2
3
mix compile
mix mix_task_example.salute Joe
Hello Joe!

A working mix task!

The code for this example can be found at https://github.com/joeyates/mix_task_example

How to Forward Blocks in Ruby

TL;DR

Use Proc.new

Calling Enumerators - normal use

You’re writing some code which calls an Enumerator - a function that makes repeated calls to the block of code that you provide.

1
2
3
4
5
6
def yield_me_2_things
  yield 'Thing 1'
  yield 'Thing 2'
end

yield_me_2_things { |x| puts x }

This will print:

1
2
Thing 1
Thing 2

The values are supplied by yield_me_2_things and the printing is done in the block, { |x| puts }, that is passed to that method.

Generalize

I can now make a generalized method, to handle any number of things:

1
2
3
4
5
6
7
8
def yield_me_n_things(n)
  1.upto(n) do |i|
    thing = "Thing #{i}"
    yield thing
  end
end

yield_me_n_things(2) { |x| puts x }

…the output is the same.

An alternative: use a block

I could equally have implemented the method using a &block parameter - for the caller, it makes no difference:

1
2
3
4
5
6
7
8
def call_this_block_with_n_things(n, &block)
  1.upto(n) do |i|
    thing = "Thing #{i}"
    block.call thing
  end
end

call_this_block_with_n_things(2) { |x| puts x }

…the output is the same.

The problem

What if I want one Enumerator to call another?

What if I want to keep the specific version (yield_me_2_things) but just make it call the generalized method?

1
2
3
4
5
6
7
8
9
10
11
12
13
def enumerate_n_things(n) # How do I receive the block?
  1.upto(n) do |i|
    thing = "Thing #{i}"
    # How do I call the block?
  end
end

def enumerate_2_things
  enumerate_n_things(2) # How do I forward the block?
end

enumerate_2_things { |x| puts x }
enumerate_2_things(2) { |x| puts x }

How should I write the two methods, while keeping both usable indipendently?

Attempt 1: Forward using yield

With yield, you don’t explicitly receive the block, you just call it. Does that work across two levels? I.e., does the block get passed to method I call?

1
2
3
4
5
6
7
8
9
10
11
12
def enumerate_n_things(n)
  1.upto(n) do |i|
    thing = "Thing #{i}"
    yield thing
  end
end

def enumerate_2_things
  enumerate_n_things(2)
end

enumerate_2_things { |x| puts x }

No, doesn’t work, enumerate_n_things doesn’t receive a block.

I get this error:

1
no block given (yield) (LocalJumpError)

Attempt 2: Forward using a block

1
2
3
4
5
6
7
8
9
10
11
12
def enumerate_n_things(n, block) # Note: no '&'
  1.upto(n) do |i|
    thing = "Thing #{i}"
    block.call thing
  end
end

def enumerate_2_things(&block)
  enumerate_n_things(2, block)
end

enumerate_2_things { |x| puts x }

Prints:

1
2
Thing 1
Thing 2

But we can no longer pass a block to the generalized method:

1
enumerate_n_things(2) { |x| puts x }

enumerate_n_things now expects the block as a normal parameter.

I get this error:

1
wrong number of arguments (1 for 2)

Solution: Proc.new

1
2
3
4
5
6
7
8
9
10
11
12
13
def enumerate_n_things(n, block = Proc.new)
  1.upto(n) do |i|
    thing = "Thing #{i}"
    block.call thing
  end
end

def enumerate_2_things(block = Proc.new)
  enumerate_n_things(2, block)
end

enumerate_2_things { |x| puts x }
enumerate_n_things(2) { |x| puts x }

Both calls now work!

Proc.new transforms any block passed to a method into a Proc. If we use that as the default value for a block parameter we can call methods directly with blocks, or forward blocks between enumerators.

Instant Sinatra Starter

I was asked to write a book about Sinatra, to be published by Packt Publishing.

Instant Sinatra Starter

The book is called “Instant Sinatra Starter” and is part of Packtpub’s Instant series.

Although the book is very short - the final version is 48 pages - it took about six months from initial planning to publication.

My target audience is people who have a little programming experience, so it doesn’t aim to teach you programming in general, or Ruby specifically.

The main section of the book follows the steps you need to develop an address book application.

The topics covered are:

  • Sinatra setup,
  • Templating (using Slim),
  • Getting an app online using Heroku,
  • GET and POST requests,
  • Integration testing,
  • Database access.

The code from the book is available on GitHub.

My Everyday Find Command

When I’m searching for files, I use this function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# f - everyday find
# usage:
#   f filename_fragment [path]
# skips whatever you list in _exclude_matches
_exclude_matches=(bundle .git *.pyc)
_excludes=''
for _match in $_exclude_matches; do
  _excludes="${_excludes}-name '$_match' -prune -o "
done

eval "
function my_everyday_find() {
  find \$2 \
    $_excludes \
    -name \"*\$1*\"    \
    -print;
}
"
unset _exclude_matches _excludes _match
alias f=my_everyday_find

It searches for files and directories with partial matches of the first parameter:

1
2
$ f 26
./db/migrate/20121003094826_add_foo_to_bar.rb

If I supply a second parameter, it is taken as the directory to search in:

1
2
3
$ f 26 ..
../api/db/migrate/20121003094826_add_foo_to_bar.rb
../redmine/db/migrate/20091017212644_add_missing_indexes_to_messages.rb

Ruby Bareword Assignment and Method Calls With Implicit Self

Problem

If I do this:

Problem - problem.rb
1
2
puts foo
foo = 3

there is always the doubt whether I’m accessing a local variable, or calling methods foo and foo=.

TL;DR

When you want to call an instance’s own methods, use self:

TL;DR - tldr.rb
1
2
self.foo             # Calls foo
self.foo = 'bar'     # Calls foo=

HTML History API

The HTML5 history API allows AJAX-based sites to avoid "breaking the back button". Every time you update the page, you store the new content is the window.history object. When the user presses the back button, you retrieve the current item from window.history and update the page with it.

Overriding the Insertion Operator for C++ Template Classes

Dump an Active Record object to Standard Out - dump_active_record_object.cpp
1
2
Person person( 123 );
std::cout << person << endl;

While working on my C++ ActiveRecord implementation, I had a few problems implementing the insertion operator for the main ActiveRecord::Base class.

The class ActiveRecord::Base class is a template class, and the problem was how to correctly declare the operator.

At the time I was unable to find examples on the Internet, so I thought I’d provide my own.