angr

writings from zac anger, who is not all that angry

Notes from the AngularJS Utah Meetup

April 24, 2016 — Zac Anger

So what with my last computer dying, getting a new phone, trying to find a job, preparing to maybe move, and all the other nonsense going on, I haven't really blogged at all lately. Oh well.

My to-do list is gigantic, like a whole huge directory tree of several gigabytes full of unfinished stuff.

Somewhere in there, there's rewriting my entire website.

I've just switched from GoDaddy's hosting to my own VPS (a droplet), since GoDaddy's cost was going up by about 110%. This means I have a LOT more available to me, now. Not quite as much space, but I can run whatever I need to on my server now, so... I think it's time to finally update everything. I plan on leaving most things as just plain old static sites (because, let's be honest, no one cares how flashy this crap is if it takes a year to render it on an old phone). The blog might change a bit, though. I'm still using that same old script (based originally on BashBlog, heavily modified over the past almost-year). Nothing against that script, it does its job and everything, but a 1300-line shell script to basically turn Markdown into HTML is absurd -- ESPECIALLY since it doesn't include the parser.

Anyway, here are some notes from the NG-JS meetup a couple of weeks ago. They were lost on my old laptop, but the SATA-to-USB thingy came in the mail the other day, so I can finally just do something with these.

read more...

tags: rxjs, immutable, js, utah, meetup, notes

so, tweet it?  

FP in JS

April 03, 2016 — Zac Anger

Notes taken while going through this guy's videos.

You should watch them all. He's great.

'use strict'

//
// HOF
//
// Higher Order Functions
// functions are values
// const something = function > function something
// obvs functions passed into functions
// composition yay
// example: filter (method on array, takes another function as action)
// filter's should return true or false to determine whether item belongs in arr
let something = [{foo : 'bar'}, {quux : 'baz'}, {whatever : 'target'}]
let newArr
for (let i = 0; i < something.length; i++) {
  if (something[i].what === 'target') {
    newArr.push(something[i])
  }
}
// vs
let newArr = something.filter(thing => {
  return thing.what === 'target'
})
// or, using reject
let isTarget = something => thing.what === 'target'
let notTarget = something.reject(isTarget)
// note: there's also find. that returns just the first item that matches.

//
// Map
//
// map's cb returns a transformed object to put into array
let peeps = [
  {name : 'geordyn', relationship : 'bffl'                   }
, {name : 'erin'   , relationship : 'number one bro'         }
, {name : 'ryan'   , relationship : 'nemesis. also, the one.'}
, {name : 'andrew' , relationship : 'special mormon'         }
, {name : 'sarah'  , relationship : 'grandma'                }
]
// non-functional way of doing getting an array of the names
let names = []
for (let i = 0; i < something.length; i++) {
  names.push(something[i].name)
}
// vs
let names = peeps.map(peep => peep.name)
let about = peeps.map(peep => peep.name + ' is my ' + peep.relationship + '.')

//
// Reduce
//
// map, filter, reject, and find are fairly specific list transformations.
// reduce is is more of a swiss-army knife. it can do just about anything.
// reduce wants an object, though. (yes, it's a method on the array prototype.)
let stuffToSum = [
  {amount : 4   }
, {amount : 16  }
, {amount : 1024}
, {amount : 4096}
]
// so...
let total = 0
for (let i = 0; i < stuffToSum.length; i++) {
  total += stuffToSum[i].amount
}
// vs
let total = stuffToSum.reduce((sum, stuff) => sum + stuff.amount, 0)
// this is adding stuffToSum[0].amount to sum (which is initialised at 0)
// and returning that sum, then going again with stuffToSum[1].amount and
// the current sum (4), and so on.
//
// let's say we have some file in TSV format, like below. (i'm using 4 spaces
// to represent a tab here, since tabs = 2 spaces in all my editors, and 2 spaces
// isn't large enough to clearly distinguish fields here, i think.)
// miss lady    an item    7    20
// miss lady    a thing or two    75    2
// some dude    another product    33    9
// some dude    some product    100    1
// we need to transform this into a nice looking object (containing two objects,
// one for each person, each containing an array of objects that are the items bought).
import fs from 'fs'
let contents = fs.readFileSync('./thatFile.tsv', 'utf8')
.trim()                        // remove trailing newline
.split('\n')                   // split into array of strings at newlines
.map(line => line.split('\t')) // \t is a tab character
.reduce((persons, line) => {
  persons[line[0]] = persons[line[0]] || []
  persons[line[0]].push({
    name  : line[1]
  , cost  : line[2]
  , quant : line[3]
  })
  return persons
}, {})
console.log('contents: ', JSON.stringify(contents, null, 2))

//
// Closures
//
function sendReq(){
  let reqId = 'asdf'
  $.ajax({
    url : '/someurl'
  , success(response){
      console.log('request ' + reqId + ' returned')
    }
  })
}
// see, we don't have to pass stuff around here. reqId is going to be 'asdf'
// no matter when jquery's ajax finishes whatever it's doing. nice.
// there's also this classic example:
function makeAdder(x){
  return(y => x + y)
}
let
  add4 = makeAdder(4)
, add8 = makeAdder(8)
console.log(add4(16))
console.log(add8(64))

//
// Currying
//
// so, you've got some arguments. you could have a function that
// takes your bunch of arguments and does stuff with them. or you could
// have a function that takes your first argument and winds up returning
// a function that takes your second argument which returns a function
// that takes your third argument... etc., you get the idea.
let self1 = (name, age, language, location) =>
  `Hi, I'm ${name}, age ${age}. I speak ${language} and live in ${location}.`
console.log(self1('zac', 26, 'english', 'utah, i guess'))
// vs
let self2 = name => age => language => location =>
  `Hi, I'm ${name}, age ${age}. I speak ${language} and live in ${location}.`
console.log(self2('zac')(26)('english')('utah, i guess'))
// why? maybe i don't know everything about myself yet, but my app will find
// out some of this information later. so i call self('zac'), have a birthday,
// call self(27)('english') because it's been another year and i still only
// speak one language, and then i call self('texas??') because i've moved.
// now, finally, i have the return value (the introductory sentence)!
// what about self1? we could always use something from some library to
// transform it, like wu.js's autoCurry, or whatever. for the sake of familiarity,
// try lodash (first npm i -S lodash):
import _ from 'lodash'
let me = _.curry(self1)
console.log(self1('zac'))
// yay! okay, another example.
let
  guitars = [
  {brand : 'ovation'    , type : 'acoustic' }
, {brand : 'silvertone' , type : 'acoustic' }
, {brand : 'esp'        , type : 'electric' }
, {brand : 'teton',     , type : 'acoustic' }
, {brand : 'danburn'    , type : 'electric' }
, {brand : 'homemade'   , type : 'cigar-box'}
]
, isType    = (type, obj) => obj.type === type
, electrics = guitars.filter(x => istype('electric'), x)
console.log(electrics)
// okay, so using the same guitars array:
import _ from 'lodash'
let isTypeCur = _.curry((type, obj) => obj.type === type)
  , acoustics = guitars.filter(isTypeCur('acoustic'))

//
// Recursion
//
// recursion is not at all a difficult idea. won't even
// bother laying it out here, really. a function calls itself
// until it's done calling itself. it's a super useful way to
// program, especially in actual functional languages.
// es6 makes recursion a lot nicer. we can get rid of the
// if statement in the below function in es6 because we won't
// end with a 'RangeError: Maximum call stack size exceeded
// or whatever.
let countDown = num => {
  if (num === 0) {
    return
  }
  console.log(num)
  countDown(num - 1)
}

//
// Promises
//
function loadStuff(url, cb){
  let img = new Image()
  img.onload = () => {
    cb(null, img)
  }
  img.onerror = () => {
    let msg = 'failed loading ' + url
    cb(new Error(msg))
  }
  img.src = url
}
export default loadStuff
// with
import loadStuff from './loadStuff'
let addThing = src => {
  let el = document.createElement('img')
  el.src = src
  document.body.appendChild(el)
}
loadStuff('/thing/to/load.png', (err, img) => {
  if (err) {
    throw err
  }
  addThing(img.src)
  loadStuff('/thing/two.png', (err, newImg) => {
    if (err) {
      throw err
    }
    addThing(img.src)
    // etc
  })
})
// vs
function loadThing(url){
  return new Promise((resolve, reject) => {
    let img = new image()
    img.onload = () => {
      resolve(image)
    }
    img.onerror = () => {
      let msg = 'failed loading ' + url
      reject(new Error(msg))
    }
    img.src = url
  })
}
export default loadThing
//with
import loadThing from './loadThing'
let addThing = src => {
  let el = document.createElement('img')
  el.src = src
  document.body.appendChild(el)
}
Promise.all([
  loadThing('/path/one.png')
, loadThing('/path/two.png')
// , etc
]).then(images => {
  images.forEach(img => addThing(img.src))
}).catch(err => {
  throw err
})

tags: functional-programming, javascript, js, fp, functional, notes, examples, map, filter, reduce, promises, closure, closures, recursion

so, tweet it?  

stuff everybody knows

April 02, 2016 — Zac Anger

Takeaways from Laurie Voss's 'Stuff Everybody Knows Except You'

  • Be good at your tools.
    • If you use Windows, be good at Windows. Also, don't use Windows.
    • Know Bash. Also know Sed and Awk. But really, really, really know Bash.
    • Be good at your editor. It doesn't matter which one. Notepad is not an editor.
  • Don't fuck with users.
    • Paralaralaralax is the devil.
    • A button is an action. A link goes somewhere.
  • Auth is not simple.
    • Identification: Hi, I'm this guy! (To people.)
    • Authentication: Hi, I can prove I'm this guy! (To a computer.)
    • Authorization: Hi, I am allowed to do these things!
    • Salt and hash your passwords. Always. (Bcrypt.)
  • Security is not a joke.
    • Leave it to people who know what they're doing.
    • Or devote your career to doing this.
  • Don't build rich web apps for everything.
    • If your site is all about content, build a plain old static site.
    • This seems obvious, but apparently it's not.
  • Load content first. Fuck your fancy fonts, fuck your gifs, just load stuff.
  • Speed over everything.
  • Write and maintain tests. Test. Write testable code.
  • Read the error logs. And write good error messages.
  • Write obvious code.
  • Get good at git.
  • Automate all the things (with deployment, but also testing, CI, and everything else).
    • But don't go overboard (yak shaving).
  • Break things up (use common patterns/modularise everything/decouple shit).
    • Also, keep in mind that everything you write is/has an API. Make it consistent.

tags: talks, notes

so, tweet it?  

Node Notes

February 03, 2016 — Zac Anger

I really enjoy node. This is all pretty disorganized. It's also all one giant code block, since I took the 'notes' bit in comments. The repos mentioned are here and here. Yay.

read more...

tags: node, notes

so, tweet it?  

Closures

February 02, 2016 — Zac Anger

A closure is a local variable for a function, which sticks around after the function has been returned.

(Or, a closure is a stack-frame which is not deallocated when the function returns [as if a 'stack-frame' were malloc'ed instead of being on the stack!]. Whatever that means.)

Here, let's explain in Javascript.

function sayHi(name){
  var text = 'hi ' + name // (local var)
    , say  = function(){
    console.log(text)
    return say
  }
}
var sayIt = sayHi('zac')
sayIt() // returns 'hi zac'

So here, a function is returned as a variable.

What we're doing here is putting a function inside a function. And we're getting something accessible outside of that enclosing function, right?

Hence closure.

In most descendants of C, after a function returns, its local variables are gone. The stack-frame is gone.

In JS, functions that are inside other functions can still be accessed outside of (after) that parent function. Try using the above code, and then doing sayIt.toString(), and you'll see that the variable say is returned -- which is a function that references text, which is a variable local to sayHi().

function oneMore(){
  var i     = 1
    , logIt = function(){
    console.log(i)
  }
  i++
  return logIt
}
var logStuff = logIt()
oneMore() // 2

Make sense? Here's a slightly more complex example pulled straight from the interwebs.

var logNumber, increaseNumber, setNumber
function setupGlobals(){
  var i = 4
  logNumber = function(){
    console.log(i)
  }
  increaseNumber = function(){
    i++
  }
  setNumber = function(x){
    i = x
  }
}
setupGlobals()
increaseNumber()
logNumber()     // 5
setNumber(8)
logNumber()     // 8
var oldLog = logNumber
setupGlobals()
logNumber()     // 4
oldLog()        // 8

Local variables from a closure will be overwritten if you call that outer function again. Don't forget this, because you can get some really screwy stuff going on if you do!

There is a closure for every function call, not for every function declaration. This example might help demonstrate this.

function newClosure(fooInt, barRef){
  var num     = fooInt
    , quuxArr = [1, 2, 3]
    , ref     = barRef
  return function(x){
    num += x
    quuxArr.push(num)
    console.log('num: ' + num +
      '; quuxArr: ' + quuxArr.toString() +
      '; ref.bazVar: ' + ref.bazVar)
  }
}
obj = {bazVar: 4}
fn1 = newClosure(4, obj)
fn2 = newClosure(8, obj)
fn1(1)     // num:5; quuxArr:1,2,3,4,5; ref.bazVar: 4
fn2(1)     // num:9; quuxArr:1,2,3,8; ref.bazVar: 4
obj.bazVar++ // 4
fn1(2)     // num:7; quuxArr:1,2,3,5,7; ref.bazVar:5
fn2(2)     // num:11; quuxArr:1,2,3,9,11; ref.bazVar:5

So... a quick recap?

When a function is used inside another function, you've used a closure. This includes eval(). (Note that using a constructor, as in new Function(), does not create a closure.)

Every time you call a function with a closure, it makes a new set of those local variables.

Closures can definitely be nested.

read more...

tags: js, closures, notes, closure

so, tweet it?  

REACT NOTES

January 25, 2016 — Zac Anger

This is all such a mess, and so unsorted, so, sorry about that in advance.

This is also almost entirely notes from very early on in trying to learn React, so not all of it will be completely valid, probably. Okay. So.

Enjoy.

REACT NOTES (yeah, again):

There's no if...else in JSX. Doesn't work. Don't try it (in your JSX).

Don't try <!doctype> either. It'll break stuff.

Same with HTML comments. Not worth the trouble, I guess. No one reads them, anyway, so whatever.

Don't try to use your own code style. JSX needs to be written the way the docs say to. Doing React means doing React their way, so screw your purely stylistic preferences, they don't matter anymore. Which, unfortunately, means semicolons everywhere. Gross.

Every single XML tag needs to be closed. That means that <br> is invalid, but <br></br> is... totally valid. Also, self-closing tags (which literally do not even exist in HTML anymore) work just fine, so <div /> is valid. What the hell.

In JSX, everything in {} will be evaluated as Javascript. So you can do some things there, if you need to. (But not if...else!)

Any JSX over multiple lines needs to be wrapped in parens. If it's single-line, you don't need them.

Evidently it's better to indent all the stuff going in your tags just inside the tag, rather than even with the first whatchamacallit. This is what I mean:

<input type="text"
       value={whatever.stuff}
       onChange={this.foo.bar} />

...is apparently NOT the way to do it. Instead, we want to do:

<input
  type="text"
  value={whatever.stuff}
  onChange={this.foo.bar} />

which, personally, I find more annoying and less readable, but apparently that's how the React community does, so whatever. Oh, and as to the closing of the tag, no matter what it's gonna be hideous, so I don't know or care whether it should be on a newline. Probably not, because that's just even more lines, but I have seen a lot of this:

<input type="text"
  value={whatever.stuff}
  onChange={this.foo.bar}
/>

which is really even more annoying, but whatever. Lastly, as far as style goes, I'll just put what would make the most sense to me, personally. Note how clean and lined up things are? Yeah. Much better, to my eyes. Still ugly af, though.

<input type="text"
      value={whatever.stuff}
   onChange={this.foo.bar} />

read more...

tags: react, webpack, js, notes, redux

so, tweet it?  

Notes

January 13, 2016 — Zac Anger

So, I have a lot of notes that I've taken over the course of the last couple of months. Seeing as they're not doing me a whole lot of good sitting in a pile of Markdown files, I'm gradually going through them, cleaning them up, and I think I'll just post them all as sort of blog posts. Why not? So here's a little list of the topics I'll be covering over the next few weeks:

  • Unicode
  • SystemJS (and JSPM)
  • Go
  • UI
  • Github Organizations
  • Functional Reactive Programming (and RxJS)
  • Elm
  • Browserify
  • Bash Builtins
  • Firebase
  • ES6
  • Pusher
  • Styleguides
  • Passport (and problems getting errors out of Express)
  • React (and Webpack)
  • Isomorphic React
  • Flux
  • Meteor
  • All the reasons I kind of dislike Angular
  • Bacon.js
  • Basics of webmastering (which is totally not a word)
  • Functional programming (in general)
  • Effective web design
  • Mongo (and Mongoose, and MongoJS, and Mongolayer)
  • Ruby, maybe a little bit
  • Electron (formerly Atom Shell)
  • NW.js (formerly Node Webkit)
  • Gulp
  • Node in general
  • Probably a good bit of Node stuff, really
  • I like Node a lot
  • Maybe a little bit of jQuery?
  • The developer hiring process
  • Maybe a little bit of that Javascript language, or something?
  • Probably not much at all on HTML, because HTML doesn't need... notes... really
  • CSS... lol, CSS.
  • People, and the experience of dealing with people on a regular basis
  • What it's like to live with the people I live with
  • What it's like to actually find myself liking human beings, and wanting to be around them, especially certain ones, quite a lot. (It's weird!)

tags: blogs, personal, notes, education, react, js, electron, flux, meteor, elm, gulp, css, es6, ruby, mongo, bash, unicode, go, ui, design

so, tweet it?  

Angular Meetup, 13th Oct, 2015

October 13, 2015 — Zac Anger

Notes:

Bene Brown; author on subject of empathy.

The Technical Bit

Jordan Last, speaker on Angular, client-side storage.

Problem: people want wikis, but don't like the word 'wiki.' (Yes, it's more complicated, but not so much so that a wiki wouldn't handle it).

Organization of survey site data (BYU Archaeology Dept.) &c.; Android devices, needed compat. with iOS. This fellow ended up with Ionic to handle building apps.

Okay, new question, how to work with storage? He checked out Cordova (PhoneGap), but wasn't into SQLite so much. Wanted straight-up persistant storage in the browser.

What options were there? Local, IndexedDB, WebSQL. Obviously IndexedDB isn't useful for people who want to stick with that Apple Webkit crap; Local storage is okay for... a little bit of stuff. They ended up choosing WebSQL (despite its deprecation), because they're big on relational databases and didn't want to get into Mongo or Node stuff. (Sidenote, this fellow doesn't quite grasp how the W3C works, or the problems with non-standard or deprecated technologies. Oh well.) Quick rundown on the very barest basics of ORM, aka Why We're Calling This A Model.

Looks like he's using Persistence JS. In persistence, you would save an object like, for example:

persistence.add(this)
persistence.flush()
callback && callback()

And now you have your whatsit all set. That's your save method. Then, say, thingy.save(function); and, y'know, there you go. Oh, wait. He forgot a bit about persistence. Needs schema.sync and a .config bit to get up and working.

Now, to query WebSQL in this kind of screwy setup (persistence-specific):

whatever.getStuff = function(thingPassed, maybeAnother) {
  whatever.all().filter('thingPassed', '=' whateveritis); // i suppose i missed quite a bit here
}

And, finally, deleting... which evidently should be pretty easy. Too easy to go over.

Closing points:

  • Never access the DB directly--do it through lots of Javascript and boilerplate and awkward ways.
  • Keep model-specific DB stuff with the model
  • Absolutely don't need to use persistence.js or WebSQL (thank goodness)
  • Use an ORM, silly!

Oh, and the fellow who organized this thing maybe isn't aware of other stuff going on aroud here. LunchJS would be worth looking into.

And this Jordan fellow is interesting. Bit enthusiastic, dresses half his age, but information architecture + comp sci + dev + project management = all the things I'm really interested in, mostly, pretty much.

Oh, and it was kinda neat to check out Adobe's SLC building.

tags: meetup, angular, javascript, notes

so, tweet it?  

zac anger?