The Forum for Discussion about The Third Manifesto and Related Matters

You need to log in to create posts and topics.

So C# really can be a D, but there are issues...

It's a common paradigm in OO programming to instantiate an object using a constructor, make sure it's initialised well enough to survive, and then modify that object. Maybe add more data, connect it to other objects, calculate something, whatever. Create a collection, then add stuff to it. Create a linked list, add items to it. A similar strategy used to apply to structs created in C before we had C++. Values don't work like that.

What I have found from getting C# to satisfy the requirements of TTM/D is that it involves a fundamentally different approach. Every selector creates an object (value) that has to be fully formed at creation, and immutable thereafter. Every collection has to be created with all its content in place. Every operator that returns a value has to create an object that is fully populated and ready to roll.

In C# terms, this means that every selector and every operator has to be told what type of object it is supposed to return in order for it to create and populate the object. There is a whole lot of creating going on! And every  object needs a type declaration. And since a relation has a body of tuples, every relation needs two type declarations: one for the relation and one for a tuple. Molto declarations also. The example given here has 6 of them.

Here is some working code.

Console.WriteLine(Rel1.Project(RelSX.Rename(Supplier.S.Select(t => t.Status == 30))));

Translation: Find all the cities for suppliers with status=30 but rename the attribute as "Supplier City". Here are the type declarations:

public class TupSX : TupleBase { // for Rename
  public readonly static string[] Heading = { "SNo", "SName", "Status", "Supplier City" };
public class RelSX : RelationBase<TupSX> { }
public class Tup1 : TupleBase { // for Projection
  public readonly static string[] Heading = { "Supplier City" };
public class Rel1 : RelationBase<Tup1> { }

And here is the literal data:

public class TupS : TupleBase {
  public readonly static string[] Heading = { "SNo", "SName", "Status", "City" };

  public string Sno { get { return (string)_values[0]; } }
  public string Sname { get { return (string)_values[1]; } }
  public int Status { get { return (int)_values[2]; } }
  public string City { get { return (string)_values[3]; } }

  public static TupS Create(string Sno, string Sname, int Status, string City) {
    return Create<TupS>(new object[] { Sno, Sname, Status, City });
  public static RelS S = RelS.Create(
    new List<TupS> {
      TupS.Create( "S1", "Smith", 20, "London" ),
      TupS.Create( "S2", "Jones", 10, "Paris" ),
      TupS.Create( "S3", "Blake", 30, "Paris" ),
      TupS.Create( "S4", "Clark", 20, "London" ),
      TupS.Create( "S5", "Adams", 30, "Athens" ),

The output:

SNo: S1, SName: Smith, Status: 20, City: London
SNo: S2, SName: Jones, Status: 10, City: Paris
SNo: S3, SName: Blake, Status: 30, City: Paris
SNo: S4, SName: Clark, Status: 20, City: London
SNo: S5, SName: Adams, Status: 30, City: Athens
Supplier City: Paris
Supplier City: Athens

So the good news is it's feasible and it works. Implementing the RA once the types are in place is almost trivial. As far as I can see it can satisfy all the Prerequisites of the TTM D language and its type system (excluding Possreps and the IM). I can't find any gaps.

But without some serious behind the scenes support for creating and checking all those types, I can't see it catching on in a hurry. The code is nice enough, but the declarations are the killer.

I'm going to try and see whether a pipeline approach can avoid creating all those intermediate types along the way, but I'm already pushing the C# generics pretty hard. We'll see.


Andl - A New Database Language -