writings from zac anger

old blog

PropTypes for Classnames

The classnames library is nice. It lets you do stuff like

import cn from 'classnames'
import styles from './styles.css'

const Thing = ({ foo }) =>
  <Stuff className={cn(styles.thing, { [styles.foo]: foo !== 2 })} />

And a whole bunch of other stuff, and it just works. If you write your CSS in CSS, you should check it out.

There is one sort of pain point with it, though. If you have components that can take anything that's classnames-compatible, PropTypes get a little annoying.

Stuff.propTypes = { className: string.isRequired }

This doesn't work, because you're passing all sorts of stuff in, possibly.

A solution is to make your own custom PropTypes. You don't even need to get into fancy stuff involving validation, just combine a bunch of other PropTypes into your own.

Let's say you have a propTypes.js file somewhere where you define custom PropTypes.

import { PropTypes } from 'react'

export const classname = PropTypes.oneOfType([

That's all you need! Then you can do:

import { classname } from './propTypes'
import cn from 'classnames'

const Stuff = ({ className }) =>
  <span className={cn(className)}>

Stuff.propTypes = {
  className: classname // this is your custom thing

That should solve all PropTypes warnings and let you throw anything the classnames library can handle at your components.

new years resolutions

things i hope to maybe do in 2017

  • Work less at work
    • Mainly, stop working on weekends and in the middle of the night and stuff
  • Get familiar enough with Racket, ClojureScript, and Haskell to write real-world stuff
  • Learn more about sh and POSIX compat in general
    • Also convert as much of my dotfiles as possible to use sh instead of bash
    • Also weed out my dotfiles, they're ridiculous
  • At least record the acoustic album that's been written and sitting there for ages
    • Maybe get Windows working enough to finish up the electro album thing
  • Be slightly healther, at least
    • Switch to vaping, for real this time
    • Maybe eat better?
      • Less pizza, at least
  • Buy a car
  • Finish paying off debts, so close
    • Also try not to tap into savings so much for stupid things
  • Actually finish anything ever
    • Various unfinished small projects
    • Finish Pharaoh rewrite early on
  • Make progress on learning Korean, for real this time
  • Try really hard to not write any untested code
  • Make a real effort to talk to real humans in real life
  • Take the time to move all things using Facebook auth away from this, so I can finally delete my Facebook
  • Change how this blog is built, so it's more flexible, and maybe using something fun like Frog
    • Also, blog more (at least, clear out my drafts dir).
  • Be making more money
    • Preferably where I am now, but somewhere else if that doesn't work out
    • Also start actually emailing recruiters back
  • Switch to Mutt or some other purely text-based email client

Category Theory Notes

Category Theory for JS Devs

Notes taken while watching this series.


Basics of type checking.

const str = a => {
  if (typeof a !== 'string') throw new TypeError('Expected a string')
  else return a

Guarded Functions and Categories

Functions that have contracts on input or output are called guarded functions.

An any function might just look like an identity function (const any = a => a).

Maps between categories are functors.

The objects of categories are the contracts. Morphisms are the (guarded) functions.

Function that returns a contract:

const typeOf = type => a => {
  if (typeof a !== <span class="hljs-subst">${type}</span>) throw new TypeError(Expected <span class="hljs-subst">${type}</span>!)
  else return a

And basic usage:

const bool = typeOf('boolean')
const num  = typeOf('number')
// etc.
// Obviously, for arrays you'd need to use Array.isArray()

Then we could do something like

const increment = a => {
  a = num(a)
  return a + 1

Before I go further I should mention that yes, I have heard of Flow and TypeScript.

const increment = (a: number) => a + 1

I assume this video series will get to actual type systems at some point, though it was made before TypeScript and Flow were written, so it won't be mentioning those.

Array Contracts

Not using isArray or instance of. Using toString.

const arr = a => {
  if ({}.toString.call(a) !== '[object Array]') throw TypeError('Expected array!')
  else return a

The same thing could be done for Date, RegExp, etc.


Takes a maps the contract over the things array. Will throw if they're not all correct. Ensure that your array is, for example, all Strings, or whatever.

const arrayOf = contract => things => arr(things).map(c)

This acts on the category's objects and morphisms both, and produces new objects and new morphisms.


The Maybe functor.

Maybe is a Monad, but I guess we're only thinking of its Functor-ness for this video?

Anyway here's some code.

const Maybe = () => {}
Maybe.prototype.getOrElse = function (a) {
  if (this instanceof Some) return this.a
  else return a
// the above: maybe something getOrElse what to do if none

const None = () => {}
None.prototype = Object.create(Maybe.prototype) // all instances of None are an instance of Maybe
None.prototype.toString = () => 'None'
const none = new None()

const Some = function (a) { this.a = a }
Some.prototype = Object.create(Maybe.prototype)
Some.prototype.toString = function () { return Some(thisa) }
const some = a => new Some(a)

const maybe = c => m => {
  if (m instanceof None) return m
  else if (m instance of Some) return some((m.a))
  else throw new TypeError('Expected None or Some a!')

Unit and Flatten

const arrayOfUnit = contract => (
  a => {
    a = contract(a)
    return arrayOf(contract)([a])

const maybeUnit = contract => (
  a => {
    a = contract(a)
    return maybe(contract)(some(a))

const arrayOfFlatten = c => (
  a => {
    a = arrayOf(arrayOf(c))(a)
    const r = []
    const l = a.length
    for (let i = 0; i < l; ++i) {
      r = r.concat(a[i]) // ew wtf is this guy doing?

const maybeFlatten = c => (
  a => {
    a = maybe(maybe(c))(a)
    if (a instanceof Some) {
      a = a.x
    } else if (a instanceof None) {
      a = a // why? if it's not Some, it must be None.
    return maybe(c)(a)

// oh god what is even happening right now
Array.unit = a => [a]
Maybe.unit = some
Array.prototype.flatten = function (c = any) { return arrayOfFlatten(c)(this) }
// he literally has if (c === void 0) c = any
// but this isn't the 90s so

// apply given functor twice to a contract
const twice = f => c => f(f(c)
const once = f => f // what the actual fuck, this is id..

Okay, I'm done, I tried. there are like 20 more videos in this series but it's so badly done and there are so many mistakes and the guy talks so slowly that I just can't do this anymore.

If anyone knows of a decent intro to category theory for JS devs, please let me know.

advice for new devs

So, I went to one of those code bootcamps. I started there just over a year ago, and when I finished the course I worked there as a mentor for a cohort (three months). Immediately after that, I got what I think is a pretty swell job doing development full time, working mostly in technologies that I really like.

It's hard to find non-success stories from bootcamps, since generally the people who go to these things are people who are really determined to do very well. You don't go and pay $10k-$20k to lock yourself up in a building with a bunch of other nerds for twelve or moure hours every day for three months straight unless you really want to get something out of it. I think I'm a good example of someone who did really well through a bootcamp, though, and the reason I did so well comes down to really just one thing, which I think everyone going into computing (whether it's web development, databases, hardware, whatever) really should be aware of.


That seems really obvious, right? But as a mentor it was amazing to me how many people would come into a course that's just about making things happen with computers, not knowing a lot of the basics of how to use a computer, and knowing virtually nothing about how computers actually work. They're not just a thing with a keyboard and a screen and a logo on the back. They're not just a status symbol, though Mac users would like you to think they are. They're not magical, and it's important to know what they do and how they do it, at least in vague terms.

No junior web dev should really be expected to be familiar with what a page cache is, or maybe even how domain names are resolved, but you should at least know what a kernel is, what userland actually means, what the implications of using your particular filesystem are, what the internet infrastructure kind of looks like (at least in vague terms), and how to do some basic things that will save you a lot of time later on (general terminal usage is a good place to start).

This is the number one thing that can help you get, and stay, ahead as a student and junior dev, in my opinion. And it's stuff you'll absolutely have to know at some point, and probably mostly won't be taught, so it's a good idea to just pick up this stuff as early as possible.


This is an elaboration on a tweet from last night.

I was born male, and I identify as male. That's pretty convenient for me. I'm white, which is probably very convenient for me. I make a conscious effort to be aware of my privilege, but I probably fuck up sometimes. I hope that whenever that happens, someone will call me out on it.

I was born in Baltimore, and went to a public school that I think was less than half white. That turned out to be a nice thing, because I never really understood what the big deal was about skin colour. My parents tell me I literally didn't understand that some people might think there was a difference between people with different coloured skin. And why would I? I was a kid, that's not a thing I should have to know.

My family moved to southern Pennsylvania when I was 11. South-Central PA is overwhemingly white, and has a large boomer population. One could easily go months at a time without seeing a black person, especially if one was homeschooled (which I was, because the local schools were some of the worst in the state).

When I was 19, I was working in the coffee shop in a local grocery store. I had just voted for the first time. Obama became President. The next morning, I went to work around 6:30, sold a newspaper to an older guy around 7. He sat down on a nearby bench and said to me "Can you believe they put a n----- in the White House?" This wasn't my first time encountering racism, but it was the first time I realised just how open people in that area were about it.

I worked at a guitar shop for a while. The guy who owned it was a stereotypical redneck, something straight out of a Far Side comic. To him, anyone non-white was nothing but an epithet, women existed to be objectified, and if he got a hint that someone wasn't straight, they wouldn't be allowed in his shop. Most of his days were spent smoking pot and looking at pictures of girls on the computer in his office.

I moved to Utah about a year ago. I didn't intend to stay here, because Utah is all of the bad things people say about it. It's also all of the good things people say about it—there are mountains and things, and if you're into that that's pretty nice—but it's extremely white, extremely Mormon, extremely dry, and extremely boring. It's a lot of the things I hated about Pennsylvania, except drier and with Mormons instead of Evangelicals.

I kind of thought, though, that being out here would be a bit of an escape from the 'culture' in Pennsylvania. James Carville described PA as being Philadelphia and Pittsburgh with Alabama in between, and that's pretty accurate. Utah's more like Salt Lake City and then a bunch of nothing mixed with Mormons, which isn't actually any better. Mormons are a little more laid-back about their racism and mysogyny, but it's still there. They're just encouraged not to show it off, because the LDS church doesn't want that public image. It's pretty clear based on their politics, though.

This election was not about anything except for hatred. A common statement is that Trump just 'tells it like it is,' but that's known to be bullshit. He's been the most dishonest Presidential candidate in the history of fact-checking, and Clinton has been one of the most factually accurate, ever, period. Straight talk has nothing to do with anything. There have also been numbers that say that Trump supports think the economy will do better under Trump, but generally folks actually worried about the economy will vote Democrat, probably because the economy tends to do better under Democrats.

Trump winning the electoral vote last night has nothing to do with policy. It was a message from the worst kind of people in this country that they want to be heard and want to be taken seriously. That they're afraid of people who don't look like them or have the same beliefs as them. People like that old man at the coffee shop, or Randy from the guitar shop, or Carmine, my boss at my last job in Pennsylvania. People who think they should have the right to openly discriminate against other people, people who are so unconcerned with facts that they sound exactly like characters in Idiocracy (link), calling people 'faggot' for being educated on a topic.

I'm a cis white male, and I'm sorry that a bunch of cis white males did this to this country. It's going to be really rough, especially at first when we have a red house and senate. We, collectively, all the people that have fought for LGBTQA rights and less discrimination and tried to defend against ignorance and won Clinton the popular vote, we need to hold on and survive this and support each other. We need to call each other out on our biases and abuse of privilege We need to not give up. We need to show each other, the country, and the world that America is not a country of hate.

There are folks on Twitter saying that this will be easy, that love and happiness and just get through it, and that's bullshit. This won't be easy. This is serious and dangerous and terrifying. This is bad news all around. But let's try, because we can't all just leave.