Bad javascript language design choices

The category discussions about weird JavaScript things is a large and amusing one, probably best exemplified by Gary Bernhardt's Wat lightning talk. I'd like to focus on two I haven't seen discussed as much (though I may simply have overlooked the canonical article). First, const doesn't work the way it ought to, and second, indexOf's magic number thing is godawful. const doesn't solve the problem it ought to solve. Consider this situation:

Carried on: bags

(This is part 3 of a series on the bag/multiset data structure. Check out parts 1 and 2.) Improving the hash function So our bag works per our tests. Let's take a look at the naïve implementation of hashing, at least for strings: // This is the equivalent of `impl`ing a trait in Rust. type String = Hashable; // https://stackoverflow.com/a/8076436/3396324 String.prototype.hashCode = function(): number { return [...this].reduce((hash, character) => { hash = (hash << 5) - hash + character.

Implementing a bag

In my previous post, I talked about a bag data structure, which is like a set that allows repeated occurrences of the same value. In this post I will discuss my naïve implementation that has the goal of O(1) best case insertion, search, and deletion. You can follow along by viewing the code at https://www.github.com/ethan826/bag. In the next post I'll discuss improvements to consider, mostly around improving the hash function and considering load factor.

That's my bag, baby

(This is part of a series of articles. The next one is here.) When we want a collection with elements that may repeat, we generally reach for an array, list, vector, etc. When we want a collection with elements that don't or whose repeats we don't care about, we generally reach for a set. Efficient set implementations often don't track insertion order. For hashsets, that's because they hash their input and organize based on that hashed value.

Breaking out of the fold

This article addresses an issue alluded to in my previous one. Namely, we sometimes want to break out of the iteration within fold, but it is not easy to do that in many languages. fold has a problem with short-circuiting. In defining any and all by using fold, as we did in the previous article, we did not short-circuit. But we'd get a better constant factor for our time complexity if we can break from those methods once we know the final outcome.

I fold!

This article is a love letter to fold, a.k.a. reduce, a.k.a. inject.1 I love fold for three reasons. First, it is useful in a wide variety of programming contexts. Second, it is a ladder between different levels of abstraction: it is simple to define, but allows operating on collections more abstractly. Third, it can have the same API but be defined based on looping or recursion, and so can help you solve similar problems in similar ways despite coding in different paradigms.

Priors

There's a lyric in a They Might Be Giants song:1 Now you're the only one here,Who can tell me if it's true:That you love me,And I love me. The lyric is effective because it uses our expectations of rhyme scheme, parallelism, and reciprocity to have us all but certain that the final line of the verse will end with you. And the surprise serves a purpose: it uses the flouting of our expectations as a way of making us feel the potency of the narrator's self-centeredness.

Types Are for People, not Computers

Types—in the static-typing sense—are useful because they help people, not computers. Oh sure, we use them, in part, to subdue the compiler or meet some need peculiarly arising from our computer. But types are valuable because they are a way of communicating. Type systems are a way of communicating. Type systems are a way of announcing what you understand, expect, or intend. Good type systems let you do so at the level of abstraction you choose.

Limiting the scope of mutation

Functional programming teaches us about the dangers of mutability. But some object-oriented code mutates variables freely, in different scopes, along different code paths, and in many places. To maintain our ability to reason about code, we can learn from functional programming and treat mutation as a risk to be managed. Even if we stop short of mandatory immutability and using constructs like monads, we can still manage mutations and recognize them as a source of bugs and confusion.