Interactive development in Rust: Tools

Something I want to do is to bring back a way to do some more interactive software development. This was something that was really common with the micros of the 1980s and still exists in some form with the Unix command prompt (perhaps the apex form of this style is represented by SmallTalk). I'm going to work with Rust.

To start with, we need a way of interacting with Rust programs. Here's the starting point:

use serde_json::*;

pub trait Tool : Send+Sync {
    fn invoke_json(&self, input: Value) -> Result<Value, Value>;
}

This is a 'Tool' - it represents a program that runs straight through and produces a value or an error. The input and output is essentially JSON - serdes representation of a JSON value rather than a raw string. These are obviously called in an untyped way, which is helpful when they're intended to interact with the rest of the world.

Tools are essentially just programs: their entry point is equivalent to a main method. They normally don't do anything interactive by themselves. Their simple API makes them easy to call. Interestingly, they could be implemented either in-process or as a separate process as their API is simple enough to require no extra work to switch between the two styles.

Tools written in this way need to be able to initialise themselves. This is something that moves a bit away from 'dependency inversion', but it's quite helpful if you want to be able to invoke one interactively as it removes the need to do a lot of tedious setup.

Somethign of paticular note about 'tools' is what happens when they're treated as a test target. A test is just an input JSON object alongside the expected output. As tools have to be able to initialise themselves, no other code is required. The tests for a tool can be written before writing any code at all, just as JSON strings.

In the next few blog posts I'm going to flesh out this idea some more, and hopefully develop this into a much more workable system.