google reader refugee.
1964 stories
·
47 followers

all your questions about negotiating salary, answered

1 Share

usnewsNegotiating salary for a new job can be complicated and stressful. How do you know how much to ask for? What if you ask for too much and the employer pulls the offer? When do you even bring it up and what do you say?

At U.S. News & World Report today, I answer all these questions and more. You can read it here.

all your questions about negotiating salary, answered was originally published by Alison Green on Ask a Manager.

Read the whole story
pfctdayelise
10 days ago
reply
Melbourne, Australia
Share this story
Delete

resigning via cod, a glorious out-of-office message, and other quitting stories

2 Shares

In case you didn’t read all of the entries in last week’s post about spectacular resignations, here are some of my favorites.

1. “One guy quit, and left up an out-of-office message with stupid quotes from all of his bosses and seniors over the year – attributed to them by name. Because our IT is so notoriously bad, it took well over a week from them to fully disable his account so that the out-of-office stopped being sent.”

2. “The summer after my first year of college, I worked at a call center doing cold-call sales. One of my coworkers ripped off his headset one day, screamed ‘I QUIT THIS PLACE SUCKS’ and stalked out. He got in his ancient Nissan minitruck, put it in gear, and attempted to drive over the landscaping between his parking spot and the driveway. He bottomed out trying to drive over a bush, got stuck, and ended up having to come back in and ask for help pushing his car off the landscaping from the coworkers he’d just staged his great exit from, his face a particularly remarkable shade of vermilion.”

3. “Ohhhh, I worked one of those jobs when I was in college. I was studying Philosophy, but nothing gave me more appreciation for Marx than working at the survey call center. I stuck it out for six months while I finished my degree and got a better job, but lots of people didn’t.

One day a girl next to me just left. I wasn’t paying much attention, but she left her jacket and everything so I figured she’d gone to the bathroom. Twenty minutes later a manager came up, looked around and left a nasty note on her keyboard. Another twenty minutes later he asked me if I knew where she’d gone. We looked at her stuff and it looked like she had left her jacket and just her purse – like, none of the stuff in it, she’d taken her wallet and phone. And left the other stuff as a ruse to give herself a good headstart on us, I guess?”

4. “I worked in high school at a mismanaged grocery chain that is now out of business. I was a cashier but they had a 16-year-old girl working behind the fish counter (which was illegal) and who was not being paid properly for the work she was doing (because she wasn’t supposed to be doing it!).

On Sunday, the beginning of the pay period, she clocked in, wrote ‘I QUIT’ in cod, haddock, and tilapia filets in the seafood counter, and clocked out. She framed a photo of her masterwork and her last paycheck for $2 and hung it in her bedroom.”

5. “I’ve been a member of an online message board for several years. About 10 years ago or so, one of the other board members announced he was going to quit his job at a grocery store and asked for suggestions on how he should leave. Not expecting him to take me up on my suggestion, I recommended that he have a little parade, driving one of the motorized shopping carts down the frozen foods aisle, with lit sparklers attached to the front and a boombox on the back playing something jubilant (‘We Are The Champions’ or some such). As it turns out, he took me up on the suggestion, had someone record the whole thing, and we got to watch a very happy ex-employee escort himself out at about 1.5mph past the Hungry Man dinners.”

6. “A colleague’s good friend had been wooed up by my company for a good 6 months. He was utterly qualified in ways we needed, a very nice guy, the perfect employee. Alluring phone calls, escalating propositions, nice dim sum lunches, they went all out. Finally, he accepted, and a starting date was set.

We had flextime at that company, meaning every waking hour was spent there but you could pretty much choose when to be awake. Alas, that particular week a couple of us (I’m one of the guilty parties) had particularly gnarly personal things to deal with before getting to work, and consistently didn’t make it in before 11-12. And equally alas, we were on the West Coast in financial services, so we already started the day ‘late’ by market standards, and to add to this the CEO was a fanatical morning person. Normally he left us to it, but this specific week he was in a bad mood, and got riled up by our seeming slackness (partly caused by staying at work way past his bedtime, but that’s another story).

So he did what Alison repeatedly warns you not to: instead of dragging the culprits into his office and giving them the personal drubbing he thought they deserved, he wrote a memo to everyone. So on his second day that Second Coming Guy meandered in to work, at a reasonable 10ish, and he found a memo on his chair saying something like ‘I’d like to remind y’all that technically your working hours are 8-5, and that you really should be here as close to that as possible blah blah blah.’ He raised his elegant eyebrows, said in a not overly loud but very clear tone of voice, ‘Oh, I can’t deal with that,’ delicately put the memo back on the chair, and walked out, never to be seen again.

Nobody was ever reprimanded for their hours again at that place, not even a hint.”

7. “When I was a supervisor at a well-known retailer, an employee in the garden center was reprimanded for something or other. He became so incensed that he went to the corner of the garden area, dropped his drawers, and pooped on a pallet. Then he quit.”

resigning via cod, a glorious out-of-office message, and other quitting stories was originally published by Alison Green on Ask a Manager.

Read the whole story
pfctdayelise
10 days ago
reply
Melbourne, Australia
Share this story
Delete

Reasons Kubernetes is cool

1 Share

When I first learned about Kubernetes (a year and a half ago?) I really didn’t understand why I should care about it.

I’ve been working full time with Kubernetes for 3 months or so and now have some thoughts about why I think it’s useful. (I’m still very far from being a Kubernetes expert!) Hopefully this will help a little in your journey to understand what even is going on with Kubernetes!

I will try to explain some reason I think Kubenetes is interesting without using the words “cloud native”, “orchestration”, “container”, or any Kubernetes-specific terminology :). I’m going to explain this mostly from the perspective of a kubernetes operator / infrastructure engineer, since my job right now is to set up Kubernetes and make it work well.

I’m not going to try to address the question of “should you use kubernetes for your production systems?” at all, that is a very complicated question. (not least because “in production” has totally different requirements depending on what you’re doing)

Kubernetes lets you run code in production without setting up new servers

The first pitch I got for Kubernetes was the following conversation with my partner Kamal:

Here’s an approximate transcript:

  • Kamal: With Kubernetes you can set up a new service with a single command
  • Julia: I don’t understand how that’s possible.
  • Kamal: Like, you just write 1 configuration file, apply it, and then you have a HTTP service running in production
  • Julia: But today I need to create new AWS instances, write a puppet manifest, set up service discovery, configure my load balancers, configure our deployment software, and make sure DNS is working, it takes at least 4 hours if nothing goes wrong.
  • Kamal: Yeah. With Kubernetes you don’t have to do any of that, you can set up a new HTTP service in 5 minutes and it’ll just automatically run. As long as you have spare capacity in your cluster it just works!
  • Julia: There must be a trap

There kind of is a trap, setting up a production Kubernetes cluster is (in my experience) is definitely not easy. (see Kubernetes The Hard Way for what’s involved to get started). But we’re not going to go into that right now!

So the first cool thing about Kubernetes is that it has the potential to make life way easier for developers who want to deploy new software into production. That’s cool, and it’s actually true, once you have a working Kubernetes cluster you really can set up a production HTTP service (“run 5 of this application, set up a load balancer, give it this DNS name, done”) with just one configuration file. It’s really fun to see.

Kubernetes gives you easy visibility & control of what code you have running in production

IMO you can’t understand Kubernetes without understanding etcd. So let’s talk about etcd!

Imagine that I asked you today “hey, tell me every application you have running in production, what host it’s running on, whether it’s healthy or not, and whether or not it has a DNS name attached to it”. I don’t know about you but I would need to go look in a bunch of different places to answer this question and it would take me quite a while to figure out. I definitely can’t query just one API.

In Kubernetes, all the state in your cluster – applications running (“pods”), nodes, DNS names, cron jobs, and more – is stored in a single database (etcd). Every Kubernetes component is stateless, and basically works by

  • Reading state from etcd (eg “the list of pods assigned to node 1”)
  • Making changes (eg “actually start running pod A on node 1”)
  • Updating the state in etcd (eg “set the state of pod A to ‘running’”)

This means that if you want to answer a question like “hey, how many nginx pods do I have running right now in that availabliity zone?” you can answer it by querying a single unified API (the Kubernetes API!). And you have exactly the same access to that API that every other Kubernetes component does.

This also means that you have easy control of everything running in Kubernetes. If you want to, say,

  • Implement a complicated custom rollout strategy for deployments (deploy 1 thing, wait 2 minutes, deploy 5 more, wait 3.7 minutes, etc)
  • Automatically start a new webserver every time a branch is pushed to github
  • Monitor all your running applications to make sure all of them have a reasonable cgroups memory limit

all you need to do is to write a program that talks to the Kubernetes API. (a “controller”)

Another very exciting thing about the Kubernetes API is that you’re not limited to just functionality that Kubernetes provides! If you decide that you have your own opinions about how your software should be deployed / created / monitored, then you can write code that uses the Kubernetes API to do it! It lets you do everything you need.

If every Kubernetes component dies, your code will still keep running

One thing I was originally promised (by various blog posts :)) about Kubernetes was “hey, if the Kubernetes apiserver and everything else dies, it’s ok, your code will just keep running”. I thought this sounded cool in theory but I wasn’t sure if it was actually true.

So far it seems to be actually true!

I’ve been through some etcd outages now, and what happens is

  1. All the code that was running keeps running
  2. Nothing new happens (you can’t deploy new code or make changes, cron jobs will stop working)
  3. When everything comes back, the cluster will catch up on whatever it missed

This does mean that if etcd goes down and one of your applications crashes or something, it can’t come back up until etcd returns.

Kubernetes’ design is pretty resilient to bugs

Like any piece of software, Kubernetes has bugs. For example right now in our cluster the controller manager has a memory leak, and the scheduler crashes pretty regularly. Bugs obviously aren’t good but so far I’ve found that Kubernetes’ design helps mitigate a lot of the bugs in its core components really well.

If you restart any component, what happens is:

  • It reads all its relevant state from etcd
  • It starts doing the necessary things it’s supposed to be doing based on that state (scheduling pods, garbage collecting completed pods, scheduling cronjobs, deploying daemonsets, whatever)

Because all the components don’t keep any state in memory, you can just restart them at any time and that can help mitigate a variety of bugs.

For example! Let’s say you have a memory leak in your controller manager. Because the controller manager is stateless, you can just periodically restart it every hour or something and feel confident that you won’t cause any consistency issues. Or we ran into a bug in the scheduler where it would sometimes just forget about pods and never schedule them. You can sort of mitigate this just by restarting the scheduler every 10 minutes. (we didn’t do that, we fixed the bug instead, but you could :) )

So I feel like I can trust Kubernetes’ design to help make sure the state in the cluster is consistent even when there are bugs in its core components. And in general I think the software is generally improving over time. The only stateful thing you have to operate is etcd

Not to harp on this “state” thing too much but – I think it’s cool that in Kubernetes the only thing you have to come up with backup/restore plans for is etcd (unless you use persistent volumes for your pods). I think it makes kubernetes operations a lot easier to think about.

Implementing new distributed systems on top of Kubernetes is relatively easy

Suppose you want to implement a distributed cron job scheduling system! Doing that from scratch is a ton of work. But implementing a distributed cron job scheduling system inside Kubernetes is much easier! (still not trivial, it’s still a distributed system)

The first time I read the code for the Kubernetes cronjob controller I was really delighted by how simple it was. Here, go read it! The main logic is like 400 lines of Go. Go ahead, read it! => cronjob_controller.go <=

Basically what the cronjob controller does is:

  • Every 10 seconds:
    • Lists all the cronjobs that exist
    • Checks if any of them need to run right now
    • If so, creates a new Job object to be scheduled & actually run by other Kubernetes controllers
    • Clean up finished jobs
    • Repeat

The Kubernetes model is pretty constrained (it has this pattern of resources are defined in etcd, controllers read those resources and update etcd), and I think having this relatively opinionated/constrained model makes it easier to develop your own distributed systems inside the Kubernetes framework.

Kamal introduced me to this idea of “Kubernetes is a good platform for writing your own distributed systems” instead of just “Kubernetes is a distributed system you can use” and I think it’s really interesting. He has a prototype of a system to run an HTTP service for every branch you push to github. It took him a weekend and is like 800 lines of Go, which I thought was impressive!

Kubernetes lets you do some amazing things (but isn’t easy)

I started out by saying “kubernetes lets you do these magical things, you can just spin up so much infrastructure with a single configuration file, it’s amazing”. And that’s true!

What I mean by “Kubernetes isn’t easy” is that Kubernetes has a lot of moving parts learning how to successfully operate a highly available Kubernetes cluster is a lot of work. Like I find that with a lot of the abstractions it gives me, I need to understand what is underneath those abstractions in order to debug issues and configure things properly. I love learning new things so this doesn’t make me angry or anything, I just think it’s important to know :)

One specific example of “I can’t just rely on the abstractions” that I’ve struggled with is that I needed to learn a LOT about how networking works on Linux to feel confident with setting up Kubernetes networking, way more than I’d ever had to learn about networking before. This was very fun but pretty time consuming. I might write more about what is hard/interesting about setting up Kubernetes networking at some point.

Or I wrote a 2000 word blog post about everything I had to learn about Kubernetes’ different options for certificate authorities to be able to set up my Kubernetes CAs successfully.

I think some of these managed Kubernetes systems like GKE (google’s kubernetes product) may be simpler since they make a lot of decisions for you but I haven’t tried any of them.

Read the whole story
pfctdayelise
10 days ago
reply
Melbourne, Australia
Share this story
Delete

JavaScript got better while I wasn’t looking

1 Share

IndustrialRobot has generously donated in order to inquire:

In the last few years there seems to have been a lot of activity with adding emojis to Unicode. Has there been an equal effort to add ‘real’ languages/glyph systems/etc?

And as always, if you don’t have anything to say on that topic, feel free to choose your own. :p

Yes.

I mean, each release of Unicode lists major new additions right at the top — Unicode 10, Unicode 9, Unicode 8, etc. They also keep fastidious notes, so you can also dig into how and why these new scripts came from, by reading e.g. the proposal for the addition of Zanabazar Square. I don’t think I have much to add here; I’m not a real linguist, I only play one on TV.

So with that out of the way, here’s something completely different!

A brief history of JavaScript

JavaScript was created in seven days, about eight thousand years ago. It was pretty rough, and it stayed rough for most of its life. But that was fine, because no one used it for anything besides having a trail of sparkles follow your mouse on their Xanga profile.

Then people discovered you could actually do a handful of useful things with JavaScript, and it saw a sharp uptick in usage. Alas, it stayed pretty rough. So we came up with polyfills and jQuerys and all kinds of miscellaneous things that tried to smooth over the rough parts, to varying degrees of success.

And… that’s it. That’s pretty much how things stayed for a while.


I have complicated feelings about JavaScript. I don’t hate it… but I certainly don’t enjoy it, either. It has some pretty neat ideas, like prototypical inheritance and “everything is a value”, but it buries them under a pile of annoying quirks and a woefully inadequate standard library. The DOM APIs don’t make things much better — they seem to be designed as though the target language were Java, rarely taking advantage of any interesting JavaScript features. And the places where the APIs overlap with the language are a hilarious mess: I have to check documentation every single time I use any API that returns a set of things, because there are at least three totally different conventions for handling that and I can’t keep them straight.

The funny thing is that I’ve been fairly happy to work with Lua, even though it shares most of the same obvious quirks as JavaScript. Both languages are weakly typed; both treat nonexistent variables and keys as simply false values, rather than errors; both have a single data structure that doubles as both a list and a map; both use 64-bit floating-point as their only numeric type (though Lua added integers very recently); both lack a standard object model; both have very tiny standard libraries. Hell, Lua doesn’t even have exceptions, not really — you have to fake them in much the same style as Perl.

And yet none of this bothers me nearly as much in Lua. The differences between the languages are very subtle, but combined they make a huge impact.

  • Lua has separate operators for addition and concatenation, so + is never ambiguous. It also has printf-style string formatting in the standard library.

  • Lua’s method calls are syntactic sugar: foo:bar() just means foo.bar(foo). Lua doesn’t even have a special this or self value; the invocant just becomes the first argument. In contrast, JavaScript invokes some hand-waved magic to set its contextual this variable, which has led to no end of confusion.

  • Lua has an iteration protocol, as well as built-in iterators for dealing with list-style or map-style data. JavaScript has a special dedicated Array type and clumsy built-in iteration syntax.

  • Lua has operator overloading and (surprisingly flexible) module importing.

  • Lua allows the keys of a map to be any value (though non-scalars are always compared by identity). JavaScript implicitly converts keys to strings — and since there’s no operator overloading, there’s no way to natively fix this.

These are fairly minor differences, in the grand scheme of language design. And almost every feature in Lua is implemented in a ridiculously simple way; in fact the entire language is described in complete detail in a single web page. So writing JavaScript is always frustrating for me: the language is so close to being much more ergonomic, and yet, it isn’t.

Or, so I thought. As it turns out, while I’ve been off doing other stuff for a few years, browser vendors have been implementing all this pie-in-the-sky stuff from “ES5” and “ES6”, whatever those are. People even upgrade their browsers now. Lo and behold, the last time I went to write JavaScript, I found out that a number of papercuts had actually been solved, and the solutions were sufficiently widely available that I could actually use them in web code.

The weird thing is that I do hear a lot about JavaScript, but the feature I’ve seen raved the most about by far is probably… built-in types for working with arrays of bytes? That’s cool and all, but not exactly the most pressing concern for me.

Anyway, if you also haven’t been keeping tabs on the world of JavaScript, here are some things we missed.

let

MDN docs — supported in Firefox 44, Chrome 41, IE 11, Safari 10

I’m pretty sure I first saw let over a decade ago. Firefox has supported it for ages, but you actually had to opt in by specifying JavaScript version 1.7. Remember JavaScript versions? You know, from back in the days when people actually suggested you write stuff like this:

1
<SCRIPT LANGUAGE="JavaScript1.2" TYPE="text/javascript">

Yikes.

Anyway, so, let declares a variable — but scoped to the immediately containing block, unlike var, which scopes to the innermost function. The trouble with var was that it was very easy to make misleading:

1
2
3
4
5
6
// foo exists here
while (true) {
    var foo = ...;
    ...
}
// foo exists here too

If you reused the same temporary variable name in a different block, or if you expected to be shadowing an outer foo, or if you were trying to do something with creating closures in a loop, this would cause you some trouble.

But no more, because let actually scopes the way it looks like it should, the way variable declarations do in C and friends. As an added bonus, if you refer to a variable declared with let outside of where it’s valid, you’ll get a ReferenceError instead of a silent undefined value. Hooray!

There’s one other interesting quirk to let that I can’t find explicitly documented. Consider:

1
2
3
4
5
6
7
let closures = [];
for (let i = 0; i < 4; i++) {
    closures.push(function() { console.log(i); });
}
for (let j = 0; j < closures.length; j++) {
    closures[j]();
}

If this code had used var i, then it would print 4 four times, because the function-scoped var i means each closure is sharing the same i, whose final value is 4. With let, the output is 0 1 2 3, as you might expect, because each run through the loop gets its own i.

But wait, hang on.

The semantics of a C-style for are that the first expression is only evaluated once, at the very beginning. So there’s only one let i. In fact, it makes no sense for each run through the loop to have a distinct i, because the whole idea of the loop is to modify i each time with i++.

I assume this is simply a special case, since it’s what everyone expects. We expect it so much that I can’t find anyone pointing out that the usual explanation for why it works makes no sense. It has the interesting side effect that for no longer de-sugars perfectly to a while, since this will print all 4s:

1
2
3
4
5
6
7
8
9
closures = [];
let i = 0;
while (i < 4) {
    closures.push(function() { console.log(i); });
    i++;
}
for (let j = 0; j < closures.length; j++) {
    closures[j]();
}

This isn’t a problem — I’m glad let works this way! — it just stands out to me as interesting. Lua doesn’t need a special case here, since it uses an iterator protocol that produces values rather than mutating a visible state variable, so there’s no problem with having the loop variable be truly distinct on each run through the loop.

Classes

MDN docs — supported in Firefox 45, Chrome 42, Safari 9, Edge 13

Prototypical inheritance is pretty cool. The way JavaScript presents it is a little bit opaque, unfortunately, which seems to confuse a lot of people. JavaScript gives you enough functionality to make it work, and even makes it sound like a first-class feature with a property outright called prototype… but to actually use it, you have to do a bunch of weird stuff that doesn’t much look like constructing an object or type.

The funny thing is, people with almost any background get along with Python just fine, and Python uses prototypical inheritance! Nobody ever seems to notice this, because Python tucks it neatly behind a class block that works enough like a Java-style class. (Python also handles inheritance without using the prototype, so it’s a little different… but I digress. Maybe in another post.)

The point is, there’s nothing fundamentally wrong with how JavaScript handles objects; the ergonomics are just terrible.

Lo! They finally added a class keyword. Or, rather, they finally made the class keyword do something; it’s been reserved this entire time.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class Vector {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }

    get magnitude() {
        return Math.sqrt(this.x * this.x + this.y * this.y);
    }

    dot(other) {
        return this.x * other.x + this.y * other.y;
    }
}

This is all just sugar for existing features: creating a Vector function to act as the constructor, assigning a function to Vector.prototype.dot, and whatever it is you do to make a property. (Oh, there are properties. I’ll get to that in a bit.)

The class block can be used as an expression, with or without a name. It also supports prototypical inheritance with an extends clause and has a super pseudo-value for superclass calls.

It’s a little weird that the inside of the class block has its own special syntax, with function omitted and whatnot, but honestly you’d have a hard time making a class block without special syntax.

One severe omission here is that you can’t declare values inside the block, i.e. you can’t just drop a bar = 3; in there if you want all your objects to share a default attribute. The workaround is to just do this.bar = 3; inside the constructor, but I find that unsatisfying, since it defeats half the point of using prototypes.

Properties

MDN docs — supported in Firefox 4, Chrome 5, IE 9, Safari 5.1

JavaScript historically didn’t have a way to intercept attribute access, which is a travesty. And by “intercept attribute access”, I mean that you couldn’t design a value foo such that evaluating foo.bar runs some code you wrote.

Exciting news: now it does. Or, rather, you can intercept specific attributes, like in the class example above. The above magnitude definition is equivalent to:

1
2
3
4
5
6
7
Object.defineProperty(Vector.prototype, 'magnitude', {
    configurable: true,
    enumerable: true,
    get: function() {
        return Math.sqrt(this.x * this.x + this.y * this.y);
    },
});

Beautiful.

And what even are these configurable and enumerable things? It seems that every single key on every single object now has its own set of three Boolean twiddles:

  • configurable means the property itself can be reconfigured with another call to Object.defineProperty.
  • enumerable means the property appears in for..in or Object.keys().
  • writable means the property value can be changed, which only applies to properties with real values rather than accessor functions.

The incredibly wild thing is that for properties defined by Object.defineProperty, configurable and enumerable default to false, meaning that by default accessor properties are immutable and invisible. Super weird.

Nice to have, though. And luckily, it turns out the same syntax as in class also works in object literals.

1
2
3
4
5
6
Vector.prototype = {
    get magnitude() {
        return Math.sqrt(this.x * this.x + this.y * this.y);
    },
    ...
};

Alas, I’m not aware of a way to intercept arbitrary attribute access.

Another feature along the same lines is Object.seal(), which marks all of an object’s properties as non-configurable and prevents any new properties from being added to the object. The object is still mutable, but its “shape” can’t be changed. And of course you can just make the object completely immutable if you want, via setting all its properties non-writable, or just using Object.freeze().

I have mixed feelings about the ability to irrevocably change something about a dynamic runtime. It would certainly solve some gripes of former Haskell-minded colleagues, and I don’t have any compelling argument against it, but it feels like it violates some unwritten contract about dynamic languages — surely any structural change made by user code should also be able to be undone by user code?

Slurpy arguments

MDN docs — supported in Firefox 15, Chrome 47, Edge 12, Safari 10

Officially this feature is called “rest parameters”, but that’s a terrible name, no one cares about “arguments” vs “parameters”, and “slurpy” is a good word. Bless you, Perl.

1
2
3
function foo(a, b, ...args) {
    // ...
}

Now you can call foo with as many arguments as you want, and every argument after the second will be collected in args as a regular array.

You can also do the reverse with the spread operator:

1
2
3
4
5
let args = [];
args.push(1);
args.push(2);
args.push(3);
foo(...args);

It even works in array literals, even multiple times:

1
2
let args2 = [...args, ...args];
console.log(args2);  // [1, 2, 3, 1, 2, 3]

Apparently there’s also a proposal for allowing the same thing with objects inside object literals.

Default arguments

MDN docs — supported in Firefox 15, Chrome 49, Edge 14, Safari 10

Yes, arguments can have defaults now. It’s more like Sass than Python — default expressions are evaluated once per call, and later default expressions can refer to earlier arguments. I don’t know how I feel about that but whatever.

1
2
3
function foo(n = 1, m = n + 1, list = []) {
    ...
}

Also, unlike Python, you can have an argument with a default and follow it with an argument without a default, since the default default (!) is and always has been defined as undefined. Er, let me just write it out.

1
2
3
function bar(a = 5, b) {
    ...
}

Arrow functions

MDN docs — supported in Firefox 22, Chrome 45, Edge 12, Safari 10

Perhaps the most humble improvement is the arrow function. It’s a slightly shorter way to write an anonymous function.

1
2
3
(a, b, c) => { ... }
a => { ... }
() => { ... }

An arrow function does not set this or some other magical values, so you can safely use an arrow function as a quick closure inside a method without having to rebind this. Hooray!

Otherwise, arrow functions act pretty much like regular functions; you can even use all the features of regular function signatures.

Arrow functions are particularly nice in combination with all the combinator-style array functions that were added a while ago, like Array.forEach.

1
2
3
[7, 8, 9].forEach(value => {
    console.log(value);
});

Symbol

MDN docs — supported in Firefox 36, Chrome 38, Edge 12, Safari 9

This isn’t quite what I’d call an exciting feature, but it’s necessary for explaining the next one. It’s actually… extremely weird.

symbol is a new kind of primitive (like number and string), not an object (like, er, Number and String). A symbol is created with Symbol('foo'). No, not new Symbol('foo'); that throws a TypeError, for, uh, some reason.

The only point of a symbol is as a unique key. You see, symbols have one very special property: they can be used as object keys, and will not be stringified. Remember, only strings can be keys in JavaScript — even the indices of an array are, semantically speaking, still strings. Symbols are a new exception to this rule.

Also, like other objects, two symbols don’t compare equal to each other: Symbol('foo') != Symbol('foo').

The result is that symbols solve one of the problems that plauges most object systems, something I’ve talked about before: interfaces. Since an interface might be implemented by any arbitrary type, and any arbitrary type might want to implement any number of arbitrary interfaces, all the method names on an interface are effectively part of a single global namespace.

I think I need to take a moment to justify that. If you have IFoo and IBar, both with a method called method, and you want to implement both on the same type… you have a problem. Because most object systems consider “interface” to mean “I have a method called method, with no way to say which interface’s method you mean. This is a hard problem to avoid, because IFoo and IBar might not even come from the same library. Occasionally languages offer a clumsy way to “rename” one method or the other, but the most common approach seems to be for interface designers to avoid names that sound “too common”. You end up with redundant mouthfuls like IFoo.foo_method.

This incredibly sucks, and the only languages I’m aware of that avoid the problem are the ML family and Rust. In Rust, you define all the methods for a particular trait (interface) in a separate block, away from the type’s “own” methods. It’s pretty slick. You can still do obj.method(), and as long as there’s only one method among all the available traits, you’ll get that one. If not, there’s syntax for explicitly saying which trait you mean, which I can’t remember because I’ve never had to use it.

Symbols are JavaScript’s answer to this problem. If you want to define some interface, you can name its methods with symbols, which are guaranteed to be unique. You just have to make sure you keep the symbol around somewhere accessible so other people can actually use it. (Or… not?)

The interesting thing is that JavaScript now has several of its own symbols built in, allowing user objects to implement features that were previously reserved for built-in types. For example, you can use the Symbol.hasInstance symbol — which is simply where the language is storing an existing symbol and is not the same as Symbol('hasInstance')! — to override instanceof:

1
2
3
4
5
6
7
8
// oh my god don't do this though
class EvenNumber {
    static [Symbol.hasInstance](obj) {
        return obj % 2 == 0;
    }
}
console.log(2 instanceof EvenNumber);  // true
console.log(3 instanceof EvenNumber);  // false

Oh, and those brackets around Symbol.hasInstance are a sort of reverse-quoting — they indicate an expression to use where the language would normally expect a literal identifier. I think they work as object keys, too, and maybe some other places.

The equivalent in Python is to implement a method called __instancecheck__, a name which is not special in any way except that Python has reserved all method names of the form __foo__. That’s great for Python, but doesn’t really help user code. JavaScript has actually outclassed (ho ho) Python here.

Of course, obj[BobNamespace.some_method]() is not the prettiest way to call an interface method, so it’s not perfect. I imagine this would be best implemented in user code by exposing a polymorphic function, similar to how Python’s len(obj) pretty much just calls obj.__len__().

I only bring this up because it’s the plumbing behind one of the most incredible things in JavaScript that I didn’t even know about until I started writing this post. I’m so excited oh my gosh. Are you ready? It’s:

Iteration protocol

MDN docs — supported in Firefox 27, Chrome 39, Safari 10; still experimental in Edge

Yes! Amazing! JavaScript has first-class support for iteration! I can’t even believe this.

It works pretty much how you’d expect, or at least, how I’d expect. You give your object a method called Symbol.iterator, and that returns an iterator.

What’s an iterator? It’s an object with a next() method that returns the next value and whether the iterator is exhausted.

Wait, wait, wait a second. Hang on. The method is called next? Really? You didn’t go for Symbol.next? Python 2 did exactly the same thing, then realized its mistake and changed it to __next__ in Python 3. Why did you do this?

Well, anyway. My go-to test of an iterator protocol is how hard it is to write an equivalent to Python’s enumerate(), which takes a list and iterates over its values and their indices. In Python it looks like this:

1
2
3
4
5
for i, value in enumerate(['one', 'two', 'three']):
    print(i, value)
# 0 one
# 1 two
# 2 three

It’s super nice to have, and I’m always amazed when languages with “strong” “support” for iteration don’t have it. Like, C# doesn’t. So if you want to iterate over a list but also need indices, you need to fall back to a C-style for loop. And if you want to iterate over a lazy or arbitrary iterable but also need indices, you need to track it yourself with a counter. Ridiculous.

Here’s my attempt at building it in JavaScript.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function enumerate(iterable) {
    // Return a new iter*able* object with a Symbol.iterator method that
    // returns an iterator.
    return {
        [Symbol.iterator]: function() {
            let iterator = iterable[Symbol.iterator]();
            let i = 0;

            return {
                next: function() {
                    let nextval = iterator.next();
                    if (! nextval.done) {
                        nextval.value = [i, nextval.value];
                        i++;
                    }
                    return nextval;
                },
            };
        },
    };
}
for (let [i, value] of enumerate(['one', 'two', 'three'])) {
    console.log(i, value);
}
// 0 one
// 1 two
// 2 three

Incidentally, for..of (which iterates over a sequence, unlike for..in which iterates over keys — obviously) is finally supported in Edge 12. Hallelujah.

Oh, and let [i, value] is destructuring assignment, which is also a thing now and works with objects as well. You can even use the splat operator with it! Like Python! (And you can use it in function signatures! Like Python! Wait, no, Python decided that was terrible and removed it in 3…)

1
let [x, y, ...others] = ['apple', 'orange', 'cherry', 'banana'];

It’s a Halloween miracle. 🎃

Generators

MDN docs — supported in Firefox 26, Chrome 39, Edge 13, Safari 10

That’s right, JavaScript has goddamn generators now. It’s basically just copying Python and adding a lot of superfluous punctuation everywhere. Not that I’m complaining.

Also, generators are themselves iterable, so I’m going to cut to the chase and rewrite my enumerate() with a generator.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
function enumerate(iterable) {
    return {
        [Symbol.iterator]: function*() {
            let i = 0;
            for (let value of iterable) {
                yield [i, value];
                i++;
            }
        },
    };
}
for (let [i, value] of enumerate(['one', 'two', 'three'])) {
    console.log(i, value);
}
// 0 one
// 1 two
// 2 three

Amazing. function* is a pretty strange choice of syntax, but whatever? I guess it also lets them make yield only act as a keyword inside a generator, for ultimate backwards compatibility.

JavaScript generators support everything Python generators do: yield* yields every item from a subsequence, like Python’s yield from; generators can return final values; you can pass values back into the generator if you iterate it by hand. No, really, I wasn’t kidding, it’s basically just copying Python. It’s great. You could now built asyncio in JavaScript!

In fact, they did that! JavaScript now has async and await. An async function returns a Promise, which is also a built-in type now. Amazing.

Sets and maps

MDN docs for MapMDN docs for Set — supported in Firefox 13, Chrome 38, IE 11, Safari 7.1

I did not save the best for last. This is much less exciting than generators. But still exciting.

The only data structure in JavaScript is the object, a map where the strings are keys. (Or now, also symbols, I guess.) That means you can’t readily use custom values as keys, nor simulate a set of arbitrary objects. And you have to worry about people mucking with Object.prototype, yikes.

But now, there’s Map and Set! Wow.

Unfortunately, because JavaScript, Map couldn’t use the indexing operators without losing the ability to have methods, so you have to use a boring old method-based API. But Map has convenient methods that plain objects don’t, like entries() to iterate over pairs of keys and values. In fact, you can use a map with for..of to get key/value pairs. So that’s nice.

Perhaps more interesting, there’s also now a WeakMap and WeakSet, where the keys are weak references. I don’t think JavaScript had any way to do weak references before this, so that’s pretty slick. There’s no obvious way to hold a weak value, but I guess you could substitute a WeakSet with only one item.

Template literals

MDN docs — supported in Firefox 34, Chrome 41, Edge 12, Safari 9

Template literals are JavaScript’s answer to string interpolation, which has historically been a huge pain in the ass because it doesn’t even have string formatting in the standard library.

They’re just strings delimited by backticks instead of quotes. They can span multiple lines and contain expressions.

1
2
console.log(`one plus
two is ${1 + 2}`);

Someone decided it would be a good idea to allow nesting more sets of backticks inside a ${} expression, so, good luck to syntax highlighters.

However, someone also had the most incredible idea ever, which was to add syntax allowing user code to do the interpolation — so you can do custom escaping, when absolutely necessary, which is virtually never, because “escaping” means you’re building a structured format by slopping strings together willy-nilly instead of using some API that works with the structure.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// OF COURSE, YOU SHOULDN'T BE DOING THIS ANYWAY; YOU SHOULD BUILD HTML WITH
// THE DOM API AND USE .textContent FOR LITERAL TEXT.  BUT AS AN EXAMPLE:
function html(literals, ...values) {
    let ret = [];
    literals.forEach((literal, i) => {
        if (i > 0) {
            // Is there seriously still not a built-in function for doing this?
            // Well, probably because you SHOULDN'T BE DOING IT
            ret.push(values[i - 1]
                .replace(/&/g, '&amp;')
                .replace(/</g, '&lt;')
                .replace(/>/g, '&gt;')
                .replace(/"/g, '&quot;')
                .replace(/'/g, '&apos;'));
        }
        ret.push(literal);
    });
    return ret.join('');
}
let username = 'Bob<script>';
let result = html`<b>Hello, ${username}!</b>`;
console.log(result);
// <b>Hello, Bob&lt;script&gt;!</b>

It’s a shame this feature is in JavaScript, the language where you are least likely to need it.

Trailing commas

Remember how you couldn’t do this for ages, because ass-old IE considered it a syntax error and would reject the entire script?

1
2
3
4
5
{
    a: 'one',
    b: 'two',
    c: 'three',  // <- THIS GUY RIGHT HERE
}

Well now it’s part of the goddamn spec and if there’s anything in this post you can rely on, it’s this. In fact you can use AS MANY GODDAMN TRAILING COMMAS AS YOU WANT. But only in arrays.

1
[1, 2, 3,,,,,,,,,,,,,,,,,,,,,,,,,]

Apparently that has the bizarre side effect of reserving extra space at the end of the array, without putting values there.

And more, probably

Like strict mode, which makes a few silent “errors” be actual errors, forces you to declare variables (no implicit globals!), and forbids the completely bozotic with block.

Or String.trim(), which trims whitespace off of strings.

Or… Math.sign()? That’s new? Seriously? Well, okay.

Or the Proxy type, which lets you customize indexing and assignment and calling. Oh. I guess that is possible, though this is a pretty weird way to do it; why not just use symbol-named methods?

You can write Unicode escapes for astral plane characters in strings (or identifiers!), as \u{XXXXXXXX}.

There’s a const now? I extremely don’t care, just name it in all caps and don’t reassign it, come on.

There’s also a mountain of other minor things, which you can peruse at your leisure via MDN or the ECMAScript compatibility tables (note the links at the top, too).

That’s all I’ve got. I still wouldn’t say I’m a big fan of JavaScript, but it’s definitely making an effort to clean up some goofy inconsistencies and solve common problems. I think I could even write some without yelling on Twitter about it now.

On the other hand, if you’re still stuck supporting IE 10 for some reason… well, er, my condolences.

Read the whole story
pfctdayelise
10 days ago
reply
Melbourne, Australia
Share this story
Delete

Save Your Work

1 Comment and 5 Shares
Here's a useful habit I've picked up as a software engineer. Every time you do something difficult, create a reproducible artifact that can be used to do it more easily next time, and shared with others.

Some examples of this:

  • You spent all afternoon debugging a thorny issue. Write down the monitoring you checked and the steps you took to reach the conclusion you did. Put these details in the issue tracker, before moving on to actually fix it.
  • You figured out what commands to run to get the binary to work properly. Turn the commands into a short script and check it into source control.
  • You spent a day reading the code and figuring out how it works. Write yourself some notes and documentation as you go. At the end, take half an hour to clean it up and send it to your boss or teammates who might find it helpful. Maybe even put up a documentation website if that seems appropriate.

This makes it easier to pick up where you left off for next time (for you or someone else), and makes it easier to prove that the work you're doing is difficult and has value.
Read the whole story
pfctdayelise
19 days ago
reply
Melbourne, Australia
mindspillage
20 days ago
reply
Mountain View, California
Share this story
Delete
1 public comment
luizirber
16 days ago
reply
Great tips!
Davis, CA

Academic writing is like a painful, upper middle class dinner party

2 Comments and 3 Shares

This blog post is part of a series dedicated to developing ideas for a new book I am writing with Shaun Lehmann (@painlessprose on Twitter) and Katherine Firth of the Research Voodoo blog. “Writing Trouble” will be a Swiss army knife of a book, containing range of strategies and tactics for fixing academic writing that is good, but not yet great.

We generated chapter titles from the bad feedback PhD students have told us about over the years. Parts of this post will end up in chapter two: “Your writing doesn’t sound very academic”: how to convince your reader you belong”. The book will be published by Open University Press and will hopefully be out in late 2018. If you’re interested in knowing more about the book before we publish, you can sign up for our writing trouble mailing list.

Although I got reasonable marks for my creative essays in high school,  literary criticism was never my strong suit. One of the issues with my analytical writing was that I didn’t really understand how to use verbs.  It wasn’t until I nearly finished my masters degree that I found out that verbs function in academic conversation much like table manners at a middle class dinner party.

Let me explain.

I owe much of my education in verbs to the good work of Pat Thomson and Barbara Kamler and their excellent book ‘Helping Doctoral Students Write’. This book was crucial for helping me understand that in humanities writing, the verb you use to describe someone else’s work indicates your feeling about the quality of the work. For instance, “Mewburn (2010) argues…” is kinder than “Mewburn (2010) asserts…”. By using the verb ‘argues’ I invite the reader to consider that what Mewburn is doing is actually arguing – a scholar who asserts is not really a scholar at all.

Looking up the verbs in a dictionary makes the difference quite plain. According to Google, the first definition of ‘argues’ is “give reasons or cite evidence in support of an idea, action, or theory, typically with the aim of persuading others to share one’s view.” By contrast, the definition for ‘asserts’ is “cause others to recognize (one’s authority or a right) by confident and forceful behavior”. In the humanities, at least these days, we are meant to make knowledge by persuasion, not through authority. Authority is used more often in political or religious arguments. If you read back into the history of Western academia, you will find examples of writing that seems very strange to contemporary eyes. The tone is much more commanding and confident – this was because the origins of Western universities were monastic and it was acceptable to make an argument on the grounds that God had ordained something.

Times have changed (despite what some Australian politicians would like to think). When you think about it, most academic writing is highly passive aggressive. By using a verb to express your evaluation of someone else’s work you avoid directly stating your opinion, leaving it up to the reader to infer what you think. To read between the lines if you like. In academic writing you would never, for example, write “Mewburn (2010) is shit – don’t bother reading this paper. She’s a rubbish scholar”. You’d say something like: “Mewburn (2010) relies on insufficient evidence”.

You mean the same thing, but it’s you know – polite. At least it’s polite according to dominant cultural norms in academia which, it’s important to recognise, are not ‘natural’. While some people struggle mightily with the idea that verbs are like manners at a middle class dinner party, Indigenous students, and people who are first in family to get to University, tend to get it straight away. When I shared this analogy with one Wiradjuri woman she laughed and said “Right, so to succeed in the academy I have to write like an uptight white person? That makes perfect sense. I’m surrounded by them all the time”.

Sadly true.

Kamler and Thomson were writing for humanities scholars, but their work led me to develop an interest in deep nerd grammar within the sciences. The most interesting difference between science writing and humanities writing is the use of verbs, or rather – the lack of them. When scientists are evaluating the work of other scientists they tend to drop the verb altogether. In the brilliant “Disciplinary Discourses: social interactions in academic writing” (told you it was nerdy) Ken Hyland points out that scientists will make a statement and then put the reference for the fact at the end of the sentence, like so (totally made up example):

“The molecules in saline solutions cluster together tightly (Mewburn et al, 2010)”.

By placing the reference at the end and not associating it with a verb, the scientist ‘imports’ this idea without comment and effectively expects the reader to accept the idea as fact. Even when they do include verbs, scientists do it in ‘sciencey’ ways. If the scientist was inclined to more ‘flowerly’ language, they might use a neutral verb, for instance:

“It has been shown that molecules in saline solutions cluster together tightly (Mewburn et al, 2010)”

In this sentence, the passsive voice functions to leave out the identity of the person who showed how the molecules cluster, that’s because, generally, in the sciences the identity of the person who did the work is irrelevant. Scientists are assumed to be identical to each other and employ scientific methods and procedures exactly the same way. This point of view has been questioned by some who argue that scientists are human like the rest of us, but that’s not a Pandora’s box that I need to open here. To complicate matters further, not all scientists use verbs in this way all the time. Hyland points out that Biologists are the outliers of the science world and tend to deploy verbs much more like humanities people. In other words, it’s complicated, but you need to know the norms of your ‘tribal dialect’ to fit in.

So how can you operationalise this knowledge? Well, unless you want to take a risk challenge academic norms (and hey – don’t let me stop you!), give your writing an ‘uptight white person’ make over. Grab a few papers from scholars you admire and make a list of the verbs they use. Then cluster the verbs into three columns based on a passive aggressive index: “this work is great”, “This work is fine” and “this work is terrible”. You can look at my own verb cheat sheet as a model, but you’re best advised to make your own.

When you’re finished, stick your cheat sheet to your wall. While you are doing your literature review, examine your feelings about the work you are reading, and then pick a verb from the list that fits your judgment. Varied verb use will make your writing more interesting and precise If you are a science student, closely examine your own verb placement and compare it to work in your discipline – could you afford to use a few more verbs? Or do you need to pare it back?

I hope that’s clear – I’ll be making edits when I put this post into the book, so your questions are helpful!

More Writing Trouble posts:

Don’t let those ‘sticky words’ confuse your examiners

The vagueness problem in academic writing






Read the whole story
claudinec
19 days ago
reply
“Right, so to succeed in the academy I have to write like an uptight white person? That makes perfect sense. I’m surrounded by them all the time.”
Melbourne, Australia
pfctdayelise
19 days ago
reply
Melbourne, Australia
Share this story
Delete
1 public comment
duerig
18 days ago
reply
I write in the sciences and this is pretty accurate. I'd add two extra subtleties.

First, for science writing, there is a difference between citation in 'related work' sections and citations elsewhere. In the 'related work' section, we cite more like the humanities folks do. And it often sounds like passive-aggressive insults. Because the purpose of the related work section is to both acknowledge similar contributions, but also show how your contribution is different and better.

Second, in the rest of the paper, I use citations almost exclusively when I want to make a non-controversial assertion. The thesis of the paper as a whole is a controversial assertion that I am attempting to back up with reasoning, data, and assertions that aren't subject to controversy. So the citations act as annotations that let me tag certain things as reliable, already-known, and understood to undergird my main argument.

It is actually pretty rare for one paper to refute another in my field. If a paper is no longer considered reliable, it is much more likely that it will just no longer be cited.
Next Page of Stories