From: Thiago A. on

Using function notation we have expressions like that:

F(G(H(X)))

Where we have to read from inside to outside. It is not so bad; this
is the normal mathematical notation.

However in some cases, I would prefer to read expression from left to
right applying the next function in the previous result.

H(x) G() F()

We can have this kind of expressions using member functions.
x.H().G().H();

In this case, each return type must have member functions for that
algorithm. But algorithms can me separated from data.
The solution that I could think about is to have an overload for
operator dot.

ReturnType operator . H (const X& x)
{
}

This operator dot would be valid only if the expression x.H() was not
defined before using member functions.

The syntax sugar would be useful in some cases.

For instance, we could write:

matrix.Rotate(pi).ReflectHor().Inverse();

instead of:

Inverse(ReflectHor(Rotate(matrix)));

Is this too much syntax sugar?
Is the dot operator overload too hard to be defined? (I know that we
can�t do this today)


Also in C++ we don�t have this kind of syntax sugar:
using x {
.Rotate(pi);
.RefelectHor();
.Inverse();
}




--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Seungbeom Kim on
On 2010-03-31 15:36, Thiago A. wrote:
>
> However in some cases, I would prefer to read expression from left to
> right applying the next function in the previous result.
>
> H(x) G() F()

Only in the (special) case where each function takes one parameter.

Expressions could be made readable from left to right in general, for
example, with a notation that puts the function name on the right:

(w, ((x, y)f1, z)f2)f3

instead of

f3(w, f2(f1(x, y), z))

but this deviates too much from the conventional mathematical notation.

Furthermore, if an expression becomes too long and complicated
to parse at a glance, it's always a good idea to break it up
into smaller expressions and give them proper names.

> The syntax sugar would be useful in some cases.
>
> For instance, we could write:
>
> matrix.Rotate(pi).ReflectHor().Inverse();
>
> instead of:
>
> Inverse(ReflectHor(Rotate(matrix)));

This is already possible, for example, if matrix is an object of
a class that has member functions Rotate, ReflectHor, and Inverse,
and they all return the reference to *this.

This is not much different from the operator chaining:

std::cout << std::setw(8) << value << std::endl

where each function returns the reference to the stream.

> Also in C++ we don�t have this kind of syntax sugar:
> using x {
> .Rotate(pi);
> .RefelectHor();
> .Inverse();
> }

Because it can easily be written out:

x.Rotate(pi);
x.ReflectHor();
x.Inverse();

If x turns out to be a long expression you don't want to repeat,
you can create an alias:

T& x = long_expression_with(arguments);
x.Rotate(pi);
x.ReflectHor();
x.Inverse();

where T could be just written as "auto" in the next version of C++.

--
Seungbeom Kim

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: pfultz2 on

> For instance, we could write:
>
> matrix.Rotate(pi).ReflectHor().Inverse();
>
> instead of:
>
> Inverse(ReflectHor(Rotate(matrix)));

You don't need to overload the dot operator to get this kind of
behaviour. You just have each function return another matrix or a
reference to a matrix like so:

class Matrix
{
public:
Matrix& Rotate(double val)
{
//Do calculations
return *this;
}

Matrix& ReflectHor()
{
//Do calculations
return *this;
}

Matrix& Inverse()
{
//Do calculations
return *this;
}
};

You could return a copy instead of reference if you have an immutable
matrix class. But now you can use your class like so:

Matrix m;
m.Rotate(3.14).ReflectHor().Inverse();


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Andy Venikov on
Thiago A. wrote:
> Using function notation we have expressions like that:
>
> F(G(H(X)))
>
> Where we have to read from inside to outside. It is not so bad; this
> is the normal mathematical notation.
>
> However in some cases, I would prefer to read expression from left to
> right applying the next function in the previous result.
>
> H(x) G() F()
>
> We can have this kind of expressions using member functions.
> x.H().G().H();
>
> In this case, each return type must have member functions for that
> algorithm. But algorithms can me separated from data.
> The solution that I could think about is to have an overload for
> operator dot.
>
> ReturnType operator . H (const X& x)
> {
> }
>
> This operator dot would be valid only if the expression x.H() was not
> defined before using member functions.
>
> The syntax sugar would be useful in some cases.
>
> For instance, we could write:
>
> matrix.Rotate(pi).ReflectHor().Inverse();
>
> instead of:
>
> Inverse(ReflectHor(Rotate(matrix)));


You can't overload operator . ()
But in your case you don't need to.
Just have every algorithm function (like Rotate())
return a reference to a (non-local) object that defines other needed
functions, like ReflectHor()


HTH,
Andy.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Thiago A. on
> > However in some cases, I would prefer to read expression from left to
> > right applying the next function in the previous result.
>
> > H(x) G() F()
>
> Only in the (special) case where each function takes one parameter.
>
> Expressions could be made readable from left to right in general, for
> example, with a notation that puts the function name on the right:
>
> (w, ((x, y)f1, z)f2)f3
>
> instead of
>
> f3(w, f2(f1(x, y), z))
>
> but this deviates too much from the conventional mathematical notation.


The first argument is always the one we can put before the dot, and we
could have N arguments.

For instance, using your sample:

f3(w, f2(f1(x, y), z))

and changing names just to express the idea:

f3_DotProduct(w_vector, f2_Normalize( f1_Rotate(x_vector,
y_scalar), z_scalar))

could be written:

vector_w.f3_DotProduct(vector_x.f1_Rotate(scalar_y).f2_Normalize(scalar_z));



--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]