Axum - The AdderAgent example part 1

 I have recently been taking a look at the Microsoft incubation project Axum.

I'm not going to spend too much time explaining what it is, there is some very good information on the homepage, as well as in the recent Hanselminutes Axum podcast. The home page describes the project as follows.

   Axum is a language that builds upon the architecture of the Web and principles of isolation, actors, and 
message-passing to increase application safety, responsiveness, scalability, and developer productivity.

   Other advanced concepts we are exploring are data flow networks, asynchronous methods, and type annotations 
for taming side-effects.

 In this post I want to concentrate on the first AdderAgent example given in the Programmer's Guide and the example video shown on the home page. The version I show below is the version taken from the video. In later posts I would like to do the same for the later AdderAgent examples in the guide.

Initially I shall compare the first AdderAgent with the (loosely) equivalent in C#, then offer an analogy that helped me to understand how to think through the Axum version's differences, and finally show the inevitable flaws in my analogy.

To start with, I should probably mention, I don't specifically intend this to be a tutorial. If you are interested in Axum, I strongly recommend you read the Programmer's guide. What I want to do in this post is simply share my thoughts on the AdderAgent example, and the thought processes that helped me understand, not specifically what the example is doing, rather why it is doing it, and how to understand what Axum is doing differently from a more conventional .NET language, such as C#.

I shall also make the assumption that the reader is not particularly well versed in thinking in a functional sense. I'll do this, largely, as I probably fall into this set of developers. I have worked with F#, professionally, as well as mucked about with Erlang for fun, but I am still far too steeped in OO development methodology to claim I can make the architectural jump without a certain amount of internal gear changing.

Following examples is a great way to learn keywords and flow, but further thought is usually required to understand why a new language is doing what it is doing, especially if you want to use the language correctly, and to its full potential. 

As with most functional style languages (Axum isn't specifically a functional language, as is F#, however it does have functional elements, even a function keyword, to ensure a marked method cannot modify state outside from itself and is side-effect free), the documentation does start with a Fibonacci number example which is well worth investigating.

Firstly, here is the Axum AdderAgent example. As I mentioned above, this is largely the code from the example given in the 'Building your first Axum Application' video on the Axum home page, but it is very similar to the first AdderAgent example in the Programming Guide. I have also added a Console.ReadLine at the end of the app, so we can see the output before the console closes.

 

using System;
using Microsoft.Axum;
using System.Concurrency.Messaging;

namespace AdderExample
{
    channel Adder
    {
	input int X;
	input int Y;
	
	output int Z;
    }

    agent AdderAgent : channel Adder
    {
	public AdderAgent()
	{
	    int result = receive(PrimaryChannel::X) +
	    receive(PrimaryChannel::Y);
	    PrimaryChannel::Z <-- result;
	}
    }

    agent MainAgent : channel Microsoft.Axum.Application
    {
	public MainAgent()
	{
            var adder = AdderAgent.CreateInNewDomain();
	    
            adder::X <-- 10;
	    adder::Y <-- 20;
		
	    var sum = receive(adder::Z);
	    Console.WriteLine("Sum of 10 + 20 = {0}", sum);
	    PrimaryChannel::ExitCode <-- 0;
	    Console.ReadLine();			
	}
    }
}

Even though there are a few new keywords and concepts evident here, it should be fairly obvious what this application is doing to a C# developer. We have a code block that implements something called a channel that appears to define 2 numbers that need to be added. Then, using what suspiciously appears to be a C++ style syntax, we call this functionality.

The term 'receive', and probably the terms 'agent' and 'channel' should also tip us off somewhat on program structure and flow, but at this point the novice should be able to construct a C# equivalent.

 

using System;

namespace CSAxumEquivalent
{
    class Program
    {
        static void Main(string[] args)
        {
            Adder adder = new Adder();

            adder.X = 10;
            adder.Y = 20;

            Console.WriteLine(adder.GetResult());
            Console.ReadLine();
        }
    }

    interface IAdder
    {
        int X { get; set; }
        int Y { get; set; }

        int GetResult();
    }

    class Adder : IAdder
    {
        public int X { get; set; }
        public int Y { get; set; }
        
        public int GetResult()
        {
            return X + Y;
        }
    }
}

Now, apart from some obvious keyword and concepts, what are the differences between these two versions.

Well, the main one is the asynchronous nature of the Axum code. If the code to Add was complex, time and resource consuming, our C# application would hang whilst it the GetResult() method was called, whilst the Axum code would, neatly and without any extra plumbing code required, nicely perform the addition on a separate thread on a separate process. It is worth noting that, on a single core machine, so would our Axum application.

I shall leave this post here. My next post will deal with an analogy that helped me, a long time OO developer, understand what is going on in the Axum application, and, more importantly, how to think in a way that will assist me in writing Axum code.