All Posts (63)

You are Orange

"People who are ORANGE are often spontaneous and flamboyant. They need a lot of variety and freedom. They take pride in being highly skilled and in being able to do several things at a time. They enjoy "hands on" work and often are good in a crisis. They are risk takes, seek challenges and are optimistic."

From the True Colors Personality Test.

Read more…

Don't just "make something". Rather, "make good".

Every so often on Hacker News, there is an article calling upon everyone to "make something". There is the Maker Culture (Wikipedia) and Maker Faire and Maker Spaces. And the mantra is "just make something". Anything. It does't matter. Just Make Something!

I don't agree with this philosophy of life at all. It seems so shallow. A better philosophy is the Catholic (and Aristotelian) one given by Joseph Pieper in his book The Four Cardinal Virtues ( that the ultimate goal of a human being is to "love the good and accomplish it".

How to do that? Here are some examples from a Guide for Confirmation Sponsors that I received today from my parish:

  • Spiritual Works of Mercy
    • Be the first to bring peace; never hold a grudge.
    • Encourage those who are discouraged by difficulties in trials.
    • Give your sympathetic understanding to your friends and family when they are in sorrow
    • Pray for all the people that you know whether they are living or dead.
  • Corporal Works of Mercy
    • Freely give to charitable organizations.
    • Give useful clothing to the poor.
    • Help with babysitting.
    • Attend funerals.

I would rather do any of the above works of mercy than make a pinwheel operated by a DC motor controlled by a Raspberry Pi computer. 

Read more…

Fr. Larry's homily

Fr. Larry gave a nice homily last Sunday on the Feast of the Holy Family. Main point was that the family is all about:
  • Love: Giving of oneself.
  • Prayer: Going to the Source to fill oneself up with love to give to others.
  • Sacrifice: Uniting love and prayer.
  • Forgiveness: Essential for marriage.
Read more…

Photo Storage Strategy

My wife and I are taking more photos these days, and like most people, we now need a "photo storage strategy" - a solution for managing all of the digital photos we take. We have a couple of thousand old photos, and new photos coming in via our iPhones and our digital camera.

Our criteria for the system were:

  1. Easy-to-use photo management software for the wife.
  2. Large storage capacity (the 60GB on the Macbook Air was filling up fast).
  3. Cloud backup.

The solution we came up with was:

  1. iPhoto. Wife was already using it.
  2. 1TB external USB drive that we already have.
  3. CrashPlan $6/mo cloud backup.

We considered various alternatives.

  1. Alternatives to iPhoto: Picasa. But people say it's not so easy to use. Plus my wife already knows iPhoto, although she finds the photo-book functionality annoying to use. I told her to just use albums instead of photo-books.
  2. Local Storage: For network drives like Synology ($500) or Zyxel ($250) I'd rather not pay. A nice thing about the Synology is that you can do headless backups (no computer required) - I'm not sure about the Zyxel. There's also the WD MyCloud ($150) but it has terrible reviews.
  3. Cloud Backup: Google Drive and Dropbox don't seem to work well with external USB drives. MS OneDrive says that they do work with external USB drives, but I don't trust it, given that Google Drive doesn't. So I'm left with CrashPlan and BackBlaze, which are pretty much on par with each other.

One cool thing I discovered about iPhoto is that when I sync our iPhones and camera with it over USB, it figures out which photos have already been imported, so it imports only the new ones. Nice!

Read more…

Apple Maps GPS is way better than Google Maps GPS


* It gives you the information you need (turn arrow and distance to the turn) in a high-contrast, large font. With Google Maps, I glance down and I can hardly read the information – it's dangerous.

* The street lines are thicker and contrast strongly against the background (unlike Google Maps, which is white on cream).

* The view is tilted, like a regular GPS, unlike Google Maps, which is straight down.

Read more…

Vine video as the sonnet of this generation

I have been wondering what is the attraction of Vine videos - those six-second looping videos.

Then today I was reading about the sonnet (16-line poems), and how popular they were in England in the 16th century. Maybe Vine is the sonnet of this generation?

Consider the following description of the sonnet - note that it has some similarity to a Vine video with its 6-second constraint:

Very often these love poems were addressed to a small circle of congenial spirits—fellow poets, wits, ladies of fashion—whom the poet wished to amuse. The way to impress this company was to exhibit special ingenuity in devising new variations on the old theme or in polishing one's work to an impressively high gloss. The reproach that such poetry is “insincere” would have astonished any Elizabethan. The rules were there with all the weighty authority of tradition behind them, and they were there to be followed. To depart from them would be as incomprehensible as if a chess player were to propose a change of rules to his opponent in order that he “might express himself better”.

—Adventures in English Literature

Read more…

Programming by Equivalence

I would like to introduce a programming technique called “Programming by Equivalence”. You can't use it all the time, but when you can use it, it’s great.

Problem: You have an existing feature X, and you want to implement a similar feature Y.

Solution: For every line of code for X, create a line of code for Y.

The beauty of this technique is:

  1. You don't need to think much - just find each line of code for X and make an equivalent line of code for Y.
  2. You know when you are done: when every line of code for X has an equivalent line of code for Y.

Here is a script that can help you to do 1 and 2 above. Just tweak the variables in the script to match your own code. Suppose you have implemented Google +1 buttons in your codebase, and now you want to add LinkedIn buttons. Run the script, and you will get output like:

lib/XG_ConfigHelper.php::: return B()->getMainConfig('googlePlusOneEnabled') === '1';
lib/components/bundle/controllers/EntryController.php::: if (R('XG_ConfigHelper')->isGooglePlusOneEnabled()) {
lib/components/bundle/lib/EntryListService.php::: if (R('XG_ConfigHelper')->isGooglePlusOneEnabled()) {
lib/components/bundle/lib/MustacheTransformer.php::: ->socialButtons()->googlePlusOneButton($entry);
lib/mustache-templates/v1/bundle/article/list.mustache::: {{{googlePlusOneButtonHtml}}}
. . . . . . . . . .

Note that the script looks for the X string (in my case, googlePlusOne) and checks if a corresponding Y string exists. The script outputs any X lines that do not have corresponding Y lines.

Using this technique, the creation of feature Y becomes mechanical. You keep running the script, and keep implementing the lines that it finds. If there are any lines that are false-positives, you mark those lines in the script. When the script's output is empty, you're done.

Thus you can be quite confident that you have thoroughly implemented the new feature.

Read more…

Cool: LibaryThing tag cloud

This is cool - if you input all of the books you own into LibraryThing, you can get it to display a tag cloud of your interests. Here are mine. Catholicism, poetry, and programming pretty much sums it up.

Read more…

Studying the QuickDraw source code

According to the interview with Donald Knuth in the book Coders at Work, Bill Atkinson's work is "well-documented code with lots of pioneering graphics algorithms in it." Let's review his code together - I created this public code review of his QuickDraw code. Come and leave comments on it and let's learn together.

Read more…

Wow. Just yesterday I opened one of my favorite books, Revolution in the Valley, containing war stories about the creation of the Macintosh computer. I was reading all of the introductory matter carefully (the scans of an engineer's notebook) when I noticed that one of the pages contained signatures of several original members of the Mac team. Note in the accompanying photo the signatures of Woz, Bill Atkinson, Daniel Kottke, Caroline Rose, Andy Hertzfeld, Bud Tribble, and Susan Kare (with the ⌘ symbol).

This is really cool. It's funny to think that this is inside a book I bought for $12.99 from a used bookstore in Victoria BC several years ago.

Read more…

Literate Programming is a style of programming invented by Donald Knuth in which, instead of the usual style of embedding comments in code, you instead embed code in comments. The result is a long narrative of prose (describing how you are writing the code) with code snippets interspersed throughout.

This never caught on. Perhaps because programmers don't like writing documentation? However, I have noticed something interesting. Sophisticated programmers today write lengthy commit messages. It is an example set by the Linux kernel committers - check out their wonderfully descriptive commit messages. (I first learned about the high quality of Linux kernel commit messages from 5 Useful Tips For A Better Commit Message.)

It strikes me now - I wonder if commit messages are the new Literate Programming. It is said that programmers don't like writing documentation, but they seem to willingly put a lot of effort into writing long, descriptive commit messages. Here's an example of a meaty commit message from the Linux kernel:

commit d940878632e63d7f0c2af5e4ebfcf5135c48dcfb
Author: Jan Kara <>
Date:   Wed Jul 11 23:16:25 2012 +0200

    jbd: Fix assertion failure in commit code due to lacking transaction credits

    ext3 users of data=journal mode with blocksize < pagesize were occasionally
    hitting assertion failure in journal_commit_transaction() checking whether the
    transaction has at least as many credits reserved as buffers attached.  The
    core of the problem is that when a file gets truncated, buffers that still need
    checkpointing or that are attached to the committing transaction are left with
    buffer_mapped set. When this happens to buffers beyond i_size attached to a
    page stradding i_size, subsequent write extending the file will see these
    buffers and as they are mapped (but underlying blocks were freed) things go
    awry from here.

    The assertion failure just coincidentally (and in this case luckily as we would
    start corrupting filesystem) triggers due to journal_head not being properly
    cleaned up as well.

    Under some rare circumstances this bug could even hit data=ordered mode users.
    There the assertion won't trigger and we would end up corrupting the

    We fix the problem by unmapping buffers if possible (in lots of cases we just
    need a buffer attached to a transaction as a place holder but it must not be
    written out anyway). And in one case, we just have to bite the bullet and wait
    for transaction commit to finish.

    Reviewed-by: Josef Bacik <>
    Signed-off-by: Jan Kara <>
    (cherry picked from commit 09e05d4805e6c524c1af74e524e5d0528bb3fef3)
    Signed-off-by: Willy Tarreau <>

Reminiscent of Literate Programming, no?

Read more…

In Mustache templates, sometimes you just want to test if an array exists, without iterating over it. However, {{#myArray}}...{{/myArray}} will iterate over myArray. What if you just want to check if myArray exists?

Solution: {{#myArray.0}}...{{/myArray.0}}

This will operate on the first (i.e., 0th) element of myArray.

Read more…

Lisphp at Ning - Sample Code

Here is the Lisp that I have written as an experiment with Lisphp. It is probably not great Lisp code—I don't have prior experience with Lisp—so any suggestions for improvement are welcome. I encourage others to make their Lisphp code publicly available so that we can all learn. Another Lisphp example I have found is balrog.

This code is for rendering an activity feed (like a Facebook Wall). It takes a bunch of activity-item objects, processes them, then feeds them into a Mustache template. The processing step sets up variables for the Mustache template to use.

For new Lisp programmers, I recommend the use of an editor plugin that automatically indents your Lisp code. See my first Lisphp blog post for related recommendations.


;;; Top-level module for rendering an activity feed for the network.
;;; @param string title  the title for the activity section
;;; @param array feed-events  the feed-event objects, parsed from JSON
;;; @param integer excerpt-length  the length at which to excerpt activity items
;;; @param string like-type  the naming scheme for likes: like, promote, or favorite
;;; @param string network-name  the name of the network
;;; @param string network-url  the URL of the network
;;; @param string network-icon-url  48x48 network icon
;;; @return string  HTML for the network feed

(import 'lib/components/activity/lib/process-feed-events.lisp')
(import 'lib/components/activity/lib/add-type-specific-properties.lisp')

;;; Filters, caches, and processes the given network feed events.
;;; @param array feed-events  the feed-event objects
;;; @param array options  options: excerpt-length
;;; @return array  the feed-event objects after processing
(define (process-feed-events feed-events options)
        ;; Remove rolled-up feed events for now, until we implement handling
        ;; for them.
        (setf! feed-events (remove-rollup-feed-events feed-events))
        (setf! feed-events (add-basic-properties feed-events options))
        (setf! feed-events (add-type-specific-properties feed-events options)))

(setf! processed-feed-events
       (process-feed-events feed-events
                            (hash 'excerpt-length'   excerpt-length
                                  'like-type'        like-type
                                  'network-name'     network-name
                                  'network-url'      network-url
                                  'network-icon-url' network-icon-url)))

;; Send the feed-events into the Mustache template.
((-> B renderMustache)
   'title' title
   'feed-events' processed-feed-events))


;;; Functions for processing activity events.

(use floor)
(use xg_elapsed_time)

;;; Removes rolled-up feed events. This is a temporary measure until we
;;; implement handling of rollups.
(define (remove-rollup-feed-events feed-events)
        (filter (lambda (feed-event)
                  (not (array-get feed-event 'rollUpType')))

;;; Adds basic properties, such as humanReadableDate, to each of the feed events
(define (add-basic-properties feed-events options)
        (map (lambda (feed-event)
               (let* ([content-id (array-get feed-event 'event' 'properties' 'contentId')])
                 (arr feed-event
                      (hash (event-type feed-event) true
                            'humanReadableDate'     (human-readable-date feed-event)
                            'content'               (to-content-properties content-id (at options 'excerpt-length'))))))

;;; Returns the event type suffixed with "Type", e.g., createBlogPostLikeType.
(define (event-type feed-event)
        (. (array-get feed-event 'event' 'eventType') 'Type'))

;;; Returns a friendly date for the event.
(define (human-readable-date feed-event)
          ;; Prefix timestamp with @ so that strtotime will understand it
          (. '@' (floor (/ (array-get feed-event 'event' 'createdDate') 1000)))
          nil nil false))

Read more…

Lisphp at Ning: Custom functions

In my previous post, I mentioned that we are experimenting with Lisphp at Ning, and we have some custom functions that seem to be helpful:

  • import: imports a lisp file: (import 'foo/bar/baz.php')
  • php: runs a PHP function without having to import it: (php :htmlentities 'foo')
  • cons: prepends an item to an array: (cons 'strawberry' flavors)
  • hash: creates an array of key-value pairs: (hash 'key1' 'value1' 'key2' 'value2')
  • array-set: sets an item on a multidimensional array: $flavors['foo']['bar'] = 'baz' is (array-set flavors 'foo' 'bar' 'baz')
  • array-get: gets an item from a multidimensional array: $flavors['foo']['bar'] is (array-get flavors 'foo' 'bar')
  • arr: array_replace_recursive()
  • environment: this is the Lisp environment itself added as a variable, to allow you to check if a function exists: (exists-at? environment 'my-function')

Here is the code that we use to call Lisphp. Note that you have a choice of runFile() or runCode(); also note the custom functions. You may need to make some modifications to get this to run in your own environment:


 * Parses Lisphp files.
class XG_Lisp {

     * Executes a Lisp file using Lisphp.
     * @param string $path  the path to the lisp file
     * @param array $env  names and values to add to the environment;
     *                             see Lisphp_Environment
     * @return  the result
     * @see
    public function runFile($path, $env = []) {
        return $this->run(Lisphp_Program::load(NF_APP_BASE . '/' . $path), $env);

     * Executes Lisp code using Lisphp.
     * @param string $code  the Lisp code
     * @param array $env  names and values to add to the environment;
     *                             see Lisphp_Environment
     * @return  the result
    public function runCode($code, $env = []) {
        return $this->run(new Lisphp_Program($code), $env);

     * Executes a Lisp program using Lisphp.
     * @param Lisphp_Program $program  a Lisp program object
     * @param array $env  names and values to add to the environment;
     *                             see Lisphp_Environment
     * @return  the result
    protected function run($program, $env = []) {
        $environment = Lisphp_Environment::full();
        foreach ($env as $name => $value) {
            $environment[$name] = $value;
        $environment['B'] = B(); // XG_BaseService
        // Import a PHP file: (import 'lib/components/activity/lib/foo.lisp')
        $environment['import'] = new Lisphp_Runtime_PHPFunction(function ($path) use ($environment) {
            $program = Lisphp_Program::load(NF_APP_BASE . '/' . $path);
            return $program->execute($environment);
        // Prepends an element to a list
        $environment['cons'] = new Lisphp_Runtime_PHPFunction([$this, 'cons']);
        $environment['->$'] = new XG_Lisp_GetField;
        $environment['array-get'] = new Lisphp_Runtime_PHPFunction([$this, 'arrayGet']);
        $environment['array-set'] = new Lisphp_Runtime_PHPFunction([$this, 'arraySet']);
        $environment['hash'] = new Lisphp_Runtime_PHPFunction([$this, 'hash']);
        $environment['var_dump'] = new Lisphp_Runtime_PHPFunction('var_dump');
        $environment['arr'] = new Lisphp_Runtime_PHPFunction('array_replace_recursive');
        $environment['environment'] = $environment;
        return $program->execute($environment);

     * Prepends an element to a list.
     * @param mixed $item  the item to prepend
     * @param array|Lisphp_List $list  the list to prepend the item to
     * @return array|Lisphp_List  a new list
    public function cons($item, $list) {
        if (is_array($list)) {
            return array_merge([$item], $list);
        return new Lisphp_List(array_merge([$item], $list->getArrayCopy()));

     * Retrieves an item from a multidimensional array
     * @param array $array  the array to read from
     * @param string $key1  the first key
     * @param string $key2  the second key, etc.
     * @return mixed  the value at the given keys
    public function arrayGet() {
        $args = func_get_args();
        $result = array_shift($args);
        foreach ($args as $key) {
            if (!is_array($result)) {
                return null;
            if (!array_key_exists($key, $result)) {
                return null;
            $result = $result[$key];
        return $result;

     * Sets an item on a multidimensional array
     * @param array $array  the array to read from
     * @param string $key1  the first key
     * @param string $key2  the second key, etc.
     * @param string $value  the value to set
     * @return mixed  the new multidimensional array
    public function arraySet() {
        $args = func_get_args();
        $array = array_shift($args);
        $subtree = &$array;
        $value = array_pop($args);
        $lastKey = array_pop($args);
        foreach ($args as $key) {
            if (!array_key_exists($key, $subtree)) {
                $subtree[$key] = [];
            $subtree = &$subtree[$key];
        $subtree[$lastKey] = $value;
        return $array;

     * Converts a list into an array of key-value pairs.
     * @param string $key1  the first key
     * @param string $value1  the first value
     * @param string $key2  the second key
     * @param string $value2  the second value, etc.
     * @return array  the key-value pairs
    public function hash() {
        $args = func_get_args();
        $hash = [];
        for ($i = 0; $i < count($args); $i += 2) {
            $hash[$args[$i]] = $args[$i+1];
        return $hash;


Read more…

Lisphp at Ning - Introduction

At Ning, we are experimenting with Lisphp, which allows us to call Lisp from PHP and vice versa. It's like an oasis of functional programming in the midst of PHP.

There isn't much on the web on Lisphp, so I am writing some blog posts (in my Lisphp category) about my experiences with it.

First, some helpful resources:

You'll notice that Lisphp does not come with any documentation other than what is on the Github page. A list of all the functions is in the Environment.php file. Here are brief descriptions of what some of the functions do:

  • define - defines a function or global variable
  • let - sets local variables
  • let* - sets local variables - the definitions can refer to each other
  • setf! - sets a local variable in an "imperative" style: (setf! foo 5). For setting local variables, prefer let first, followed by let*, followed by setf!
  • lambda - creates an anonymous function
  • apply - applies a function to an array of arguments
  • list - creates a Lisphp list: (list) or (list 'a' 'b' 'c')
  • array - creates a PHP array: (array) or (array 'a' 'b' 'c')
  • do - executes code several times in a loop
  • car - returns the first item in a list: (car flavors)
  • cdr - returns the remaining items in the list (i.e., not the first one): (cdr flavors)
  • at - returns the value at the given key: (at flavors 'key')
  • set-at! - sets the value at the given key: (set-at! flavors 'key' 'value')
  • unset-at! - unsets the value at the given key: (unset-at! flavors 'key' 'value')
  • exists-at? - does isset() on the value at the given key: (exists-at? flavors 'key')
  • count - returns the number of items in the list: (count flavors)
  • map - applies a function to every item in a list
  • filter - filters out items from a list
  • fold - (aka "reduce") goes through a list to create a single value
  • if - if statement
  • cond - switch statement
  • = - ==
  • == - ===
  • !=, !==, <, >, <=, >=, +, -, /, *, %, not, and, or, nil, true, false
  • . - concatenates strings
  • isa? - returns whether the object is an instance of the given class: (isa? foo <ArrayObject>)
  • string - strval()
  • substring - substr()
  • string-upcase - strtoupper()
  • string-downcase - strtolower()

I'm not sure about the following - if you know, let me know:

  • eval
  • quote
  • symbol
  • macro
  • dict - I'm not exactly sure how this works. I made a replacement called "hash"—see below.

I also added the following custom functions - I'll give the code in my next blog post:

  • import: imports a lisp file: (import 'foo/bar/baz.php')
  • php: runs a PHP function without having to import it: (php :htmlentities 'foo')
  • cons: prepends an item to an array: (cons 'strawberry' flavors)
  • hash: creates an array of key-value pairs: (hash 'key1' 'value1' 'key2' 'value2')
  • array-set: sets an item on a multidimensional array: $flavors['foo']['bar'] = 'baz' is (array-set flavors 'foo' 'bar' 'baz')
  • array-get: gets an item from a multidimensional array: $flavors['foo']['bar'] is (array-get flavors 'foo' 'bar')
  • arr: array_replace_recursive()
  • environment: this is the Lisp environment itself added as a variable, to allow you to check if a function exists: (exists-at? environment 'my-function')

Finally, some tips:

  • See if your editor has a plugin that will automatically indent your Lisp code. For example, Sublime Text has a lispindent plugin that will indent your code whenever you press Enter; you can also press Command+I to re-indent the selected code.
  • Sometimes you may need to dive into the Lisphp code to fix things. This is a good opportunity to learn how Lisphp works, and to contribute back by submitting a pull requests. I submitted two pull requests and they were accepted immediately.
  • To import a constant: (use +XG_Model::PLAINTEXT+). Now you can reference +XG_Model::PLAINTEXT+.
Read more…

Sublime Text Window-Splitting Bliss

I'm trying out Sublime Text again, and I'm really missing how easy it is to split windows in jEdit. In jEdit, you just do:

  • Command+2 to split the window horizontally.
  • Command+3 to split the window vertically.
  • Command+0 to unsplit the window.

Well, it turns out you can do this in Sublime Text! First, install the Origami plugin. Then add the following keybindings:

    { "keys": ["super+0"], "command": "destroy_pane", "args": {"direction": "self"} },
    { "keys": ["super+2"], "command": "create_pane_with_cloned_file", "args": {"direction": "right"} },
    { "keys": ["super+3"], "command": "create_pane_with_cloned_file", "args": {"direction": "down"} }

Now you can split your windows super-easily. Origami's default keybindings are pretty hard to remember and use, but the above is all you need.

Read more…

How I am writing commit messages now

I am trying a new way of writing commit messages based on Thoughtbot's 5 Useful Tips For A Better Commit Message. Basically my commit messages now look like this:

[Ticket number]: Summary: 1-line description: what and why

Problem: ...

Solution: ...

Side-effects: ...


[BDZL-4222] Summary: Digest's link "To control which emails you receive" is incorrect

Problem: The digest core has a link to /profiles/profile/emailSettings. However, this link is the old Bazel URL; in Bedazzle, the URL has changed to /main/profilesettings/email.

Solution: Make /profiles/profile/emailSettings redirect to /main/profilesettings/email.

Side effects: /profiles/profile/emailSettings responds with a 302 to /main/profilesettings/email, instead of a 404.

We'll see how long I can keep this up. The quality of these commit messages is great though - they give the why and the how of your commit.

Read more…

JWZ on commenting code

I love this exchange between Peter Seibel and Jamie Zawinski from the book Coders at Work. It captures what I like about well-documented code.

Seibel: Earlier you said something about writing code in order to make it easier to read, which ties into maintenance. What are the characteristics that make code easier to read?

Zawinski: Well, comments obviously. Writing down what the assumptions are and what this does. If it's building up a data structure, describing the layout of it. A lot of times I find that pretty helpful. Especially in writing Perl code when it's like, uh, well, it's a hash table and values are bunch of references to lists, because the data structures in Perl are just nuts. Do I need a right arrow here to get to this? I find examples like that to be helpful.

I always wish people would comment more, though the thing that makes me cringe is when the comment is the name of the function rephrased. Function's called push_stack and the comment says, This pushes to the stack. Thank you.

You've got to say in the comment something that's not there already. What's it for? Either a higher-level or a lower-level description, depending on what's most important. Sometimes the most important thing is, what is this for? Why would I use it? And sometimes the most important thing is, what's the range of inputs that this expects?

Long variable names. I m not a fan of Hungarian notation, but I think using actual English words to describe things, except for loop iterators, where it's obvious. Just as much verbosity as possible, I guess.

Read more…