Using #in?

??? words · ??? min read

This is a work in progress from The Pipeline. It will likely change before it is published to the main listing of articles. It is currently at the "hidden" stage.

One of the active support extensions that I’ve grown to like (yes, they do exist) is the Object#in? method.

TODO: better intro

TODO: use a different word to refer to the grammatical object, as distinct from the programming concept.

Active And Passive Voice

English, both written and spoken, has the concept of active and passive voice.

Active voice is when the grammatical subject of the sentence is the agent: the person or thing which performs the action[^This is a simplified, not comprehensive, definition]. For example, “I knocked on the door” is written in active voice because the subject is “I”, and I am the one who knocks.

Conversely, passive voice is when the grammatical subject is the recipient: the person or thing being acted upon[^Again, this is a simplification]. A classic example of passive voice is the sentence “mistakes were made”, where the subject is “mistakes”. The mistakes are being acted upon (being made) by a deliberately-unspecified actor (usually a politician).

Active voice is generally preferable to passive voice. Both voices are grammatically correct and have particular use cases, but active voice is considered to be more direct and clear. There are a few possible reasons for this:

  1. Placing the agent at the beginning of a sentence provides useful context that makes the rest of the sentence easier to mentally digest.

  2. Native English speakers, or perhaps humans in general, might process sentences better if the agent comes before the action being taking.

  3. Passive voice provides less information, because it allows the agent to be omitted from the sentence, unlike active voice where the agent is mandatory.

Whatever the case may be, readability is likely affected by the ordering of agent and action within a sentence.

Identifier Ordering In Code

There are similarities between active/passive voice and the ways that code can be written.

Consider the implementation of a function that takes two arguments, in an object-oriented language. There are generally three places where this could be implemented as a method: on the first argument, on the other argument, or on some other object. As an example, a method that chops wood with an axe could be designed in these three ways:

  1. axe.chop(wood)
  2. wood.chop(axe)
  3. lumberjill.chop(wood, axe)

The chop method is quite clearly the action, but the agent and the recipient are not so clear. Is it best to consider the agent to be the axe, or the lumberjill? Or can wood have agency, and be capable of chopping itself? These might seem like silly questions, because most English speakers will quickly arrive at an intuitive answer.

But we don’t need to look far to find real-world examples of all three, in code. A string can find matches in itself (string.match(regex)), or a regular expression can find matches in a string (regex.match(string)), or a pattern-matching engine can find matches in a string for a given pattern (engine.match(string, regex)). Intuition becomes blurry in the context of the ethereal thoughtstuff that is software design[^This problem is more specific to object-oriented design than it is to software design in general. Users of Lisp and other functional languages will inevitably congratulate themselves for their impeccable taste, while ignoring the larger point about how humans repurpose their natural language faculties to understand code, which may partially explain why these programming languages have low rates of adoption.].

Viewing Code Through The Lens Of English

The most intuitive approach to chopping wood, in the context of English and Ruby, is probably lumberjill.chop(wood, with: axe). The method is called on the agent, the recipient is passed in as an argument, and the axe is differentiated from the recipient using a keyword argument.

In English, “with an axe” is an adjunct: an optional or structurally-dispensable part of the sentence that provides additional information. For example, “the lumberjill chopped wood” is a perfectly cromulent sentence without the addition of “with an axe”. Adjuncts align nicely with keyword arguments in Ruby, which are often used to pass additional “options” to a method.

But the end goal is not to make code look like English, or any other natural language.

This is the case for all functions of two arguments, implemented as a method. The method can exist on either of the arguments, or on some other object which takes both arguments.

The code that is closest to typical English is lumberjill.chop(wood, with: axe). The subject, verb, and object are quite clear. Even the adjunct axe is differentiated from the object wood by using a keyword argument that is intuitive to English speakers.

Got questions? Comments? Milk?

Shoot an email to [email protected] or hit me up on Twitter (@tom_dalling).

← Previously: My Post

Next up: You Are Not Your Code →

Join The Pigeonhole

Don't miss the next post! Subscribe to Ruby Pigeon mailing list and get the next post sent straight to your inbox.