modified: January 14, 2018

1 Language for Building

This post is about the language I am working on as a part of this environment. For the sake of this post, let’s call the language ITCH. Hopefully I can expose some of the assumptions underlying the system and open them up for discussion.

The language is intended to support these two goals:

1.1 A Type of World

For the model of complexity, I am imagining certain types of games.

As genre examples, you could take interactive fiction (see also), roguelikes, card games like Magic, or puzzle games like jelly no puzzle, SSR.

These games tend to be interesting because of their interacting parts: many local actors and places whose combinations produce surprising game events.

1.1.1 Desires

1.2 Rules

When reasoning about an artificial situation, I tend to “start from somewhere.” I start with an empty model and extend it by recognizing consequences.

Recognizing a consequence first requires recognizing basic facts: objects that can be true of, or present in, the situation.

A consequence is of the form “when some condition (defined in terms of basic facts) is true, or present, then make true, or make present, certain new facts.”

When a set of consequences fail to predict the behavior of the system, we extend it. We may need to change an existing rule or add new rules to make the model more accurate. This may require recognizing new classes of facts.

Programming languages based on Datalog build systems in this way. We interpret consequences (now called rules) operationally; they denote atomic behaviors. A program accepts input facts, computes applications of rules, and produces output facts. This is the basic model used with ITCH.

When the system itself is defined using facts and consequences, then the models constructed by our informal style of reasoning actually become immediately formalizable.

1.2.1 Terminology

We often call facts tuples and consequences rules. We divide tuples into sets called relations.

1.3 Object Orientation

For our game applications, we might normally use an object oriented language. This paradigm divides functionality up into objects, places them together in a world, and lets them interact by message passing or procedure calls.

I consider ITCH to be basically object oriented, by this definition.

For our classes, we write sets of rules.

Instead of sending a message to an object (to be processed by its most specific superclass) we assert a tuple (to be processed by the most specific applicable rule).

1.3.1 Boundaries

Many object-oriented systems make these two operational assumptions:

Rule programming deprioritizes this view of things; our object is more like a hook which causes the rules of the game to change in some local, temporary way. Objects allow rules to trigger. Messages can refer to specific objects, but don’t have to.

An object has no canonical boundary with the world. If there is one, then the world can carry on even if the object is excised.

1.3.2 Interaction

Rule sets can define individual object behaviors, but they can also flexibly define interactions between objects.

A rule of a game frequently refers to multiple objects.

For instance, the implementation of a single card’s behavior tends to look like a consequence, as defined earlier: when a certain formation of game conditions is present (“a player has an empty hand”, “a piece lands on a square owned by another player”), draw some conclusion (“the game is over”, “the player attempts to pay the other a certain amount”).

Puzzle games usually have very simple physics: some rules that describe how a configuration of elements move after the player performs an action. Puzzles are constructed from configurations of token objects that follow these rules.

Localizing these behaviors at a query, rather than a particular object, is natural.

1.3.3 Composite Identity

This style has a more flexible notion of identity.

Rather than judging that an instance is nominally a member of some class, we can only say that it matches some query.

The most basic queries are single predicates; for instance

banana x

This pattern might form the basis for all our banana behaviors.

We can recognize a familiar subtype by extending the query:

banana x, overripe x

1.3.4 Modifiability

A formation of tuples, viewed as attributes, thus may form an instance of some “query class”, while a different collection of tuples referring to the same values may be recognized as a different instance by some other query.

The system can be extended with new recognizers, unconstrained by a class hierarchy. When extended with an effect, a recognizer becomes a rule, and it can interpose at any level of the system’s behavior.

Rules allow us to abstract:

banana x, overripe x => overripe-banana x
overripe-banana _ => 1:ripe-banana-count

and add new behavior orthogonally to the rest of the application:

n:ripe-banana-count, n > 2 => make-banana-bread?

2 Language for Asking

2.1 Programmer

Our hope is to write applications that treat their users as aspiring programmers. Our model of a programmer is that they

  1. build models of behavior,
  2. relate source code and behavior,
  3. construct new code and modify existing code to effect the desired behavior.

2.2 Strawman?

Our view of the average programming situation, as it relates to the three activities above:

  1. no/little support for intuitive model building; formal model building options determined by abstractions present in language
  2. “read the source”, debuggers
  3. a text editor, IDEs, git.

In other words, the processes of building models and relating observed or modelled behavior to source code is mostly intuitive, and not supported by tools.

Providing source code is a very coarse way of supporting a student. Applications are nominally defined by their source, but compiled programs do not generally reflect the structure of their source. Reading the source is like reading a manual.

Debuggers are traditionally used to fix bugs. Their usefulness to people learning the relation between some behavior and its source code is not emphasized.

2.3 Hope

Our model of the future of the programming situation:

  1. a language suitable for gradual model refinement: from intuitive behaviors to formal specification to implementation
  2. applications with spatial structure, a fine-grained language for questions, efficient answers to local questions.
  3. image based environments. editor embedded in/around the application. flexible views of history.

Treat every application like a domain specific language.

Expert users have developed a command of the grammar of their application. They have sophisticated mental models of the objects at hand. These models may go beyond the application designer’s understanding.

This expertise should form the basis of a language for asking. The knowledge kept by an interpreter is about how the definitions in the program relate to computed values. A responsible interpreter can answer certain questions about this knowledge:

Their answers must be local: an answer to “who computed this value?” is a program that computes that value and nothing more. The source can be less like a book and more like a tutor. A tutor teaches by providing mind-sized answers and nudges in the right direction.

Answers to questions such as these should help the user leverage their expertise in the domain to develop expertise in the inner logic of the application. Although the application-DSL may not be extensible, its implementation in ITCH is extensible. The language is a substrate for constructing new experiences that prioritize learning, trust, and modification.