I was rereading Lydia Goehr’s The Imaginary Museum of Musical Works the other
evening after a long day spent translating several of
music21’s
score-representation code packages from Python to JavaScript (for
music21j). What struck me when I was reading the introduction, which
lays out several pre-existing theories about the work-concept, and the
relationship(s) among the musical idea, the building blocks of scores
(pitches, etc.), the score-copy, and performances, was my own need to
take a stand on the proper relationships of such conceptions when
choosing a computational language in which to express musical languages.
Those who haven’t programmed may not know that no modern computer
program (or very very few) is built from a single code file, or
flowchart leading from input to output. Instead each program is built
from components (a file browser, a set of functions for manipulating
canvases for drawing, a module for representing tempo) that can be
called upon by other components in a systematized but reusable and
testable manner. These get bundled or packed or linked together to
make a complete or extensible application or library. Different
philosophies exist about which structures (or ontologies, to use a
word with related but quite different meanings between the humanities
and computer science) can be well-formed or desirable.
These philosophies about file linking—importing and exporting—lie
close to the marrow of the designs of various computer languages and in
many cases evolved in response to the environments within which the
languages were originally created. Python, a language run on
individual computers that came of age in the era of fast hard drives
and, from the user’s perspective, near instantaneous loading of small
files, aims to put as few limitations on the possible relationships
between modules as possible. JavaScript, on the other hand, which
appeared first on the web in the time of dialup internet and unreliable
connections, has, even in its most recent incarnations, placed sharper
restrictions on connecting resources in the name of efficiency.
Translating music analysis software from the first language to the
other has raised complex problems for the representation of music in
code. Python allowed me to interweave different levels of musical
thought, such that notes could will into existence a measure (say by
asking for the creation of an object to encompass them) while a measure
could in another context give birth to notes (for instance by asking
for a suitable number to fill it, given some metrical, harmonic, and
accentual constraints). A score could of course be a container to many
measures, but a measure could also be linked or contain many scores
(for instance as a key or heading to a catalogue of quotations or
standard topoi). As I created the original music21 in Python, I reveled
in the multiplicity of possible relationships, in the way some musical
philosophers might argue that a score gives rise to a performance
which, if transcribed or imagined, gives rise to a new score, which
gives rise to a new performance, and so on to infinity.
Rewriting the “same code” posed, and continues to pose, a challenge to my
ecumenical notion of musical relationships. (With “same code” in
quotation marks since the work-concept-concept for computer works has
not been the subject of nearly so much rumination.) In JavaScript, in
order to make sure that everything has been loaded before the user
closes her browser in frustration, in general if one module (A) uses
another module (B) in its code, then the second module (B) cannot use,
or import, the first (A) into its code. What some, perhaps those trained
as humanists, might exult as a beautiful web of inter-compu-textuality,
is called a cyclic or circular dependency and it is easy to find
categorial pronouncements that such things are
bad or the result of lazy or sloppy thinking. They
resist creating a hierarchy of elements, and prevent creating beautiful
tree structures that are, or at least were during the time when
computers were problem-solving devices and not enablers of exploration,
the key to moving in an efficient manner from point A to point Z without
getting into an endless loop somewhere around J to M. (A programmer—who
had apparently gotten too deep into the trenches of coding to remember
that the terms which undergird so many computational structures are
metaphors—once criticized a part of my code that had many pointers
running up and down a hierarchy by saying, “This is absurd! A child
cannot have more than one parent.”)
In Python, I could say that a Note in the presence of another Note
created an Interval. (Like in German, in most computer languages, nouns,
or Objects, are capitalized.) And, I could simultaneously say that an
Interval, given a starting Note for reference, could define a second
Note that fulfilled it. Both of these generating relationships seemed
not just plausible, but natural and essential to a full representation
of the complexity of music. The ambiguity of which came first, the
interval or the note can never be resolved. In JavaScript, however, the
programming musicologist is left with a decision to be made: either
Notes can create Intervals or Intervals can create Notes, but not both.
The work creates the score (or performance), or the performance or the
score creates the work, but not both. The one who is able to create both
Notes and Intervals is an entity that stands outside the system—the
calling program—which is perhaps better named “the observer” in the
best literary criticism traditions, since the network of Notes and
Intervals cannot operate with knowledge that it exists.
(To be fair, there are some complex and fragile ways to work with
circular dependencies in JavaScript, and in Python, true circular
dependencies are also impossible: either the Note can only become aware
of its ability to create Intervals at the moment of action [an import
nested in a method] or vice versa.)
I have found that programming musical logic has sharpened my awareness
of the ambiguities, hierarchies, and underdefined elements of music. By
underdefined elements, I suggest: is the interval from E# to Fb an
ascending doubly-diminished second or a descending doubly-diminished
second? If spelling matters more than sound, such that C-G is consonant
but Dbb-G is dissonant, is the bass of a chord beginning on
E##-Fbb-Bb the E## or the Fbb? (If it’s the Fbb, then is a
B###-Dbbb-F# chord in root position or first inversion? If the E##,
does that mean that we cannot determine the bass of a chord by ear?)
These may be absurdities to practicing musicians but deciding a “right
answer” to them makes all the difference in how standard musical
relationships should be represented and encoded.
It is extremely difficult to tell a computer to hold off on making a
decision or to leave a paradox in place to solve later. The human
ability (flaw?) in being able to reason around ambiguity, or to hold
conflicting ideas without breaking down, is a capacity that those who
design practical computing systems have either not been able to
replicate or have deliberately chosen not to. Within the limited
choices, I have generally been drawn to computing frameworks that let
me come as close as possible to representing multiple perspectives.
(Ironically, I’ve found the closest match so far in Python, despite its
community adopting a motto that says there should be only one way to do
it.) There is a danger that when good but still inadequate tools are
used to model human behavior and creativity, eventually human behavior
will bend to suit the tools, rather than the other way around. It is a
force that those who design and use these tools must be aware of and
continually fight against.
(updated 2022.02.03 — corrected "revealed" to "reveled")
(updated 2026.02.08 — correct minor grammar issues, fixed broken links.)
(updated 2026.02.08 — correct minor grammar issues, fixed broken links.)