## Introduction

As I have mentioned before, the lack of polyadic returns from many supposedly modern languages acts a a barrier to their future usefulness. However, the introduction of Tuples (originally to support F#) into .NET shows a possible way to retrofit this feature without syntax enhancement. I demonstrate the technique in C# and COBOL.

Why do we have function signatures like this:

void divideAndRemainder(int numerator, int denominator,ref int div, ref int remain)

The result of the function is obviously polyadic, it has two distinct parts. Because our programming language is not set up to handle polyadic returns, we pass in parameters by reference to act as return values. This is a big fat hack. One or the other, but not both please. What would be great is something like this:

void (int ref, int remain)divideAndRemainder(int numerator, int denominator)

But we cannot have that in C#, VB, Java, COBOL ....

In F#, we do have native syntax for tuples:

let someFunc= (1,"hello world")

The above will produce a strongly typed tuple which contains two items: the first an integer, and the second a string. The function is polyadic. Not only that - but it is implemented on the Common Language Runtime. So, **it must be possible to access whatever structures F# is using from other .NET languages**, and it is. OK, the result is a bit clunky, but it is a first step.

To illustrate, I will use a very simple example: a function to divide an integer by an integer and get the result and remainder. This example shows two huge advantages of the tuple approach.

- It gets rid of the need for reference parameters to synthesize polyadic returns.
- It allows for in-line encapsulation of data by functions, making the role of variables less complex in code, and thus making the code closer to a functional description of what it is actually doing (more self documenting).

Here is the classic C# approach to the example:

...
int local2 = 26;
int local3 = 4;
int local4 = 0;
var local5 = divAndRemainderHorrid(local2, local3,ref local4);
System.Console.WriteLine
(
"Dividing " + local2 +
" by " + local3 +
" gives " + local5 +
" remainder " + local4
);
...
static int divAndRemainderHorrid(int numerator,
int denominator, ref int remainder)
{
remainder = numerator % denominator;
return numerator / denominator;
}
}

There is nothing exactly wrong with this; it is just a mess. The function returns some of its results and passes back some of it via a reference variable. I guess one could make the function `void`

and pass back everything via reference parameters - but that does not seem like much of an improvement. Also, there has to be heavy use of locals to manage all the intermediate storage. This makes chaining of the function near impossible. E.g., we could not make a function `WriteResult`

which encapsulates the `System.Console.Write`

line code and call that with the return from the divide/remainder function without marshalling all the intermediates via local variables.

## Doing it with Tuples

F# tuples are implemented under the covers using `System.Tuple`

. This type has a set of generic factor methods `Create(...)`

which allow the generation of strongly typed tuples of up to 7 elements. It is possible to make longer tuples by chaining them (putting tuples in tuples). F# does this chaining for us; however, in other languages, this has to be done by hand, which makes longer tuples rather clunky. See http://msdn.microsoft.com/en-us/library/system.tuple(VS.100).aspx.

Rather than write lots of text describing tuples further, I have illustrated their use via code.

Example 1 shows a simple example of using tuples so that dividend and remainder are returned in one tuple, thus avoiding the use of a reference parameter. Example 2 shows how we can make the function return a tuple of the passed in parameters and the results so that all the information about the operation is encapsulated. This then allows for simple access to this encapsulated information.

Example 3 is the really interesting one. It shows that by fully encapsulating all the information about a function, it is possible to dispense with local temporary storage (variables) altogether. Example 3 shows how using tuples has allowed us to write code which exactly expresses the actions being performed without having to have loads of operational clutter getting in the way!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Tuples
{
class Program
{
static void Main(string[] args)
{
System.Console.WriteLine("Result=" + DivAndRemainder (10 , 3));
var local1 = DivAndRemainderKeepAll(26, 4);
System.Console.WriteLine
(
"Dividing " + local1.Item1 +
" by " + local1.Item2 +
" gives " + local1.Item3 +
" remainder " + local1.Item4
);
WriteResult(DivAndRemainderKeepAll(26, 4));
int local2 = 26;
int local3 = 4;
int local4 = 0;
var local5 = DivAndRemainderHorrid(local2, local3,ref local4);
System.Console.WriteLine
(
"Dividing " + local2 +
" by " + local3 +
" gives " + local5 +
" remainder " + local4
);
}
static Tuple<int, int> DivAndRemainder(int numerator, int denominator)
{
return Tuple.Create(numerator / denominator, numerator % denominator);
}
static Tuple<int,int,int, int>
DivAndRemainderKeepAll(int numerator, int denominator)
{
return Tuple.Create
(
numerator,
denominator,
numerator / denominator,
numerator % denominator
);
}
static int DivAndRemainderHorrid(int numerator,
int denominator, ref int remainder)
{
remainder = numerator % denominator;
return numerator / denominator;
}
static int WriteResult(Tuple<int, int, int, int> result)
{
System.Console.WriteLine
(
"Dividing " + result.Item1 +
" by " + result.Item2 +
" gives " + result.Item3 +
" remainder " + result.Item4
);
}
}
}

## Doing it with COBOL

Micro Focus COBOL for .NET has full support for generics with a simply syntax. This allows us to use Tuples in a straightforward way:

procedure division
using by value numerator as
binary-long denominator as binary-long
returning result as
type System.Tuple[binary-long binary-long binary-long binary-long].

Above, we can see the signature definition for the `DivAndRemainderKeepAll`

method. This is equivalent to the C#:

static Tuple<int,int,int, int> DivAndRemainderKeepAll(int numerator, int denominator)

Which is 'better' is simply a question of taste. Also, we can note that they are fully interoperable. So the whole of example 3 in COBOL is here:

class-id. "Tuples".
method-id. Main static.
procedure division.
invoke Tuples::WriteResult
(
Tuples::DivAndRemainderKeepAll(26 4)
)
end method.
method-id. DivAndRemainderKeepAll static.
01 div binary-long.
01 rem binary-long.
procedure division
using by value numerator as
binary-long denominator as binary-long
returning result as
type System.Tuple[binary-long binary-long binary-long binary-long].
compute div = numerator / denominator
compute rem = function mod(numerator denominator)
set result to type System.Tuple::Create(numerator denominator div rem)
end method.
method-id. WriteResult static.
procedure division
using by value result
as type System.Tuple[binary-long binary-long binary-long binary-long].
invoke type System.Console::WriteLine
(
String::Format
(
"Dividing {0} by {1} gives {2} remainder {3} "
result::Item1
result::Item2
result::Item3
result::Item4
)
)
end method.
end class.

## Multi-Core and the Cloud - Why this Really Matters

So far, I have presented some nice syntactic reasons for using Tuples specifically, and polyadic returns in general. There is a really major, huge, looming and life critical reason why we - as developers and architects - need to start thinking this way. Hardware is changing - processing distribution is ascendant!

The problem is that passing in reference parameters just to allow polyadic return does not actually express the intent of the programmer. The compiler and runtime must understand the reference parameter has a value which exists outside the scope of the function to which it is passed. It can therefore be updated outside that scope, and updates inside that scope should be visible outside it. These scoping effects are not the intention of the programmer, but the compiler and runtime do not 'know' this.

In a massively multi-core or distributed cloud environment, we might want to execute a function on a different core from the one on which it is called. If the function does not reference any external storage (class, object, or calling function local variables), then there is no reason this cannot be done. However, the reference parameters mean that the compiler and runtime 'think' the function does reference external storage and so they cannot efficiently move execution onto a different core.

## Conclusions

The tuples based patterns used here show how to overcome a major drawback of many traditional programming languages (the lack of polyadic returns) and so pave the way to more efficient program implementations in current and upcoming environments. Where we can expect languages such as COBOL and Algol's children (C#, Java etc.) to continue to do the heavy lifting of much of the computing, these techniques could prove a very useful way forward until such time as explicit polyadic types are added into the syntaxes themselves.