Blog logotrial and stderr

Javascript Module Systems in 30 Seconds

 •  Filed under javascript

Here's my attempt at the most compact description of Javascript module systems on the internet:

ES6 (aka ES Harmony)

import a from 'b'
export c


var a = require(‘b’)
exports = c

CommonJS is synchronous, and supports one file per module.

NodeJS is a CommonJS variant

var a = require(‘b’)
modules.exports = c


define(['a', 'b'], function(a, b) { return c })

AMD supports multiple files per module.

RequireJS is a loader that implements AMD and loads plain JS files as modules

Don't use Google Sheets' ISBLANK()


If you've tried to make formulas in Google Sheets using the ISBLANK() function, you probably have noticed its wildly unintuitive behavior: it does not consider "" as blank. No, that's not two visible quotation marks – that's the presence of the string delimiter. So cells with the contents (omitting the initial " used to display the formulas)

resolve to

Despite this somehow charmingly condescending attempt to explain, you're correct in identifying this behavior as wrong. It's the wrong thing to do; it's bad design.

To mitigate this problem, use EQ(LEN(A1), 0), which does what you expect.

Advice for Using R: Pure Invective

 •  Filed under r

I think the best piece of advice I could give to someone considering doing an R project of more than twenty lines of code is the following:

Don't. Use Python with Pandas.

I have many beefs with R, but the main one is the type system. It is nearly impossible to predict what most functions will do based on their type. This is largely due to the fact that everything is a vector, so it's ambiguous whether a function operates on a whole vector or on each of its elements.

Also, the vector might accidentally be a factor, which behaves differently from a normal vector. Casting from a factor to a numeric vector, like much of the language, does the least intuitive imaginable thing.

All of the more complex structures are extremely wiley. Data frames behave in absurd ways. They were badly designed. The whole language was badly designed. That's why tidyverse was invented, with tibbles as a nice replacement for data frames. But few functions outside the tidyverse document their behavior when run on tibbles, and very often you'll get a data frame out the other end.

The debugger is awful; breakpoints cannot be set from sourced files. The typing difficulties make this especially egregious.

There is no namespacing; you must invent it yourself.

Even the basic types behave in absurd ways:

> "111" > 27

In short, even once you have a good grasp on the syntax and some of the usual operations, it is incredibly difficult to predict what any given R statement will actually do. It's like solving a puzzle in the dark: you will know when you have the right piece exactly when it snaps into place.

Widgets in GNOME

 •  Filed under linux, tutorials

If you've used GNOME extensions for more than a few months, you've probably realized that they can easily send your desktop into a hellish crash-on-login loop that can only be remedied by dropping to a root shell.

This is obviously insane and awful, but is also wholly predictable. GNOME is written in JavaScript, and the official GNOME extension "mechanism" is that arbitrary JavaScript is allowed to mess with your GNOME environment. When an update introduces an incompatibility and something goes wrong, GNOME crashes. It's like a handful of mechanics are continuously making modifications to your car without talking to each other, and there are no seat belts.

I got tired of GNOME crashing every other day, so I disabled extensions. The thing I really missed, though, was an always-visible system resources monitor. Turns out there's a nice way to get one!

The answer is a minimalistic terminal emulator called Tilda. Here's the bottom-left corner of my screen.

I'll walk you through setting this up.

Install Tilda and htop (or whatever you'd like to run in your widget) and open preferences. Go to the "Title and Command" tab, tick "Run a custom command...," and enter htop for the "Custom Command."

Configure htop by hitting F2 (if you like what I have going, you can use my htoprc).

Once you get it right, go back to the Tilda preferences, go to "Appearance" and get it to appear at the size and position that you like.

Then from the GNOME launcher, launch "Startup Applications" and add a startup program with command tilda.

There you have it!

Gnome to KDE and back again

 •  Filed under linux

I was a mostly-happy Gnome (that is, vanilla Ubuntu 18.04) user for almost a year. I liked almost everything about it, really. The big problem is the fact that extensions are written in JavaScript and have no sandboxing of any sort, so that when Gnome updates and some incompatibility with an enabled extension is introduced, Gnome crashes on login.

I disabled all my extensions from the Ubuntu recovery console. While this made it so I could log in, it didn't stop all the crashes. Clearly there was still just some instability with Gnome.

So I switched to KDE. KDE required a lot more configuration to get it to look and feel right. Probably a lot of that was due to residual configuration from the Gnome installation. I imagine it's much smoother getting started with Kubuntu directly. But I was dismayed to realize that KDE too was crash-prone. After a few months, it eventually got to the point where it was crashing every time I closed my laptop lid. At that point I switched back to Gnome, sans extensions.

Both Gnome and KDE are pleasant to use, except when they crash. They are bad when they crash.

Gnome has more reasonable defaults; it makes more sense out of the box. KDE has more cool features – a vertically-split file browser is what I want basically 100% of the time, and I didn't know it until I used KDE.

But the way Gnome does extensions is irresponsible to the point of insanity. There's just no hope of having a stable system like that. A huge ecosystem of extensions has sprung up based on a software design decision so abysmally bad it could only have been an afterthought.

I imagine that the crashes on lid-close-lid-open have to do with shitty drivers for my hardware, so as a warning to future generations: I'm using an HP Spectre x360.

Beginning R Resources for Experienced Programmers

 •  Filed under r

Basics and Syntax

R Language for Programmers

5 Kinds of Subscripts in R

The Google Style Guide, which is better than the Advanced R one

In RStudio, auto-format your code with with the Styler Addin: install('styler')

Technique and Structure

Structuring R Projects

Advanced R, starting with Data Structures and Functional Programming

Data Manipulation using dplyr and tidyr


1:1 generates a sequence of length one, [1]. 1:0 generates a sequence of length two, [1, 0]. Therefore, when an object x with zero rows is passed into for (i in 1:nrow(x)), the code in the for loop will be executed twice, which is probably very different from what you expect. Therefore always use seq_len() or seq_along() in place of : ranges in your for loops. E.g., for (i in seq_len(nrow(x))). Reference.

Trying to learn R reminds me of when I, as an undergraduate math-philosophy double major, had to take a logic class in the philosophy department. In the math department, the class could have been compressed into two weeks. But in the philosophy department, even spread out over three months, it was the subject of much frustration for the less mathematically inclined philosophy students.

Similarly, most resources for learning R are directed at non-programmers, and as such are painfully gentle. So I will be maintaining here a list of satisfyingly terse explainers and tutorials.