Operator overloading coolness

Posts   
 
    
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 05-Sep-2005 15:21:02   

I'm currently testing the operator overloads I've implemented in the 1.0.2005.1 code (which I hope to have finished later this week if I can cram in all the little things still on the list). Operator overloads are used for creating expressions, sortclauses and predicate expressions. Furthermore I've added utility methods to EntityField(2) which allow you to chain commands together when setting object alias, aggregate function and expression on a field.

Also added are utility classes which produce an EntityField(2) object with a static method.

I've based some of the things on the ideas expressed by louthy here: http://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=3460

ok, here's some code in the old style:


// SUM((UnitPrice*Quantity)-(UnitPrice*Quantity*Discount/100)) / SUM(Quantity) FROM [Order Details]
// UnitPrice * Quantity
IExpression eP1 = new Expression(EntityFieldFactory.Create(OrderDetailsFieldIndex.UnitPrice), ExOp.Mul, EntityFieldFactory.Create(OrderDetailsFieldIndex.Quantity));
// (UnitPrice * Quantity) * Discount
IExpression eP2 = new Expression(eP1, ExOp.Mul, EntityFieldFactory.Create(OrderDetailsFieldIndex.Discount));
// ((UnitPrice * Quantity) * Discount) / 100
IExpression eP3 = new Expression(eP2, ExOp.Div, 100);
// (UnitPrice * Quantity)-((UnitPrice * Quantity) * Discount) / 100
IExpression eP4 = new Expression(eP1, ExOp.Sub, eP3);

// sum((UnitPrice * Quantity)-((PrecioLocal * Quantity) * Discount) / 100)
IEntityField2 op1=EntityFieldFactory.Create(OrderDetailsFieldIndex.UnitPrice);
op1.ExpressionToApply=eP4;
op1.AggregateFunctionToApply=AggregateFunction.Sum;

// sum(Quantity)
IEntityField2 op2=EntityFieldFactory.Create(OrderDetailsFieldIndex.Quantity);
op2.AggregateFunctionToApply=AggregateFunction.Sum;

// sum((UnitPrice * Quantity)-((UnitPrice * Quantity) * Discount) / 100) / sum(Quantity)
IExpression expRes=new Expression(op1, ExOp.Div, op2);
IPredicate filter = PredicateFactory.CompareValue(OrderDetailsFieldIndex.OrderId, ComparisonOperator.Equal, 10254);
object r=adapter.GetScalar(EntityFieldFactory.Create(OrderDetailsFieldIndex.UnitPrice), expRes, AggregateFunction.None, filter);
Assert.AreEqual(7.88685265796607, r);

and this is the new style:


IExpression expOp1 =  ((OrderDetailsFields.UnitPrice * OrderDetailsFields.Quantity) - 
                    (OrderDetailsFields.UnitPrice * OrderDetailsFields.Quantity * OrderDetailsFields.Discount / 100));
EntityField2 op1 = OrderDetailsFields.UnitPrice.SetAggregateFunction(AggregateFunction.Sum).SetExpression(expOp1);
IExpression scalarExpression = op1 / OrderDetailsFields.Quantity.SetAggregateFunction(AggregateFunction.Sum);

IPredicate filter = (OrderDetailsFields.OrderId == 10254);
object r=adapter.GetScalar(OrderDetailsFields.UnitPrice, scalarExpression, AggregateFunction.None, filter);
Assert.AreEqual(7.88685265796607, r);

it can even be formulated shorter but you get the idea simple_smile

VB.NET on .NET 1.x can't use this, as VB.NET .NET 1.x doesn't support operator overloads, though they can use and have the field utility classes which produce a field, and the utility methods on EntityField(2). People who use VB.NET for .NET 2.0 will be able to use this.

Ok, back to testing.

(ps: this is completely build on top of the current system with predicate objects, predicate expression object etc. etc., so your existing code will keep on working, there is now another, more easier way to write the same code, and you can mix the two as well, if you like simple_smile )

Frans Bouma | Lead developer LLBLGen Pro
alexdresko
User
Posts: 336
Joined: 08-Jun-2004
# Posted on: 05-Sep-2005 20:20:37   

Otis wrote:

there is now another, more easier way to write the same code, and you can mix the two as well, if you like simple_smile )

Wow! That's an understatement!

davisg avatar
davisg
User
Posts: 113
Joined: 27-Feb-2005
# Posted on: 06-Sep-2005 09:40:19   

I'll second that Wow, very clean and much easier to construct. I like it simple_smile

Geoff.

NickD
User
Posts: 224
Joined: 31-Jan-2005
# Posted on: 06-Sep-2005 17:15:06   

Very nice, especially on the hands as typing has been reduced by, what, 75%? And to me the best part is it reads nicer too. Most excellent indeed!

Fishy avatar
Fishy
User
Posts: 392
Joined: 15-Apr-2004
# Posted on: 06-Sep-2005 17:41:44   

Very Cool. Unfortunely I'm using vb. So, could you expand on this or show me where to look:

VB.NET on .NET 1.x can't use this, as VB.NET .NET 1.x doesn't support operator overloads, though they can use and have the field utility classes which produce a field, and the utility methods on EntityField(2).

Thanks,

Fishy (not swiming in the sea-# cry )

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 06-Sep-2005 21:19:42   

Well, the constructions you see, for example the (field == value) construction, produces a Predicate object because the '==' operator is overloaded on EntityField(2). This makes it possible to write normal code with +, -, *, == etc. as if you're working with integers. However, operator overloading is a feature which isn't implemented in VB.NET for .net 1.x, so writing code which uses (Field = value) will result in a compile error, as the operator '=' isn't known to work on an EntityField. So it's a flaw in VB.NET 1.x, however Microsoft has added operator overloading in .NET 2.0 for VB.NET, so it will work there.

Frans Bouma | Lead developer LLBLGen Pro
alexdresko
User
Posts: 336
Joined: 08-Jun-2004
# Posted on: 06-Sep-2005 22:12:41   

Fishy wrote:

Fishy (not swiming in the sea-# cry )

Don't feel too bad.. We who see sharp don't have a functional equiv to your With statement... I miss that thing. simple_smile

Well, we've got 'with', but it's not the same thing.

Fishy avatar
Fishy
User
Posts: 392
Joined: 15-Apr-2004
# Posted on: 06-Sep-2005 23:30:32   

alexdresko wrote:

Fishy wrote:

Fishy (not swiming in the sea-# cry )

Don't feel too bad.. We who see sharp don't have a functional equiv to your With statement... I miss that thing. simple_smile

Well, we've got 'with', but it's not the same thing.

yea, you really need to get 'with' it simple_smile Actually, I don't even use With. It doesn't play well with quickwatch disappointed

Trig
User
Posts: 96
Joined: 09-Jun-2004
# Posted on: 07-Sep-2005 21:31:45   

Very nice Frans! I can't wait to see 2005... BTW, I'm back. wink Finally convinced the new employer of the coolness of LLBLGen.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 08-Sep-2005 10:52:15   

Trig wrote:

Very nice Frans! I can't wait to see 2005... BTW, I'm back. wink Finally convinced the new employer of the coolness of LLBLGen.

Welcome back, Trig! smile

Frans Bouma | Lead developer LLBLGen Pro
Posts: 20
Joined: 06-Sep-2005
# Posted on: 08-Sep-2005 18:06:52   

I'm new to the Gen Pro world; my employer uses it in the shop for a variety of tasks. Anyway, i saw this and jsut wanted to add that operator overloading is very cool and it's good to see it being integrated into the product. It's a personal favorite source level construct and I particularly like to overload the cast operators to perform data type conversions of user-defined types (classes and structs), which can be useful for keeping the lives of downstream developers simple and free of unncecessary details. Anyway, looks like a cool set of features that you are adding.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 09-Sep-2005 20:34:38   

Operators are very cool indeed, it's too bad they didn't allow you to define new operators, like C++ allows you to wink

Frans Bouma | Lead developer LLBLGen Pro
tprohas
User
Posts: 257
Joined: 23-Mar-2004
# Posted on: 10-Sep-2005 00:10:50   

I'm still fairly new to the oo world and am wondering if you could point me to some documentation that explains what Operators are?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 10-Sep-2005 10:51:15   

tprohas wrote:

I'm still fairly new to the oo world and am wondering if you could point me to some documentation that explains what Operators are?

Operators are '+', '-', '&' and the like, the things you use in C# and VB.NET to specify expressions. A == B means A and B are the operands, and '==' is the operator.

so if I do: bool c = (a==b);

and a and c are of some type, you'll know that c will become true if a and b are the same. Now, you can override this behavior of '==' for a type, so that it means something else. That's what I did for for example '==' when the type is an entityfield. You wouldn't use: bool c = (entityfieldA == entityfieldB) anyway, so it's not a clash with normal programming. I've overriden the behavior of '==' to produce a field compare expression predicate if '==' is applied on 2 fields, instead of a boolean. See operator overloading in the MSDN help.

In C++ you can also define new operators. So you could define '#' to become your operator for a given operation and do : c = a # b;

That's not possible on .NET

Frans Bouma | Lead developer LLBLGen Pro
alexdresko
User
Posts: 336
Joined: 08-Jun-2004
# Posted on: 02-Nov-2005 19:49:32   

Take the following example:


Dim filter As IPredicateExpression = _
    ((TableFields.Foo="One") Or (TableFields.Foo="Two")).AddWithOr(TableFields.Foo="Three").AddWithOr(TableFields.Foo="Four")

filter.AddWithOr(TableFields.Foo = "Five")


Is there a shortcut to that second line? I haven't tried it yet, but I assume I could do this for an AddWithAnd predicate..


filter &= (TableFields.Foo = "Five")

alexdresko
User
Posts: 336
Joined: 08-Jun-2004
# Posted on: 02-Nov-2005 19:53:04   

Hrmmmmmmmm... this is getting away from the question I posted above, but tinyforum seems to be acting strange to me.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 02-Nov-2005 21:38:24   

alexdresko wrote:

Hrmmmmmmmm... this is getting away from the question I posted above, but tinyforum seems to be acting strange to me.

It's the quotes, the parser sees a quoted string, but as there's no end quote, throws up and pushes back the parsed tokens. Though they're not reparsed. You forgot a quote after 'Four' simple_smile

About the question: I think it can, but your second line is AddWithOr, not AddWithAnd wink

Frans Bouma | Lead developer LLBLGen Pro