Thoughts on Spek: The usage of channels and ports, Part 3

I covered this in my last two posts, but the Spek language that I’ve been slowly working on over the past few months is based on the Axum programming language originally developed by Microsoft about five years ago. I’ve been making changes to the Axum language’s grammar after spending a couple of weeks painstakingly trying to recreate it. The area I’m working to change at the moment are channels and ports.

To recap where we are: channel patterns are entirely out, channel ports have been updated, channel functions just came back from vacation, and a couple of feature ideas for channels in the future to share.

Now that channel input ports define their own output, and I plan to utilize contract validation attributes via lightweight predicate lambdas on an extended port definition, the question of how someone perform a similar validation on a much more complex type becomes an issue.

That is quickly resolved through the use of channel functions, of course!

channel Channel_A 
{ 
    port int Add<int,int>; 

    [Message(y, "The values passed would result in a DivideByZero exception")] 
    port int Divide<int,int> { x => false, y => y >= 0 }; 

    func bool DivideByZeroPossible(int val) 
    { 
        if (val == 0) 
        { 
            throw new ContractViolationException("The values passed would result in a DivideByZero exception"); 
        } 

        return false; 
    } 
}

There is the lightweight predicate lambda on the Divide port from the previous post, along with a channel function that performs exactly the same logic. This is much more useful for those complex object scenarios when you have multiple things that could go wrong.

That’s about it for channel functions as I currently plan to go for the first version of the language. Remember, I still have to actually get the language working once I’m done theorizing about the syntax. That doesn’t keep me from thinking about other ideas for the future though.

We could imitate a part of the Go language very easily by allowing multiple-parameter output ports.

channel Channel_A 
{
    port int,int,int SplitByForwardSlash<string>;
}

Given a string like “11/16/2014”, you could then get back “11”, “16”, and “2014” in separate variables. The part that I could use some help on is what a C#-like syntax for receiving that from a channel would look like.

I could also use some help on asking what channel functions could possibly do in the future as well. For example, if the channel mechanism is essentially the “postal service” between agents, would it make sense to let a channel function call out to another agent?

Let’s use a scenario where a channel is going to create an employee entity with the Employee agent where one of the properties is an organization identifier. To verify if the contract is valid, we would need to validate the identifier with the Organization agent. Would you want that logic in the agent, or in the channel? We’re already doing validations to ensure other values are within the right range with the contract validation attributes. Age should be higher than 15 in corporate world due to federal regulations on working children, and anyone over the age of 130 is obviously incorrect data. To me it would only make sense.