The Blurry Boundaries Between Programming and Direct Use
Abstract
While a narrow conception of programming makes it possible to draw sharp lines between programming
and direct use
, many of the efforts of the PL + HCI community call for expanded senses of programming that blur these lines. In this paper, we explore these murky boundaries from both sides, exploring situations where programming systems are used for direct use, and situations where direct-use systems take on the characteristic powers of programming.
Introduction
We often draw a distinction between the activity of programming and the activity of directly using a computer. But as we expand our view to include end-user programming [programming
?
This paper explores this question, focused on complications that arise when programming and direct use overlap. Our goal is much less to present an answer to the question than it is to convince you that the answer is unclear and the question is worth talking about.
In fact, we believe that this question is of vital importance to the community of researchers at the intersection of PL and HCI. In this community, we often step away from the narrowest conception of programming to explore possibilities that tug at its boundaries. Programs might be edited as diagrams, rather than as text. Programmers might be end-users, rather than professional software engineers. And programming might even be done by working by demonstration on concrete data, rather than by editing a symbolic specification. While these situations may not match the superficial appearance of the most stereotyped modes of programming, the PL + HCI community embraces them, sensing that they match a deeper essence of programming.
But stretching the bounds of a conceptual space can get you into trouble. We have repeatedly encountered reviewers who object to classifying our work as programming
, because the work does not expose a textual format, or because it does not offer Turing-complete expressivity. We have heard similar reports from our colleagues. It appears that what does and does not qualify as programming
is a site of active controversy. If we wish to continue exploring these further reaches without giving up the banner of programming
, we will need to clarify and argue for the things programming means to us.
The value of such clarification goes beyond armoring ourselves for academic turf battles. We need clarity to make progress.
Some of the most exciting visions of programming, at least to the present authors, are those that intertwine programming and everyday computer use.
In these visions, programming begins to take on the directness and visibility of direct use, and direct use begins to take on the expressiveness and power of programming.
In imagining these hybrid systems, one begins to see aspects of programming already present in everyday computer use, in mechanisms like multi-cursor editing in text editors and component systems in graphics editors.
Perhaps these aspects could be cultivated and extended.
But to think clearly about these promising possibilities, one needs to make sense of a radically expanded notion of programming
.
This paper aims to chart out some of these blurry boundaries.
In the authoring of dynamic artifacts
, identifying difficulties in this definition.
In feelings
along the way, previewed in
It feels like programming …
- when you create dynamic artifacts, especially when the dynamics are bespoke and unpredictable.
- when you can define reusable components.
- when processes have persistent, editable representations.
- when you can act on many objects at once, and when you have powerful tools for specifying what objects to act on.
- when you have a smooth pathway from concrete action to parameterized action.
feelings of programming, gathered from throughout the paper.
Throughout this paper, we adopt a predominantly technical perspective on the question what is programming?
– a question that is, of course, entangled with significant historical and sociological factors. (Indeed, we have encountered these factors ourselves during review cycles – there is clearly a lot of boundary-work [
Programming as Ends
So then: what is programming?
In the interest of time, we will skip entirely past the narrowest conceptions of programming – those that demand Turing-completeness, a general-purpose
range of applications, or text-centeredness. Instead, we will begin with a much more enlightened definition from requiring, for example, that the notation be Turing complete, and able to specify sequence, conditional logic and iteration
. They proceed:
[W]e define a program as
a collection of specifications that may take variable inputs, and that can be executed (or interpreted) by a device with computational capabilities.Note that the variability of input values requires that the program has the ability to execute on future values, which is one way it is different from simply doing a computation once manually. This definition captures general purpose languages in wide use, such as Java and C, but also notations as simple as VCR programs, written to record a particular show when the time of day (input) satisfies the specified constraint, and combinations of HTML and CSS, which are interpreted to produce a specific visual rendering of shapes and text. []
We take the core of this definition to be the criterion that programmed artifacts take variable inputs
, and thereby have the ability to execute on future values, [rather than] simply doing a computation once manually
. We will call such artifacts dynamic artifacts
, in contrast to static artifacts
like text documents and images.
Note that this criterion is about the ends of programming, not the means.
It examines what comes out of the process of programming, rather than characteristics of the process itself.
Artifacts can be dynamic in different ways. Perhaps the most obvious is that they can be dynamic by being interactive, responding in the moment to actions taken by a user. They can also be dynamic by responding to non-user data streams, such as real-time weather data. Finally, artifacts can be dynamic by being explicitly abstract and incomplete, like functions provided by a software library.
By defining programming in terms of its ends – what it produces – this definition adopts a stance of impartiality towards the means by which a system does this. This keeps the door open to diverse and radical approaches. For instance, it’s easy to say, with this definition, that a visual programming system like Scratch [programming
, as they both clearly produce the same kind of dynamic artifacts that traditional languages do. We consider this a clear advantage of this definition.
What counts as dynamic? However, we immediately run into complications when trying to pin down which artifacts are and are not dynamic. A lot of this has to do with perspective: What qualifies as external inputs
to an artifact, versus what is part of an artifact itself? For instance, Ko et al. provocatively claim VCR programming is programming, as a programmed VCR responds to the time of day in a dynamic way. However, this relationship between time of day and behavior seems exceptionally predictable and, one could say, static. We can tug on this example in the direction of other time-dependent programs
. It is said, colloquially, that one programs
a drum machine. But a user working in a digital audio workstation like Ableton Liveprogrammer
merely because they are arranging clips in time, to be played back later.
It is apparently unclear when unfolding in time makes an artifact dynamic. It is similarly unclear when affording interaction makes an artifact dynamic.
Is a simple HTML file a dynamic artifact? You can scroll it. Perhaps the HTML has certain elements that remain sticky
on scroll, so scrolling does not simply pan a fixed image. Perhaps the HTML contains responsive
CSS, which makes it adapt to different screen widths. Perhaps we have a network of HTML pages linked together with hyperlinks.
At what point do we cross the line from static to dynamic?
Charts made with Google Sheets have interactive tooltips that appear on hover – does that make them dynamic artifacts, and make Google-Sheets chart-makers programmers?
When are dynamics considered an authored part of a dynamic artifact, and when are they considered a part of how we interact with a static artifact?
Our suspicion: All else being equal, affording interaction does make an artifact seem more dynamic, and does make the act of creating it feel more like programming. But the more predictable these interactions are, and the less thought the creator has to put into them, the less we consider their activity to be programming
. An HTML page is scrollable, but an HTML author does not typically redefine the way this scrolling works. If they do, that begins to feel like programming.
It feels like programming … when you create dynamic artifacts, especially when the dynamics are bespoke and unpredictable.
Dynamic means to static ends. A second, intertwined issue is that the authoring dynamic artifacts
definition of programming would seem to exclude many things that feel an awful lot like programming. Picture a scientist using a Jupyter notebook to analyze a data set. They use every imaginable programming technique along the way, but at the end, they just write out a table of values and a chart, and forget about the notebook entirely. Is this programming? Tables and charts are undeniably static artifacts. It appears the scientist has used dynamic means to produce static ends – a common pattern, but one unaccounted for when defining programming in terms of ends.
Or imagine a user writing a single-use Bash script at the command line to rearrange files on their computer in a complex way; a script that will not be saved nor run again. It certainly seems like they’re programming, but they produce no artifact at all – just an effect on their file system.
While there is clearly a strong link between programming and authoring dynamic artifacts
, this criterion is neither necessary nor sufficient to characterize our intuitions. It seems difficult to get around this problem with a purely external
, ends-centric definition of programming.
Programming as Means
If an ends-centric conception doesn’t effectively capture what programming is about, we should turn our attention to means. Here, we must tread carefully, since investigating the internal mechanisms of systems puts us at risk of reproducing narrow ideas about what these mechanisms should look like. As a strategy to keep our minds open, we will begin by looking for programmatic means not in situations conventionally described as programming (like the data-analyzing scientist), but in situations arising in direct-use computing.
Reusable components. What aspects of an activity make it feel like programming? Our first guide comes directly from our discussion of ends: When does a computer user construct, as part of their activity, dynamic artifacts as intermediate tools? That is, when do they define specifications that may take variable inputs
as part of a larger workflow?
In direct-use contexts, such specifications often appear as reusable templates. For instance, most word processors (such as Google Docs or Microsoft Word) provide a system of labeled styles
, such as Heading 1
and Subtitle
, which can be applied to text, setting attributes like font, size, and weight. When a user sets a style’s attributes, they are performing an abstract act which may have no immediate effect on the document. Rather, they are setting up a tool for future use, in a way akin to a programmer defining a function. They are specifying a dynamic artifact.
One can imagine a primitive word processor implementing styles as imperative macros
, where applying a style to text simply applies the style’s attributes in the moment. But modern word processors actually link the text to the style symbolically, meaning that changes to a style’s attributes automatically update all previous uses of the style in the document. This feels, in some ways, even more programmatic than macro styles, as it embeds symbolic structures persistently into a document in a way we will later term non-destructive
.
Template systems in direct-use software grow in complexity from here. For instance, the vector graphics editor Figma features a component
system in which a main component can be duplicated to form instances with a persistent link. Changes to the main component propagate to instances, while certain aspects of instances (like label text and color choices) can override the main component. Further levels of abstraction have been added to Figma’s component system to meet the needs of graphic designers, such as the ability to define (multiple dimensions of) variants and the ability to parameterize instances with properties
.
It feels like programming … when you can define reusable components.
Persistent representations of process. Persistently linked, reusable templates build on an even more fundamental capability: non-destructive
(aka non-linear
) editing. Traditionally, edits to a raster image in a program like Photoshop
In the academic literature, instrumental interaction has been a prominent champion of persistently representing processes [turning concepts into objects
. In practice, this often means reifying transient workflows into persistent parts of documents. For instance, StickyLines [Turning commands into objects provides potentially infinite regression. Since instruments are objects, they can be operated upon by (meta)-instruments, which are themselves objects, etc.
This potential for unlimited composability and abstraction is characteristic of programming systems.
group
structures as a prime example of reification – by reifying a collection of objects into a new object called a group
, tree structures become possible. This possibility is exploited and extended by Cuttlelive modifiers
to groups, which transform the group’s contents with operations like repetition, boolean operations, and geometric transformations.
These modifiers live persistently in the user’s drawing.
It is striking that, since these modifiers live in a tree-shaped hierarchy, they can in fact be combined in an open-ended way much like functions in a programming language.
It feels like programming … when processes have persistent, editable representations.
Selections and parallel action.
One hallmark of computer programming is the use of abstraction to specify repetition using constructs like loops or queries.
Direct-manipulation systems have often been faulted for their limited ability to express repetition. Performing repetitive actions
in his list of tasks which are difficult to do by [direct] manipulation
.
Naturally, some parallel action is pervasive in conventional direct-manipulation interfaces – selecting a set of shapes in a vector-graphics editor and changing fill colors in a bulk operation.
But direct-use systems have often been limited, both in their ability to express targets of parallel action and their ability to express actions themselves.
We see hints of programmatic structure in ways that direct-use systems stretch these limitations.
For example, take multi-cursor editing in text editors. Powerful editors like Emacs have long had the ability to repeat actions through explicit macros or scripting. Most editors also have specialized parallel-action commands like search-and-replace. But more recently, it has become common for editors to offer the ability to operate on multiple cursors simultaneously.multiply(vec, 10) into method calls like vec.multiply(10), using cursor movement commands and copy-paste, rather than complex, symbolic regular-expressions.
The usefulness of multi-cursor editing replies upon the semantically expressive range of commands made available by text editors.
In order to effect the transform described above, the user must move the cursor from the selections matching multiply( (which they obtained via a search) to the first parameter of the call, like vec. Once the cursor is after the open-parenthesis, they can select this first parameter with a single word-wise
cursor movement command (conventionally shift-alt-right
). Each cursor may run into a different identifier in this position (like vec2 or circleVec), but word-wise selection will pick all of these up correctly. In single-cursor editing, access to word-wise cursor movement is a helpful speed-up, but never essential – a user can always just press left
or right
until they get where they want to go. But in the presence of multi-cursor editing, higher-level operations like word-wise cursor movement become indispensable. They are what allow users to express intent in a way that can generalize across multiple selections, even as the details of the selections vary. For parallel action to be expressive and useful in direct-use systems, these systems need commands that generalize.
Another prominent limitation of parallel action in direct-use systems is the difficulty of specifying what objects to act on. For instance, to adequately support… the descriptive specification of operands
(emphasis added), giving as an example a user wishing to replace all instances of one structure in a circuit editor with a different structure. Direct-use systems have made progress on this front. As a humble example, when a set of objects are selected in Figma, a side-panel shows a palette of colors appearing among the selected objects. From this panel, colors can be directly replaced (a search-and-replace-like action), or, better yet, the selection can be narrowed to objects with a given color. The ability to query
a selection like this is extended by Collection Objects [sculpting
of multi-cursor-like selections through steps of generalization, navigation, and filtering.
It feels like programming … when you can act on many objects at once, and when you have powerful tools for specifying what objects to act on.
Non-programming programming and abstractability
. Throughout this work, we have been inspired by Hoff’s Always Already Programming [When a programmer is writing javascript, they are using prewritten, packaged functions and variables in order to carry out the actions they want their code to do. In this way, the programmer is also the user. Why is using pre-made scripts seen so differently than using buttons that fire pre-made scripts?
. While we tend, like Hoff, to be programming maximalists, seeking programmatic structures in unlikely places, we can also interpret Hoff’s question in the opposite direction. When a textual program only replicates actions that could be done in a direct-use interface, should it count as programming?
Victor’s Learnable Programming [fill() and rect() are controlled by direct manipulations on the canvas. He reflects: With this interface, is this even
But, writes Victor, neither is using the canvas drawing API to draw shapes with fixed cartesian coordinates. programming
? No, not really.It’s merely a very cumbersome form of illustration. It becomes genuine programming when the code is abstracted – when arguments are variable, when a block of code can do different things at different times.
Here, Victor closely echoes
If writing lines of code like triangle(80,60, 80,20, 140,60) isn’t programming, what other things might not be? For instance, the Bash language used at the Unix command line is certainly a programming language. But much of its use is unabstract in the same way this triangle is. If one types mv old.mp4 new.mp4 to move a file, this is no more abstract than dragging the file in a file browser. If one types ffmpeg -i old.mp4 -vcodec libx264 -crf 18 new.mp4 to re-encode a video, this is no more abstract than loading the video in a GUI like HandBrake, specifying parameters in a form, and pressing Start
.
But there is, in fact, an important difference. Even though these actions are not abstract, their representation as code in larger programming systems makes the pathway into abstraction much more clear. Each parameter to triangle or mv or ffmpeg provided as a constant literal can quickly be replaced with a parameter, or the call itself can easily be inserted into a loop or a conditional. We may say that although the call is not abstract, it is abstractable. This is not at all the case in conventional user interfaces. Dragging a corner of a triangle in a vector-graphics editor does not reveal a slot
for parameterization. And actions in direct-use systems are typically immediately forgotten, or at most placed in an undo history. They are seldom reified as objects that can be looped or made a part of a larger, parametric process.
It feels like programming … when you have a smooth pathway from concrete action to parameterized action.
Bridging the gap. What would it mean for dragging the corner of a triangle to present a slot for parameterization? In other words, what infrastructures might give direct-use systems a gentle pathway into programmability and abstraction?
One set of possibilities lies in bidirectional programming systems, exemplified by Sketch-n-Sketch [direct manipulation
side of the system quite limited.
At the other end of the spectrum lie systems like Sketch-n-Sketch, which aim to make it possible to edit arbitrary code written in general-purpose languages using operations on output.
If successful, this approach will be tremendously expressive, and gain many advantages from its compatibility with existing programming workflows.
However, such systems may be held back by their dependence on existing textual-language structures.
The mechanisms direct-use systems develop to gain programmatic power rarely map one-to-one with conventional programming-language idioms.
Rather, they are designed around the ontologies and interactions found in the direct-use systems hosting them.
For example, while Figma components can receive explicit function-like parameters, instances of components can also override parts of the main component in an ad-hoc fashion.
Other direct-manipulation programming systems like Apparatusmanaged copy and paste
prototype from
Direct-manipulation programming systems which do not insist on maintaining bidirectional compatibility with conventional textual code can often be classified as programming by demonstration
[snapping
during a drag.
We can contrast this approach with that of StickyLines [macro
-style approach is also adopted by Wrangler [macro
-style approach has weaknesses – algebraic
systems for the difficulty they present to editing programs after they are first written.
Programming as a Lens
Perhaps what makes a given situation programming
is that the programming-languages (PL) community can turn their eye to it and think of it as programming. That is, we may want to view programming
not as an inherent quality of an activity, but as a lens we can apply to any activity. For instance, how might we think about a Photoshop document as a program? Perhaps we might see the arrangement of layers and filters as the syntax
of this program, and see compositing the document into a raster image as a semantics
. From this perspective, we might ask what sort of static analysis is possible – are there properties of a document we might detect without actually running it? We might also call upon traditional patterns and techniques of programming languages. Can you save layers into variables and refer to them elsewhere? Can you combine arrangements of layers into parameterized procedures?
Applying the lens of PL to unconventional settings can be extraordinarily generative. This is, essentially, half of the call of Many [domain-specific languages] have been designed ad hoc, and they would benefit from the formal rigor that’s brought to the design of general-purposes languages
.
However, elevating the disciplinary lens of PL carries some dangers. The discipline of PL does not examine programming in a value-neutral way. Rather, it carries path-dependent (and not entirely disinterested) assumptions and ways of approaching problems. For instance, the PL community tends to celebrate sophisticated static type systems. This may come from the mathematical appeal of types, and from the needs of large software-engineering organizations. Yet static types may or may not be appropriate as we blur the boundaries of programming into other spaces, like end-user use. Shaw makes this argument in her paper, listing myths
that PL practice implicitly embeds in their work, like the Mathematical Tractability
myth that [s]oundness of programming languages is essential
and the Specifications myth
that formal specifications are […] essential
[The Structure of a Programming Language Revolution
[
Acknowledgments
Many of the perspectives offered in this paper arose during collaboration with Devamardeep Hayatpur. We also thank participants in the Pacific Programming Interfaces Confab for helpful feedback on a draft.
References
- Bakke, E., & Karger, D. R. (2016). Expressive Query Construction through Direct Manipulation of Nested Relational Results. Proceedings of the 2016 International Conference on Management of Data, 1377–1392. https://doi.org/10.1145/2882903.2915210
- Beaudouin-Lafon, M. (2000). Instrumental interaction. Proceedings of the SIGCHI Conference on Human Factors in Computing Systems, 446–453. https://doi.org/10.1145/332040.332473
- Beaudouin-Lafon, M., & Mackay, W. E. (2000). Reification, polymorphism and reuse. Proceedings of the Working Conference on Advanced Visual Interfaces, 102–109. https://doi.org/10.1145/345513.345267
- Bostock, M., Ogievetsky, V., & Heer, J. (2011). D³ Data-Driven Documents. IEEE Transactions on Visualization and Computer Graphics, 17(12), 2301–2309. https://doi.org/10.1109/tvcg.2011.185
- Bullynck, M., & De Mol, L. (2024). The Myth of the Coder. Communications of the ACM, 67(9), 20–23. https://doi.org/10.1145/3639562
- Buxton, B. (1993). HCI and the inadequacies of direct manipulation systems. ACM SIGCHI Bulletin, 25(1), 21–22. https://doi.org/10.1145/157203.157206
- Chasins, S. E., Glassman, E. L., & Sunshine, J. (2021). PL and HCI. Communications of the ACM, 64(8), 98–106. https://doi.org/10.1145/3469279
- Chugh, R., Hempel, B., Spradlin, M., & Albers, J. (2016). Programmatic and direct manipulation, together at last. Proceedings of the 37th ACM SIGPLAN Conference on Programming Language Design and Implementation, 341–354. https://doi.org/10.1145/2908080.2908103
- Ciolfi Felice, M., Maudet, N., Mackay, W. E., & Beaudouin-Lafon, M. (2016). Beyond Snapping. Proceedings of the 29th Annual Symposium on User Interface Software and Technology, 133–144. https://doi.org/10.1145/2984511.2984577
- Do, Q., Campbell, K., Hine, E., Pham, D., Taylor, A., Howley, I., & Barowy, D. W. (2019). Evaluating ProDirect manipulation in hour of code. Proceedings of the 2019 ACM SIGPLAN Symposium on SPLASH-E, 25–35. https://doi.org/10.1145/3358711.3361623
- Edwards, J., & Petricek, T. (2022). Interaction vs. Abstraction: Managed Copy and Paste. Proceedings of the 1st ACM SIGPLAN International Workshop on Programming Abstractions and Interactive Notations, Tools, and Environments, 11–19. https://doi.org/10.1145/3563836.3568723
- Frohlich, D. M. (1993). The history and future of direct manipulation. Behaviour & Information Technology, 12(6), 315–329. https://doi.org/10.1080/01449299308924396
- Gabriel, R. P. (2012). The structure of a programming language revolution. Proceedings of the ACM International Symposium on New Ideas, New Paradigms, and Reflections on Programming and Software, 195–214. https://doi.org/10.1145/2384592.2384611
- Gieryn, T. F. (1983). Boundary-Work and the Demarcation of Science from Non-Science: Strains and Interests in Professional Ideologies of Scientists. American Sociological Review, 48(6), 781. https://doi.org/10.2307/2095325
- Hempel, B., & Chugh, R. (2016). Semi-Automated SVG Programming via Direct Manipulation. Proceedings of the 29th Annual Symposium on User Interface Software and Technology, 379–390. https://doi.org/10.1145/2984511.2984575
- Hempel, B., Lubin, J., & Chugh, R. (2019). Sketch-n-Sketch. Proceedings of the 32nd Annual ACM Symposium on User Interface Software and Technology, 281–292. https://doi.org/10.1145/3332165.3347925
- Hoff, M. (2020). Always Already Programming. https://gist.github.com/melaniehoff/95ca90df7ca47761dc3d3d58fead22d4
- Horowitz, J., Hayatpur, D., Xia, H., & Heer, J. (2025). Sculpin: Direct-Manipulation Transformation of JSON. Proceedings of the 38th Annual ACM Symposium on User Interface Software and Technology, 1–15. https://doi.org/10.1145/3746059.3747651
- Kandel, S., Paepcke, A., Hellerstein, J., & Heer, J. (2011). Wrangler. Proceedings of the SIGCHI Conference on Human Factors in Computing Systems, 3363–3372. https://doi.org/10.1145/1978942.1979444
- Keer, L. (2021). Always Already Programming. https://lucykeer.com/notebucket/always-already-programming/
- Ko, A. J., Abraham, R., Beckwith, L., Blackwell, A., Burnett, M., Erwig, M., Scaffidi, C., Lawrance, J., Lieberman, H., Myers, B., Rosson, M. B., Rothermel, G., Shaw, M., & Wiedenbeck, S. (2011). The state of the art in end-user software engineering. ACM Computing Surveys, 43(3), 1–44. https://doi.org/10.1145/1922649.1922658
- Ko, A. J. (2016). What is a programming language, really? Proceedings of the 7th International Workshop on Evaluation and Usability of Programming Languages and Tools, 32–33. https://doi.org/10.1145/3001878.3001880
- Lonati, V., Brodnik, A., Bell, T., Csizmadia, A. P., De Mol, L., Hickman, H., Keane, T., Mirolo, C., & Monga, M. (2022). What We Talk About When We Talk About Programs. Proceedings of the 2022 Working Group Reports on Innovation and Technology in Computer Science Education, 117–164. https://doi.org/10.1145/3571785.3574125
- Maloney, J., Resnick, M., Rusk, N., Silverman, B., & Eastmond, E. (2010). The Scratch Programming Language and Environment. ACM Transactions on Computing Education, 10(4), 1–15. https://doi.org/10.1145/1868358.1868363
- Mcnutt, A. M., Outkine, A., & Chugh, R. (2023). A Study of Editor Features in a Creative Coding Classroom. Proceedings of the 2023 CHI Conference on Human Factors in Computing Systems, 1–15. https://doi.org/10.1145/3544548.3580683
- Miller, R. C., & Myers, B. A. (2001). Interactive Simultaneous Editing of Multiple Text Regions. Proceedings of the General Track: 2001 USENIX Annual Technical Conference, 161–174.
- Cypher, A. (Ed.). (1994). Watch what I do: Programming by demonstration. The MIT Press.
- Nardi, B. A. (1993). A small matter of programming. MIT Press.
- Petricek, T. (2019). Cultures of Programming: Understanding the History of Programming through Controversies and Technical Artifacts. https://tomasp.net/academic/drafts/cultures/cultures.pdf
- Shaw, M. (2020). Myths and mythconceptions: what does it mean to be a programming language, anyhow? Proceedings of the ACM on Programming Languages, 4(HOPL), 1–44. https://doi.org/10.1145/3480947
- Victor, B. (2012). Learnable Programming. http://worrydream.com/LearnableProgramming/
- Victor, B. (2013). Drawing Dynamic Visualizations. https://vimeo.com/66085662. https://vimeo.com/66085662
- Voinov, P., Rigger, M., & Su, Z. (2022). Forest: Structural Code Editing with Multiple Cursors. Proceedings of the 2022 ACM SIGPLAN International Symposium on New Ideas, New Paradigms, and Reflections on Programming and Software, 137–152. https://doi.org/10.1145/3563835.3567663
- Xia, H., Araujo, B., & Wigdor, D. (2017). Collection Objects. Proceedings of the 2017 CHI Conference on Human Factors in Computing Systems, 5592–5604. https://doi.org/10.1145/3025453.3025554