writings from zac anger

old blog

2017 todo list


I'm re-posting NY resolutions as a checklist, post-dated for the end of this year.

Some things will be ongoing tasks, and won't be checked off until I feel like I've been consistent with them for several months at the least.

I may add things to this list, or remove ones that I've straight-up decided were a bad idea (like buying a car).

The checklist is using GFM, which this blog generator doesn't understand. (That's on the list.)

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 these languages to write real-world stuff
    • [ ] Racket
    • [x] ClojureScript
    • [ ] Haskell
  • [x] Learn more about sh and POSIX compat in general
    • [ ] Also convert as much of my dotfiles as possible to use sh instead of bash
    • [x] 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 healther
    • [ ] Switch to vaping, for real this time
    • [x] Maybe eat better?
      • [x] Less pizza, at least
  • [x] Finish paying off debts, so close
    • [x] Also try not to tap into savings so much for stupid things
  • [ ] Change how this blog is built, so it's more flexible, and maybe using something fun like Frog (using GFM).
    • [ ] Also, blog more (at least, clear out my drafts dir).
  • [x] Be making more money
    • [x] Preferably where I am now, but somewhere else if that doesn't work out
    • [x] Also start actually emailing recruiters back
  • [x] Actually finish anything ever
    • [x] Various unfinished small projects
  • [x] Make progress on learning Korean, for real this time
  • [x] Try really hard to not write any untested code
  • [x] Make a real effort to talk to real humans in real life
  • [x] Take the time to move all things using Facebook auth away from this
  • [x] Delete Facebook
  • [x] Get more tattoos

a short rant about languages and people


I wrote this on Mastodon but decided to cross-post for whatever reason.

One of my biggest pet peeves is when people talk about how great foo-lang is as an alernative to bar-lang, & it turns out they're just shit at bar-lang, or write deliberately bad bar-lang in examples to try to make foo-lang look better. Don't do that. If you can't write decent, idiomatic bar-lang, you don't get to hate it yet. If you can and are writing it like someone who's never read a tutorial on it intentionally, you're just making foo-lang's community look like assholes. Chances are foo-lang is pretty great, & can stand up on its own merits. Talk about those, not how bad your half-assed bar-lang is in comparison. I see this a lot with functional languages that compile to JS, especially, & it's sad, because most of those languages are actually really neat & there are a lot of good reasons to try them, but people saying 'look how horrible this JS is compared to this other thing' when the JS looks like it was written by someone who skimmed a jQuery tutorial once really doesn't present the community very well. So don't do that.

Also: a fun vim/Twitter trick (I also cross-posted this to Twitter ): :set textwidth=140, then gq. You're welcome.

WTF is Set?


WTF is Set?

Please excuse the funky syntax highlighting in this post. Apparently the thing my blog uses for that doesn't know what to do about template strings.

So, someone asked in a Slack channel how they might clean up the following code:

getNames (contacts) {
  let contacts_set = []

  contacts.forEach((contact) => {
    let firstName = get(contact, 'contactInfo.firstName')
    let lastName  = get(contact, 'contactInfo.lastName')
    let fullName = `${firstName} ${lastName}`

    if (contacts_set.includes(fullName)) {
      return
    } else {
      contacts_set.push(fullName)
    }

    set(this, 'contactsSet', contactsSet)
  })
}

Note that the get and set going on here seemed to be Ember-specific. I don't know Ember so don't ask me.

And I said, how about this?

getNames: (contacts) =>
  [...new Set(
    contacts.map(({ contactInfo: { firstName, lastName }}) =>
      `${firstName} ${lastName}`))]

I like this version because it's very concise and still readable (to me). It also doesn't do mutation-y stuff, which is a good thing.

And then someone else asked:

Can some one eli5 what Set is that's referenced above?

Which made me realise that a lot of folks still aren't using a lot of the nice new things from ES2015, so I explained a bit. Here's how I understand it.

Set is a new (in ES2015) iterable builtin (like Array, String, TypedArray). Map is also new in 2015. Set is to Array as Map is to Object, kinda.

For practical usage Set is basically Array but unique, and with different methods. add, has, delete, size, and some others. There's a lot more info on MDN.

You can pass Set an iterable, which is why the thing I have above works (because thing inside new Set() results in an array).

In that case Set isn't being used for too much besides just the fact that it's Set (so it only holds unique values). Someone else pointed out in the same channel that maybe it's not the best idea if you have a lot of values, because then you're creating another thing, which is totally true.

There's a bit more background here) on what JS's Set is suppose to be kind of like.

And underneath it sorta looks vaguely like this:

class Set {
  constructor () {
    this.storage = []
  }
  add (a) {
    if (!this.storage.includes(a)) {
      this.storage.push(a)
    }
  }
  has (a) {
    return this.storage.includes(a)
  }
  remove (a) {
    this.storage.splice(this.storage.indexOf(a), 1)
  }
}

That's a lot of stuff, but mostly you can think of Set as a thing that's like Array but it only holds unique things.

There's also a WeakSet which can only hold objects. I haven't really found a valid use case for WeakSet and WeakMap yet, personally.

Set turns out to be pretty useful. I've used it a few times at work (with appropriate polyfills) without any problems, and I use it in a few places in zeelib, my sort-of-sometimes-popular utility library. Definitely play around with it!

Recommendations For New Web Devs


Some Recommendations for New (Web) Developers

Some of these thoughts probably apply to all developers. Some don't.

  1. Learn an editor. It doesn't matter which editor. Just learn one. Be good at it. I don't care if you use Visual Studio or Emacs or whatever. Be really good at the thing you pick, though.
  2. Learn enough vi to get by. You will need to know it, at some point. At the very least, learn how to enter text, move around, save, quit, and quit without saving.
  3. Install jq (build it from source if you want the newest hotness; otherwise install it with your package manager). Don't install the jq clones written in other languages (not C) — most of them are slow and/or only half-finished.
  4. Get comfortable with Bash. You don't have to be great with it, just know enough to get by. It doesn't matter what shell you actually use (Zsh, Ksh, Bash, Sh, Dash, Ash, PowerShell — I don't care, whatever). If you're writing stuff that's going to be run by other people, ever, write it in Bash. If you're writing stuff that may or may not be run on a server, write it in POSIX-compliant sh.
  5. Spend some time on Twitter. Facebook is for finding out how your middle-school best friend's back surgery went. LinkedIn is for collecting recruiter spam just in case. Twitter is for following people who say things that matter, so get on Twitter.
  6. No one cares if you can't afford a Mac. Macs aren't great computers, they're okay computers that are very expensive. If you can't afford a Mac, try Linux (I recommend Debian with the XFCE desktop environment, but try other things too if you want!). If you don't have time for that, Windows is also okay (just remember to tell your editor and Git to use UNIX-style line-endings).
  7. Don't work (for your employer) on the weekends. Work on side projects, if you want. Or do other things. Go out to brunch. Climb a mountain. Learn a Primus song on bass. Get drunk. Just don't work for the person who pays you to work during the week. If they seem to expect you to be working when you're not at work, start looking for another job.
  8. Learn other languages. HTML and CSS are not programming languages, so they don't count. JS is actually a really great language (so don't take shit from Java or C# developers who bitch about it!), but it's only one language. Learn another language that helps you think about what you do in a different way. Scheme (specifically, Racket) is a really nice one to start with. Haskell is interesting (or some other ML-type language, like OCaml or Purescript). C is also really useful to know, even if you only ever learn enough to write a basic shell or something.
  9. Figure out your own method for managing tasks. Chances are, you'll work for more than one company over the next few years. Your employer might be really into Jira, or Trello, or whatever, or they might change their mind four times a year, but either way, getting heavily invested in one tool is not a great idea. Use their thing, but also figure out what works for you. I keep track of tasks for work in plain Markdown files, and I use lilnote for personal tasks. Just find a thing you like and stick with it.
  10. Make time for personal development. Including on the clock. If your employer doesn't like that you spend a half hour every morning catching up on what new flags Chromium shipped, or competing on Codewars, or whatever other technical thing happens to really interest you but might also benefit your company, start looking for another job.

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([
  PropTypes.object,
  PropTypes.string,
  PropTypes.arrayOf(
    PropTypes.oneOfType([
      PropTypes.array,
      PropTypes.bool,
      PropTypes.object,
      PropTypes.string
    ])
  )
])

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.