Update on "C# is a D" project
Quote from dandl on May 10, 2020, 8:04 amAfter some deep and meaningful experiments with C# generics, the latest code looks this:
WriteLine(Supplier.S.Select(t => t.Status == 30) .Rename<TupSX>() // "SNo", "SName", "Status", "Supplier City" .Project<Tup1>() // "Supplier City" .Format()); WriteLine(Supplier.P .Rename<TupPcolour>() // "PNo", "PName", "Colour", "Weight", "City" .Select(t => t.Colour == "Red") .Project<TupPPno>() // "PNo", "PName" .Join<TupSP, TupPjoin>(Supplier.SP) // "PNo", "PName", "SNo", "Qty" .Format());I'm happy with this. Actually, better than I expected.
Other points.
- Generalised aggregation as per RM Pre 6 is straightforward. Andl has this, but I'm not aware of any other D that has.
- RM VSS 5 (GTC) is straightforward. Andl has this, I'm not aware of any other D that has.
- RM VSS 6 (user defined generic relational operators) is satisfied. I don't think any other D has it.
- RM VSS 7 (SQL in D) is obviously satisfied.
After some deep and meaningful experiments with C# generics, the latest code looks this:
WriteLine(Supplier.S.Select(t => t.Status == 30) .Rename<TupSX>() // "SNo", "SName", "Status", "Supplier City" .Project<Tup1>() // "Supplier City" .Format()); WriteLine(Supplier.P .Rename<TupPcolour>() // "PNo", "PName", "Colour", "Weight", "City" .Select(t => t.Colour == "Red") .Project<TupPPno>() // "PNo", "PName" .Join<TupSP, TupPjoin>(Supplier.SP) // "PNo", "PName", "SNo", "Qty" .Format());
I'm happy with this. Actually, better than I expected.
Other points.
- Generalised aggregation as per RM Pre 6 is straightforward. Andl has this, but I'm not aware of any other D that has.
- RM VSS 5 (GTC) is straightforward. Andl has this, I'm not aware of any other D that has.
- RM VSS 6 (user defined generic relational operators) is satisfied. I don't think any other D has it.
- RM VSS 7 (SQL in D) is obviously satisfied.
Quote from Dave Voorhis on May 10, 2020, 9:07 amQuote from dandl on May 10, 2020, 8:04 am
- Generalised aggregation as per RM Pre 6 is straightforward. Andl has this, but I'm not aware of any other D that has.
Rel does. See https://reldb.org/c/wp-content/uploads/2016/06/User-Defined-Aggregate-Operators-in-Tutorial-D-and-Rel.pdf
Quote from dandl on May 10, 2020, 8:04 am
- Generalised aggregation as per RM Pre 6 is straightforward. Andl has this, but I'm not aware of any other D that has.
Rel does. See https://reldb.org/c/wp-content/uploads/2016/06/User-Defined-Aggregate-Operators-in-Tutorial-D-and-Rel.pdf
Quote from dandl on May 12, 2020, 11:27 amQuote from Dave Voorhis on May 10, 2020, 9:07 amQuote from dandl on May 10, 2020, 8:04 am
- Generalised aggregation as per RM Pre 6 is straightforward. Andl has this, but I'm not aware of any other D that has.
Rel does. See https://reldb.org/c/wp-content/uploads/2016/06/User-Defined-Aggregate-Operators-in-Tutorial-D-and-Rel.pdf
It does indeed. Not quite the OO Pre 6, but actually in a way I prefer it. But I guess it took you quite a while to figure all that out?
I just added aggregation to by 'C# as a D' project. It looks like this.
WriteLine("Aggregation"); WriteLine(Supplier.SP .Aggregate<TupAgg,int>((t,a) => a + t.Qty) // "PNo", "TotQty" .Format()); public class TupAgg : TupleBase { public readonly static string[] Heading = { "PNo", "TotQty" }; } Aggregation PNo: P1, TotQty: 600 PNo: P2, TotQty: 1000 PNo: P3, TotQty: 400 PNo: P4, TotQty: 500 PNo: P5, TotQty: 500 PNo: P6, TotQty: 100Took maybe half a day, including debugging some dumb mistakes. The bar for adding features is low.
Quote from Dave Voorhis on May 10, 2020, 9:07 amQuote from dandl on May 10, 2020, 8:04 am
- Generalised aggregation as per RM Pre 6 is straightforward. Andl has this, but I'm not aware of any other D that has.
Rel does. See https://reldb.org/c/wp-content/uploads/2016/06/User-Defined-Aggregate-Operators-in-Tutorial-D-and-Rel.pdf
It does indeed. Not quite the OO Pre 6, but actually in a way I prefer it. But I guess it took you quite a while to figure all that out?
I just added aggregation to by 'C# as a D' project. It looks like this.
WriteLine("Aggregation"); WriteLine(Supplier.SP .Aggregate<TupAgg,int>((t,a) => a + t.Qty) // "PNo", "TotQty" .Format()); public class TupAgg : TupleBase { public readonly static string[] Heading = { "PNo", "TotQty" }; } Aggregation PNo: P1, TotQty: 600 PNo: P2, TotQty: 1000 PNo: P3, TotQty: 400 PNo: P4, TotQty: 500 PNo: P5, TotQty: 500 PNo: P6, TotQty: 100
Took maybe half a day, including debugging some dumb mistakes. The bar for adding features is low.
Quote from Dave Voorhis on May 12, 2020, 12:40 pmQuote from dandl on May 12, 2020, 11:27 amQuote from Dave Voorhis on May 10, 2020, 9:07 amQuote from dandl on May 10, 2020, 8:04 am
- Generalised aggregation as per RM Pre 6 is straightforward. Andl has this, but I'm not aware of any other D that has.
Rel does. See https://reldb.org/c/wp-content/uploads/2016/06/User-Defined-Aggregate-Operators-in-Tutorial-D-and-Rel.pdf
It does indeed. Not quite the OO Pre 6, but actually in a way I prefer it. But I guess it took you quite a while to figure all that out?
Yes. As I recall, it was most of an afternoon. The actual aggregation was trivial, particularly as I'd added lambda expressions to Rel some time before. Determining how to slot user-defined aggregation into Tutorial D syntax and semantics so that it would work without changing existing Tutorial D code was most of it.
Quote from dandl on May 12, 2020, 11:27 amQuote from Dave Voorhis on May 10, 2020, 9:07 amQuote from dandl on May 10, 2020, 8:04 am
- Generalised aggregation as per RM Pre 6 is straightforward. Andl has this, but I'm not aware of any other D that has.
Rel does. See https://reldb.org/c/wp-content/uploads/2016/06/User-Defined-Aggregate-Operators-in-Tutorial-D-and-Rel.pdf
It does indeed. Not quite the OO Pre 6, but actually in a way I prefer it. But I guess it took you quite a while to figure all that out?
Yes. As I recall, it was most of an afternoon. The actual aggregation was trivial, particularly as I'd added lambda expressions to Rel some time before. Determining how to slot user-defined aggregation into Tutorial D syntax and semantics so that it would work without changing existing Tutorial D code was most of it.
Quote from dandl on May 14, 2020, 1:22 amI've added
while
and Generalised Transitive Closure to my 'C# is a D' project (RM VSS 5). The sample is per DTATRM p238.I also added Transform (superset of Rename, Project, Extend). It can really shorten and simplify the code. I'm surprised TD doesn't have it.
That completes the Extended RA:
- First order (Codd): Select, Project, Join, Rename, Union (literals only)
- Negation: Antijoin, Minus
- Functional: Select, Extend, Transform, Aggregate
- Recursive: Transitive Closure, Generalised TC, While
// code WriteLine("While"); var seed = MMQData.MMQ.Extend<TupMMQA>(t => t.Qty); // "Major", "Minor", "Qty", "AggQty" var zmq = MMQData.MMQ.Rename<TupzMQ>(); // "zmatch", "Minor", "Qty" var exp = seed.While(t => t .Rename<TupMzA>() // "Major", "zmatch", "AggQty" .Join<TupzMQ, TupMMQA>(zmq) .Transform<TupMMQA>(tt => TupMMQA.Create(tt.Major, tt.Minor, 0, tt.AggQty * tt.Qty))); WriteLine(exp.Format()); WriteLine("P1 -> P5"); WriteLine(exp.Select(t => t.Major == "P1" && t.Minor == "P5") .Aggregate<TupMMT,int>((t,a) => a + t.AggQty) .Format()); // type definitions public class RelMMQA : RelationBase<TupMMQ> { } public class TupMMQA : TupMMQ { new public readonly static string[] Heading = { "Major", "Minor", "Qty", "AggQty" }; public int AggQty { get { return (int)Values[3]; } } public static TupMMQA Create(string major, string minor, int qty, int aggqty) { return Create<TupMMQA>(new object[] { major, minor, qty, aggqty }); } } public class TupMzA : TupleBase { public readonly static string[] Heading = { "Major", "zmatch", "AggQty" }; } public class TupzMQ : TupleBase { public readonly static string[] Heading = { "zmatch", "Minor", "Qty" }; } public class TupMMT : TupleBase { public readonly static string[] Heading = { "Major", "Minor", "TotQty" }; } // data public static class MMQData { public static RelMMQ MMQ = RelMMQ.Create<RelMMQ>( new List<TupMMQ> { TupMMQ.Create("P1", "P2", 5), TupMMQ.Create("P1", "P3", 3), TupMMQ.Create("P2", "P3", 2), TupMMQ.Create("P2", "P4", 7), TupMMQ.Create("P3", "P5", 4), TupMMQ.Create("P4", "P6", 8), }); } // output While Major: P4, Minor: P6, Qty: 8, AggQty: 8 Major: P3, Minor: P5, Qty: 4, AggQty: 4 Major: P2, Minor: P4, Qty: 7, AggQty: 7 Major: P2, Minor: P6, Qty: 0, AggQty: 56 Major: P2, Minor: P3, Qty: 2, AggQty: 2 Major: P2, Minor: P5, Qty: 0, AggQty: 8 Major: P1, Minor: P3, Qty: 3, AggQty: 3 Major: P1, Minor: P5, Qty: 0, AggQty: 12 Major: P1, Minor: P2, Qty: 5, AggQty: 5 Major: P1, Minor: P4, Qty: 0, AggQty: 35 Major: P1, Minor: P6, Qty: 0, AggQty: 280 Major: P1, Minor: P3, Qty: 0, AggQty: 10 Major: P1, Minor: P5, Qty: 0, AggQty: 40 P1 -> P5 Major: P1, Minor: P5, TotQty: 52
I've added while
and Generalised Transitive Closure to my 'C# is a D' project (RM VSS 5). The sample is per DTATRM p238.
I also added Transform (superset of Rename, Project, Extend). It can really shorten and simplify the code. I'm surprised TD doesn't have it.
That completes the Extended RA:
- First order (Codd): Select, Project, Join, Rename, Union (literals only)
- Negation: Antijoin, Minus
- Functional: Select, Extend, Transform, Aggregate
- Recursive: Transitive Closure, Generalised TC, While
// code WriteLine("While"); var seed = MMQData.MMQ.Extend<TupMMQA>(t => t.Qty); // "Major", "Minor", "Qty", "AggQty" var zmq = MMQData.MMQ.Rename<TupzMQ>(); // "zmatch", "Minor", "Qty" var exp = seed.While(t => t .Rename<TupMzA>() // "Major", "zmatch", "AggQty" .Join<TupzMQ, TupMMQA>(zmq) .Transform<TupMMQA>(tt => TupMMQA.Create(tt.Major, tt.Minor, 0, tt.AggQty * tt.Qty))); WriteLine(exp.Format()); WriteLine("P1 -> P5"); WriteLine(exp.Select(t => t.Major == "P1" && t.Minor == "P5") .Aggregate<TupMMT,int>((t,a) => a + t.AggQty) .Format()); // type definitions public class RelMMQA : RelationBase<TupMMQ> { } public class TupMMQA : TupMMQ { new public readonly static string[] Heading = { "Major", "Minor", "Qty", "AggQty" }; public int AggQty { get { return (int)Values[3]; } } public static TupMMQA Create(string major, string minor, int qty, int aggqty) { return Create<TupMMQA>(new object[] { major, minor, qty, aggqty }); } } public class TupMzA : TupleBase { public readonly static string[] Heading = { "Major", "zmatch", "AggQty" }; } public class TupzMQ : TupleBase { public readonly static string[] Heading = { "zmatch", "Minor", "Qty" }; } public class TupMMT : TupleBase { public readonly static string[] Heading = { "Major", "Minor", "TotQty" }; } // data public static class MMQData { public static RelMMQ MMQ = RelMMQ.Create<RelMMQ>( new List<TupMMQ> { TupMMQ.Create("P1", "P2", 5), TupMMQ.Create("P1", "P3", 3), TupMMQ.Create("P2", "P3", 2), TupMMQ.Create("P2", "P4", 7), TupMMQ.Create("P3", "P5", 4), TupMMQ.Create("P4", "P6", 8), }); } // output While Major: P4, Minor: P6, Qty: 8, AggQty: 8 Major: P3, Minor: P5, Qty: 4, AggQty: 4 Major: P2, Minor: P4, Qty: 7, AggQty: 7 Major: P2, Minor: P6, Qty: 0, AggQty: 56 Major: P2, Minor: P3, Qty: 2, AggQty: 2 Major: P2, Minor: P5, Qty: 0, AggQty: 8 Major: P1, Minor: P3, Qty: 3, AggQty: 3 Major: P1, Minor: P5, Qty: 0, AggQty: 12 Major: P1, Minor: P2, Qty: 5, AggQty: 5 Major: P1, Minor: P4, Qty: 0, AggQty: 35 Major: P1, Minor: P6, Qty: 0, AggQty: 280 Major: P1, Minor: P3, Qty: 0, AggQty: 10 Major: P1, Minor: P5, Qty: 0, AggQty: 40 P1 -> P5 Major: P1, Minor: P5, TotQty: 52
Quote from Erwin on May 14, 2020, 8:55 amQuote from Dave Voorhis on May 10, 2020, 9:07 amQuote from dandl on May 10, 2020, 8:04 am
- Generalised aggregation as per RM Pre 6 is straightforward. Andl has this, but I'm not aware of any other D that has.
Rel does. See https://reldb.org/c/wp-content/uploads/2016/06/User-Defined-Aggregate-Operators-in-Tutorial-D-and-Rel.pdf
SIRA_PRISE has too. See http://shark.armchair.mb.ca/~erwin/languageandgrammar_0105.html
Quote from Dave Voorhis on May 10, 2020, 9:07 amQuote from dandl on May 10, 2020, 8:04 am
- Generalised aggregation as per RM Pre 6 is straightforward. Andl has this, but I'm not aware of any other D that has.
Rel does. See https://reldb.org/c/wp-content/uploads/2016/06/User-Defined-Aggregate-Operators-in-Tutorial-D-and-Rel.pdf
SIRA_PRISE has too. See http://shark.armchair.mb.ca/~erwin/languageandgrammar_0105.html
Quote from Dave Voorhis on May 14, 2020, 10:08 amQuote from Erwin on May 14, 2020, 8:55 amQuote from Dave Voorhis on May 10, 2020, 9:07 amQuote from dandl on May 10, 2020, 8:04 am
- Generalised aggregation as per RM Pre 6 is straightforward. Andl has this, but I'm not aware of any other D that has.
Rel does. See https://reldb.org/c/wp-content/uploads/2016/06/User-Defined-Aggregate-Operators-in-Tutorial-D-and-Rel.pdf
SIRA_PRISE has too. See http://shark.armchair.mb.ca/~erwin/languageandgrammar_0105.html
Doesn't SIRA_PRISE have generalised transitive closure, too?
Quote from Erwin on May 14, 2020, 8:55 amQuote from Dave Voorhis on May 10, 2020, 9:07 amQuote from dandl on May 10, 2020, 8:04 am
- Generalised aggregation as per RM Pre 6 is straightforward. Andl has this, but I'm not aware of any other D that has.
Rel does. See https://reldb.org/c/wp-content/uploads/2016/06/User-Defined-Aggregate-Operators-in-Tutorial-D-and-Rel.pdf
SIRA_PRISE has too. See http://shark.armchair.mb.ca/~erwin/languageandgrammar_0105.html
Doesn't SIRA_PRISE have generalised transitive closure, too?
Quote from dandl on May 14, 2020, 10:34 amI've added relational assignment and the conventional shortcuts: insert, update and delete.
It should be noted that these are all type safe and provide native type inference in the editor. In fact that's also true of select, while, union and friends. It's the operators that depend on the heading that can cause errors that need to be detected at runtime: project, rename, join and related.
// code WriteLine("Insert P6 P7"); v1.Insert( RelS.Create<RelS>( new List<TupS> { TupS.Create( "S6", "White", 25, "Paris" ), TupS.Create( "S7", "Black", 15, "London" ), }) ); WriteLine(v1.Format()); WriteLine("Move to Sydney"); v1.Update(t => t.City == "Paris", t => TupS.Create(t.SNo, t.SName, t.Status, "Sydney")); WriteLine(v1.Format()); WriteLine("Delete Sydneysiders"); v1.Delete(t => t.City == "Sydney"); WriteLine(v1.Format()); // output Insert P6 P7 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 SNo: S6, SName: White, Status: 25, City: Paris SNo: S7, SName: Black, Status: 15, City: London Move to Sydney SNo: S1, SName: Smith, Status: 20, City: London SNo: S2, SName: Jones, Status: 10, City: Sydney SNo: S3, SName: Blake, Status: 30, City: Sydney SNo: S4, SName: Clark, Status: 20, City: London SNo: S5, SName: Adams, Status: 30, City: Athens SNo: S6, SName: White, Status: 25, City: Sydney SNo: S7, SName: Black, Status: 15, City: London Delete Sydneysiders SNo: S1, SName: Smith, Status: 20, City: London SNo: S4, SName: Clark, Status: 20, City: London SNo: S5, SName: Adams, Status: 30, City: Athens SNo: S7, SName: Black, Status: 15, City: London
I've added relational assignment and the conventional shortcuts: insert, update and delete.
It should be noted that these are all type safe and provide native type inference in the editor. In fact that's also true of select, while, union and friends. It's the operators that depend on the heading that can cause errors that need to be detected at runtime: project, rename, join and related.
// code WriteLine("Insert P6 P7"); v1.Insert( RelS.Create<RelS>( new List<TupS> { TupS.Create( "S6", "White", 25, "Paris" ), TupS.Create( "S7", "Black", 15, "London" ), }) ); WriteLine(v1.Format()); WriteLine("Move to Sydney"); v1.Update(t => t.City == "Paris", t => TupS.Create(t.SNo, t.SName, t.Status, "Sydney")); WriteLine(v1.Format()); WriteLine("Delete Sydneysiders"); v1.Delete(t => t.City == "Sydney"); WriteLine(v1.Format()); // output Insert P6 P7 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 SNo: S6, SName: White, Status: 25, City: Paris SNo: S7, SName: Black, Status: 15, City: London Move to Sydney SNo: S1, SName: Smith, Status: 20, City: London SNo: S2, SName: Jones, Status: 10, City: Sydney SNo: S3, SName: Blake, Status: 30, City: Sydney SNo: S4, SName: Clark, Status: 20, City: London SNo: S5, SName: Adams, Status: 30, City: Athens SNo: S6, SName: White, Status: 25, City: Sydney SNo: S7, SName: Black, Status: 15, City: London Delete Sydneysiders SNo: S1, SName: Smith, Status: 20, City: London SNo: S4, SName: Clark, Status: 20, City: London SNo: S5, SName: Adams, Status: 30, City: Athens SNo: S7, SName: Black, Status: 15, City: London
Quote from dandl on May 14, 2020, 10:44 amQuote from Dave Voorhis on May 14, 2020, 10:08 amQuote from Erwin on May 14, 2020, 8:55 amQuote from Dave Voorhis on May 10, 2020, 9:07 amQuote from dandl on May 10, 2020, 8:04 am
- Generalised aggregation as per RM Pre 6 is straightforward. Andl has this, but I'm not aware of any other D that has.
Rel does. See https://reldb.org/c/wp-content/uploads/2016/06/User-Defined-Aggregate-Operators-in-Tutorial-D-and-Rel.pdf
SIRA_PRISE has too. See http://shark.armchair.mb.ca/~erwin/languageandgrammar_0105.html
Doesn't SIRA_PRISE have generalised transitive closure, too?
If not, I'm sure it could be added easily (and you should add it to Rel as well). A while operator just isn't hard. Happy to provide code if you need it (but I'm sure you don't).
Quote from Dave Voorhis on May 14, 2020, 10:08 amQuote from Erwin on May 14, 2020, 8:55 amQuote from Dave Voorhis on May 10, 2020, 9:07 amQuote from dandl on May 10, 2020, 8:04 am
- Generalised aggregation as per RM Pre 6 is straightforward. Andl has this, but I'm not aware of any other D that has.
Rel does. See https://reldb.org/c/wp-content/uploads/2016/06/User-Defined-Aggregate-Operators-in-Tutorial-D-and-Rel.pdf
SIRA_PRISE has too. See http://shark.armchair.mb.ca/~erwin/languageandgrammar_0105.html
Doesn't SIRA_PRISE have generalised transitive closure, too?
If not, I'm sure it could be added easily (and you should add it to Rel as well). A while operator just isn't hard. Happy to provide code if you need it (but I'm sure you don't).
Quote from Dave Voorhis on May 14, 2020, 11:10 amQuote from dandl on May 14, 2020, 10:44 amQuote from Dave Voorhis on May 14, 2020, 10:08 amQuote from Erwin on May 14, 2020, 8:55 amQuote from Dave Voorhis on May 10, 2020, 9:07 amQuote from dandl on May 10, 2020, 8:04 am
- Generalised aggregation as per RM Pre 6 is straightforward. Andl has this, but I'm not aware of any other D that has.
Rel does. See https://reldb.org/c/wp-content/uploads/2016/06/User-Defined-Aggregate-Operators-in-Tutorial-D-and-Rel.pdf
SIRA_PRISE has too. See http://shark.armchair.mb.ca/~erwin/languageandgrammar_0105.html
Doesn't SIRA_PRISE have generalised transitive closure, too?
If not, I'm sure it could be added easily (and you should add it to Rel as well). A while operator just isn't hard. Happy to provide code if you need it (but I'm sure you don't).
I'm not sure there's much justification for a generalised transitive closure or while, because Tutorial D / Rel supports general-purpose recursive functions.
Quote from dandl on May 14, 2020, 10:44 amQuote from Dave Voorhis on May 14, 2020, 10:08 amQuote from Erwin on May 14, 2020, 8:55 amQuote from Dave Voorhis on May 10, 2020, 9:07 amQuote from dandl on May 10, 2020, 8:04 am
- Generalised aggregation as per RM Pre 6 is straightforward. Andl has this, but I'm not aware of any other D that has.
Rel does. See https://reldb.org/c/wp-content/uploads/2016/06/User-Defined-Aggregate-Operators-in-Tutorial-D-and-Rel.pdf
SIRA_PRISE has too. See http://shark.armchair.mb.ca/~erwin/languageandgrammar_0105.html
Doesn't SIRA_PRISE have generalised transitive closure, too?
If not, I'm sure it could be added easily (and you should add it to Rel as well). A while operator just isn't hard. Happy to provide code if you need it (but I'm sure you don't).
I'm not sure there's much justification for a generalised transitive closure or while, because Tutorial D / Rel supports general-purpose recursive functions.