I was recently flattered by a former colleague, Ilya Rostovtsev, about my knowledge of computer programming languages. I was surprised because I have
always found I have so much more to learn about programming itself
and the languages we use.
I have been asked recently by potential employers to rate my knowledge
of particular languages. Most of the languages I use regularly
are in significant motion - not just in terms of language features but
also in the paradigms communities are inventing to use them. This makes
my judgements of myself rather challenging. I am an expert C programmer because that languages has largely stabilized and I have used it a lot. As for C++ it feels like playing "snakes and ladders: from intermediate to expert as C++
and its use evolves. An encouraging trend in recent releases is welcome compensations for the challenging syntactic complexities templates introduced. It's impressive how C++ has been able to track ideas from other languages and communities and integrate those paradigms. Here is an example of how much cleaner code can be with (C++17): https://adrianfreed.com/content/c-container-output-stream-header-file
I am an expert and experienced programmer - expert because
I have addressed challenges that stretch what programming languages and computer
systems can be used for - experienced because I have done this many times
over the years.
Early on these challenges were stupidly mechanical like
punching holes in paper tape, in cards with a stylus (remember the hanging chads?),
and with an electronic punch. I never managed to get the endless microcassettes of the Sinclair
PC to reliably store anything.
Another significant constraint in the early days was limited computer memory.
I developed a C compiler for the 8085 processor
I used in
a home-built computer in the late 1970s. The assembler programming class I was taking at college at the time
required us to run our code on 6809 development boards which were suprisingly similar
in capability and complexity to the original Arduinos. I got a 6809 C code generator going to do those
assignments. I managed to skirt around programming very much assembler code by this
method. When I was trying to squeeze code into the limited memory I could afford I discovered
the “readonly” reserved keyword in the PCC front end
which I used to direct strings and constants into the EPROM of my
DIY computer. I wasn’t very happy with the way this was defined
in the early C compilers (as
a storage class designator like static, register, volatile and auto). This prompted
me to start correspondence with Dennis Ritchie and Steve Johnson (author of PCC) at Bell Labs. on how to proceed.
It turned out that a few others had also started developing compilers for small microprocessors. What emerged
eventually was of course “const” a type modifier which was much more flexible (allowing for const pointers for example).
In 1981, a colleague from the Unversity of New South Wales (UNSW), Peter Ivanov, proposed we take advantage of an interesting feature of “round the world” airline tickets
- unlimited North America air travel. We visited UC Berkeley, Disneyland, and Bell Labs together. Somehow I managed
to squeeze San Francisco, Paris, Sydney, and Montreal into that month. It is still a fond memory that when I ran out of tickets in my
ticket boook for North American flights, the friendly Continental airlines clerk handed me another book full of open tickets. Flights
were not full in those days and I just showed up at the airport and looked at where flights were going that day.
At Bell Labs we knocked on the door of a guy called Bjarne who we had heard
was ruffling feathers at Bell Labs. by developing a preprocessor to add classes to C.
I knew why this might be interesting
because Wirth visited my alma mater while I was learning Pascal and talked about Modula.
Implementing things like “const” prompted his abandonment of
a preprocessor strategy and the bifurcation that would become C++.
By a fun coincidence Rick Mascitti, one of the programmers that joined the team I worked
on at Bell Labs a few years later, named C++.
Another memory-saving trick used in those early compilers I developed required the assembly-code skills of a buddy, Graeme Elseworthy.
I made the C compiler output calls to a library of code he wrote that emulated a stack machine. This short-cut was inspired
by my study of Dijkstra’s many contributions including his enthusiasm for the fast one-pass Algol-68 compiler for the Burroughs Stack Machines.
Inadvertently we had discovered a software architecture that is now standard (e.g. LLVM). Dijkstra also visited my alma mater while
I was studying computer science. I was a nerdy fan - having asked for his 1972 book on structured programming
as a high school math prize. A measure of his influence is that just in the last month his name has come up twice in my
different technical projects - his graph algorithm is a common part of circuit routing software
and his work on clock synchronization is still relevant and important.
In the mid 1980s, very few people were using C++ at Bell Labs or elsewhere. Other earlier languages were competing for mindshare
in the reliable, object-oriented and functional programming spaces, e.g., ada, lisp, smalltalk.
For Aegis, our Bell Labs project,
we chose an object-oriented dialect of lisp. Still unpublished this work for the ATT PC,
interfaces with a DOM, and client/server architecture. This experience prepared me for the awkward accommodation
that programmers have now been living with for over half a century - compiled languages for “efficiency” programming
and interpreted languages for “productivity” programming. My most recent programming projects reflect this:
a Python program for analog circuit design, and a C++ program for a MIDI touch controller. This bifurcation has
practical and historical roots although I am one of many who think this is technically unnecessary. I was fortunate
to be part of the Parlab where we developed a model of how this unification might work under the rubric, “Sejits”.
This bifurcation has produced two different ways of doing object-oriented programming: static classes as exemplified by C++
This latter approach is central to graphical programming languages like PD and Max/MSP/Jitter.
After John MacCallum’s promising early experiments
OSC messages could be the basis of a new object-oriented language, I enthusiastically joined and managed a team effort to integrate
the language into PD and Max/MSP/Jitter to address their notorious lack of user-defined data structures.
The “odot” language
favors an interesting programming style which simplifies challenges often encountered in conventional programming languages.
For example, exceptions are handled by delegation - already a fundamental part of language and the basis of its object dynamism. There is no
hidden name mangling or type signatures - introspection isn’t an exceptional facility it is built from the ground up.
Object, Class, and Message are all implemented in a single concept in “odot”.
One of the biggest reliefs using “odot” is not
worrying about memory management or invalidated states during iterations. This and the complexity of “const” are avoided
by using cloning semantics where expressions
transform objects into new objects functionally.
Recent standardizations of C++ have introduced features with some parallels to this paradigm- notably C++20’s range views, and string_views.
Unfortunately, in C++ we still have the cognitive burden of knowing which operations might invalidate a view - a situation that doesn’t arise by construction with “odot”.
Although we haven’t adapted this cloning paradigm to native Python, “odot" has influenced my programming style in Python3. I rarely write
or modify the contents of a Python class. In my recent analog design environment, PAD, the key data structure (eDict) is assembled functionally
by accretion without modification.
Software engineering is an aspect of programming language knowledge with its own rich history. It’s not enough to know
the “features” of a programming language. How to employ those features to produce reliable software is essential
in engineering programming as opposed to what I call exploratory or experimental programming where reliablity of a rapidly
evolving program is often not the goal. Here I have learned that the quality of the IDE and underlying tools is very determinant.
I was amused to discover people after all these decades still appreciate the efficiency of the old PCC compiler. It is
usually 5 times faster than GCC. I remember very fast compile times when I was a student on time-shared machines with about the same
memory as an Arduino with 3% of the speed. This fast compile time encouraged me to build programs incrementally with testing every
few lines or every new function and I still seek development environments with this focus on speed. The Teensy microcontroller
is optimized for fast load and run times and has enormously contributed to the quality and quantity of my embedded systems programming.
My least favorite software engineering task is debugging with a step by step, breakpointing debugger. I prefer to take longer and
that is correct by construction. As I have refined this I spend less and less time debugging. On rare occasion when I am stuck with a debugger
it is usually tracking a bug in the compiler or libraries. These debuggers have also been useless for about 70% of my code because
I have written a lot of real-time audio and gesture processing code and they can’t recreate the context the code is running in.
This real-time requirement helped a lot of fellow programmers at CNMAT develop good software engineering practices like defensive programming. I like to build the test harness as early as possible. As it turned out Max/MSP turned out to be a great environment for this. We could do our efficiency programming in C or C++ and build rich tests and examples in Max/MSP to exercise the code. I was so enthusiastic with the value of this I encouraged Amanda Chaudhary to to take this to the next level with her language OSW. She was able to provide a way for people to build their C++ extensions (the externalizer) and load them dynamically into a running patch - significantly increasing productivity of programmers and encouraging incremental development now fashionable under the rubric of agile programming.
The biggest change in IDE’s over the years has been the hinting and navigation tools. Some people really like their direct access to
versioning systems. I don't use these very much as I try to test as I go - rarely referring back to old releases. A subtle
but important aspect of these systems is a normalization of coding styles and paradigms. This normalization is a two-edged sword.
Python indentation is an annoying extreme example. Fast access to libraries and documentation encourages people to reuse
well-tested libraries whilst at the same time discouraging some interesting alternative ideas that might have been pursued.
Some of the IDEs I use currently have interesting hinting that can, for example, explain which standards of C++ a particular paradigm works for.
An insight about programming languages that has been consistantly helpful came from conversations with Georgina Born, an anthropologist/sociologist who
studied IRCAM, an institution I was working at in the 1980s. Her studies of our practices ended up bootstrapping what is now called software studies. The insight
is that programs are written by people for other people to read and that might be their primary value.
That they also are interpretable instructions for computers is an important side effect
but programs are rarely static so one’s code is likely destined for transformation and reuse by another person - likely a stranger.
I didn’t learn to program from text books, my computer science classes, or web tutorials. I learned by studying other people’s large programs:
initially the C Compiler, a Basic interpreter and UNIX itself. As I write code for others to use, I ask myself what are the
valuable things I and others can learn from what I am writing? This puts me at odds sometimes with common dogma which discourages
expressive uses of a programming language. I have encountered this in recent years around the Arduino IDE which has a few folk zealously
proclaiming we shouldn’t use fancy C or new C++ features to avoid confusing “beginners". This is thinly disguised infantalization. There will always
be beginner programmers but there are also a lot of people have been doing embedded programming on Arduinos for 15 years. My most recent C++
program, FingerPhoneUSB is an exploration of what aspects of C++ will significantly improve an embedded systems application. The current version sticks with
the Arduino constraints of no RTTI, or standard libraries. Others have become impatient with the lack of the standard libraries with Arduino and have
created special lightweight implementations. I am enthusiastic to see which of those library features my example will evolve to include.
Selected Writings on Programming
o.OM: Structured-Functional Communication between Computer Music Systems using OSC and Odot, Bresson, Jean, MacCallum John, and Freed Adrian , FARM 2016
Dynamic Message-Oriented Middleware with Open Sound Control and Odot, John MacCallum, Rama Gottfried, Ilya Rostovtsev, Jean Bresson, Adrian Freed , ICMC, 2015
Agile Interface Development using OSC Expressions and Process Migration, MacCallum, John, Freed Adrian, and Wessel David, NIME 2013
Composability for Musical Gesture Signal Processing using new OSC-based Object and Functional Programming Extensions to Max/MSP, Freed, Adrian, MacCallum John, and Schmeder Andrew , NIME 2011
Dynamic Instance-based, Object-Oriented Programming (OOP) in Max/MSP using Open Sound Control (OSC) Message Delegation, Freed Adrian, MacCallum John, Schmeder Andy, ICMC 2011
Advances in the Parallelization of Music and Audio Applications, Eric Battenberg, Adrian Freed, David Wessel, ICMC 2010
Music Programming with the new Features of Standard C++, Freed, Adrian, and Chaudhary Amar , ICMC 1998
Guidelines for signal processing applications in C, Freed, Adrian , C Users Journal, 1993
The Portable C Compiler, Freed, Adrian , Australian UNIX User Group Meeting, 1980, Canberra, (1980)