July 12, 2004
In article <ccumam$2omh$1@digitaldaemon.com>, Charlie says...
>
>>I've never seen static
>>opCall used for any purpose OTHER than emulating constructors
>
>Ive used for functors before.

Are you sure you aren't referring to opCall()? (As opposed to static opCall())?

I would have thought that a /static/ functor was just ... well ... a function. Albeit one with a uppercase first letter.

Arcane Jill



July 12, 2004
Andy Friesen wrote:
> Arcane Jill wrote:
> 
>> In article <cctj4p$115q$1@digitaldaemon.com>, Mike Parker says...
>>
>>
>>> struct Foo
>>> {
>>>   int x;
>>>   static Foo opCall(int i)
>>>   {
>>>       Foo f;
>>>       f.x = i;
>>>       return f;
>>>   }
>>> }
>>>
>>> Foo foo = Foo(5);
>>
>>
>>
>> See, Walter. I told you - people are using static opCall to simulate
>> constructors. You can do this for both structs and classes. For structs, the
>> advantage is, you GET constructor-like calls. For classes, the advantage is, you
>> get to dispense with the unnecessary word "new".
>>
>> I have suggested this before (though I gather you didn't like the suggestion)
>> that (1) structs should be allowed constructors; (2) the keyword "new" should be
>> ditched, or at least made optional, in constructor calls; and (3) static opCall
>> be deprecated in favor of constructors. The language would be SO much neater and
>> cleaner with these changes built in.
>>
>> I find it hard to believe, after all, that the use of static opCall as
>> demonstrated above was a DESIGN FEATURE of D. I mean - I've never seen static
>> opCall used for any purpose OTHER than emulating constructors. I find it more
>> believable that someone simply discovered that the compiler lets you get away
>> with it, and started using it because structs don't have constructors. It would
>> be really nice to tidy this up - even if only for syntactic consistency.
> 
> 
> 'this' syntax for struct constructors is definitely a good idea: programmers try it first when they need the functionality, so it stands to reason that they are right and D is (currently) wrong.
> 
> Playing with 'new' isn't a good idea, though.  As it stands, 'new' always means allocating something on the heap.  This must always be the case for objects, but there are still structs and other value types which can be on the stack or heap.
> 
> This should do it:
> 
>     struct Rectangle {
>         int x, y, w, h;
>         this(int x, int y, int w, int h) { ... }
>     }
> 
>     Rectangle r = Rectangle(...); // initialized stack variable
>     Rectangle* p = new Rectangle(...); // heap allocated instance
> 
>  -- andy
the point is that then you have to jump through hoops to get templates that should work for both structs and classes working... I think there needs to be some work to add transparency to types... making them all act different, construct different and copy different makes it next-to-impossible to make a template class that works for all (case in point see my float1,2,3,4 structs that need to accept integers, classes (i.e. BigInt) or other floatX structs.

I accomplished this with a ton of template specialization...but Walter's right... template specialization is really ugly and it doesn't make things easy to write.
particularly I can't do things like
int x= int(1);
why not? that owuld match the
mystruct x= mystruct(1);
and an opcall'd class
myclass x = myclass(1); //then I have to write a useless opcall function for each overloaded constructor...and I can't make one template constructor because the compiler can't autoinstantiate.
July 12, 2004
"Matthias Becker" <Matthias_member@pathlink.com> wrote in message news:ccth2r$tg7$1@digitaldaemon.com...
> All people here allwas say: "D is great!". So it seems like I'm stupid or something. Every second program I try to write using D doesn't work
because of
> some unexpected behavor of D.
>
> E.g.
>
> This works:
>
> class Foo {
> Foo recursive;
> }
>
> This works:
>
> class Bar (T) {
> T value;
> }
>
> So is it realy that stupid that this works:
>
> class Baz (T) {
> Baz!(T) recursive;
> }

The way to write it is:

class Baz (T) {
    Baz recursive;
}

Or use the '.' global scope operator in front of the Baz:

class Baz (T) {
    .Baz!(T) recursive;
}

The rule is that, within the class body, the name found is the name of the class instantiation, not the class template. The class instantiation name is "Baz". To get the class template, you'll need to go outside of the scope using the '.' scope operator, or start with the module name:

module foo;
class Baz (T) {
    foo.Baz!(T) recursive;
}


> Even experienced programmers like Andy F. are fooled by the language. We
wanted
> to simulate the simple ML-line
>
> fun mul x y = x * y
>
> So he wrote:
>
> template MulReturnType (T, U) {
> alias typeof(T.init * U.init) MulReturnType;
> }
>
>
> template mul (T, U) {
> MulReturnType!(T, U) mul (T x, U y)
> {
> return x * y;
> }
> }
>
>
> Of course this doesn't work, as you can overload opMul and structs and
classes
> don't have an init-property.

The following does work:

------------------------------------------------------------------
template MulReturnType (T, U)
{
    alias typeof(T.init * U.init) MulReturnType;
}


template mul (T, U)
{
    MulReturnType!(T, U) mul (T x, U y)
    {
 return x * y;
    }
}

class X { int opMul(X); }
struct Y { int opMul(Y); }


void test()
{
    X x,y;

    mul!(X,X)(x, y);

    Y a, b;

    mul!(Y,Y)(a, b);
}
-------------------------------------------------------------
Or even in one line, as the MulReturnType template is unnecessary:

template mul (T, U) {  typeof(T.init * U.init) mul (T x, U y) { return x *
y; }}



July 12, 2004
On Mon, 12 Jul 2004 11:10:58 +0000 (UTC), Arcane Jill <Arcane_member@pathlink.com> wrote:
> In article <cctj4p$115q$1@digitaldaemon.com>, Mike Parker says...
>
>> struct Foo
>> {
>>    int x;
>>    static Foo opCall(int i)
>>    {
>>        Foo f;
>>        f.x = i;
>>        return f;
>>    }
>> }
>>
>> Foo foo = Foo(5);
>
> See, Walter. I told you - people are using static opCall to simulate
> constructors. You can do this for both structs and classes. For structs, the
> advantage is, you GET constructor-like calls. For classes, the advantage is, you
> get to dispense with the unnecessary word "new".

I agree constructors for structs would be great.

I don't think getting rid of 'new' is necessarily a big advantage, it may even be a disadvantage as it obfuscates what the call is actually doing. That is, creating a 'new' object.

However, if structs got a real constructor and did not require 'new', then classes should not require a 'new' either.

> I have suggested this before (though I gather you didn't like the suggestion)
> that (1) structs should be allowed constructors;

Agree.

> (2) the keyword "new" should be
> ditched, or at least made optional, in constructor calls;

Perhaps, perhaps not, I'm still on the fence.

> and (3) static opCall
> be deprecated in favor of constructors.

I don't agree. opCall has more uses than simply simulating a constructor. I have used a C++ class with the STL as a comparisson 'function' using operator() overloads. This allows you to pack a bunch of stuff that you require for the comparrison into the class and then use it in the operator() method.

> The language would be SO much neater and
> cleaner with these changes built in.
>
> I find it hard to believe, after all, that the use of static opCall as
> demonstrated above was a DESIGN FEATURE of D. I mean - I've never seen static
> opCall used for any purpose OTHER than emulating constructors.

I think I have given an example of one? I'm not sure whether it is possible to do that example in D.. I have never tried. Not cos I don't need it, but cos I am not doing serious development in D yet.

> I find it more
> believable that someone simply discovered that the compiler lets you get away
> with it, and started using it because structs don't have constructors. It would
> be really nice to tidy this up - even if only for syntactic consistency.

As always, I agree with *most* of what you have said.

Regan

-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
July 12, 2004
On Tue, 13 Jul 2004 09:49:56 +1200, Regan Heath <regan@netwin.co.nz> wrote:
> On Mon, 12 Jul 2004 11:10:58 +0000 (UTC), Arcane Jill <Arcane_member@pathlink.com> wrote:
>> In article <cctj4p$115q$1@digitaldaemon.com>, Mike Parker says...
>>
>>> struct Foo
>>> {
>>>    int x;
>>>    static Foo opCall(int i)
>>>    {
>>>        Foo f;
>>>        f.x = i;
>>>        return f;
>>>    }
>>> }
>>>
>>> Foo foo = Foo(5);
>>
>> See, Walter. I told you - people are using static opCall to simulate
>> constructors. You can do this for both structs and classes. For structs, the
>> advantage is, you GET constructor-like calls. For classes, the advantage is, you
>> get to dispense with the unnecessary word "new".
>
> I agree constructors for structs would be great.
>
> I don't think getting rid of 'new' is necessarily a big advantage, it may even be a disadvantage as it obfuscates what the call is actually doing. That is, creating a 'new' object.
>
> However, if structs got a real constructor and did not require 'new', then classes should not require a 'new' either.
>
>> I have suggested this before (though I gather you didn't like the suggestion)
>> that (1) structs should be allowed constructors;
>
> Agree.
>
>> (2) the keyword "new" should be
>> ditched, or at least made optional, in constructor calls;
>
> Perhaps, perhaps not, I'm still on the fence.
>
>> and (3) static opCall
>> be deprecated in favor of constructors.
>
> I don't agree. opCall has more uses than simply simulating a constructor. I have used a C++ class with the STL as a comparisson 'function' using operator() overloads. This allows you to pack a bunch of stuff that you require for the comparrison into the class and then use it in the operator() method.

I just read the rest of the messages in this thread and have realised I'm not talking about a /static/ opCall. :) Oops.

>> The language would be SO much neater and
>> cleaner with these changes built in.
>>
>> I find it hard to believe, after all, that the use of static opCall as
>> demonstrated above was a DESIGN FEATURE of D. I mean - I've never seen static
>> opCall used for any purpose OTHER than emulating constructors.
>
> I think I have given an example of one? I'm not sure whether it is possible to do that example in D.. I have never tried. Not cos I don't need it, but cos I am not doing serious development in D yet.
>
>> I find it more
>> believable that someone simply discovered that the compiler lets you get away
>> with it, and started using it because structs don't have constructors. It would
>> be really nice to tidy this up - even if only for syntactic consistency.
>
> As always, I agree with *most* of what you have said.
>
> Regan
>



-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
July 12, 2004
On Mon, 12 Jul 2004 19:16:20 +0200, Sigbjørn Lund Olsen <sigbjorn@lundolsen.net> wrote:

> Matthias Becker wrote:
>
>> Could anybody explain me, in which I you'd want to overload opMul on classes?
>
> class Matrix
> {
> 	// snip
> }
>
> Cheers,
> Sigbjørn Lund Olsen

Wouldn't you rather that was

struct Matrix
{
}

is a Matrix a 'value' type, or a 'reference' type?

Regan.

-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
July 12, 2004
On Mon, 12 Jul 2004 08:59:24 +0000 (UTC), Arcane Jill <Arcane_member@pathlink.com> wrote:

> In article <ccthi2$ucn$1@digitaldaemon.com>, Lars Ivar Igesund says...
>>
>> Matthias Becker wrote:
>>
>>> Could anybody explain me, in which I you'd want to overload opMul on classes?
>>
>> Well, one VERY well known example is for vector or matrix classes that
>> can be multiplied, but in a more complex way than just x * y.
>>
>> Lars Ivar Igesund
>
> Also the Int class (unlimited precision integer) in etc.bigint.bigint.

Shouldn't these all be structs, not classes, they're 'value' types, not 'reference' types aren't they?

I thought that was the point "Matthias Becker" was trying to make, that you'd only want to overload opMul on structs, not classes.

However as I have found structs have a few limitations that force you to use classes when you'd rather use a struct.

Regan.

-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
July 12, 2004
Daniel Horn wrote:
> the point is that then you have to jump through hoops to get templates that should work for both structs and classes working... I think there needs to be some work to add transparency to types... making them all act different, construct different and copy different makes it next-to-impossible to make a template class that works for all (case in point see my float1,2,3,4 structs that need to accept integers, classes (i.e. BigInt) or other floatX structs.

I see your point, but they use different syntax because they are different things.  Trying to hammer them into something that looks the same sounds dangerous at best.

 -- andy
July 12, 2004
well an int is no different than a struct
not sure why you can't just do


int x = int(5);
float y= float(2.5);

or at least some syntax to define opCall with an int...would this make the grammar anything not context-free for some reason

that way I could define opCall on the class to do the constructing,,, opcall on the float to do the constructing...and opcall on the struct--
even though one has value semantics and the other has reference semantics--at least that would nail the construction problem
Andy Friesen wrote:
> Daniel Horn wrote:
> 
>> the point is that then you have to jump through hoops to get templates that should work for both structs and classes working... I think there needs to be some work to add transparency to types... making them all act different, construct different and copy different makes it next-to-impossible to make a template class that works for all (case in point see my float1,2,3,4 structs that need to accept integers, classes (i.e. BigInt) or other floatX structs.
> 
> 
> I see your point, but they use different syntax because they are different things.  Trying to hammer them into something that looks the same sounds dangerous at best.
> 
>  -- andy
July 12, 2004
Daniel Horn wrote:
> well an int is no different than a struct
> not sure why you can't just do
> 
> int x = int(5);
> float y= float(2.5);

Right, I don't see anything wrong with this.  I was referring to using the same syntax for classes.

> that way I could define opCall on the class to do the constructing,,, opcall on the float to do the constructing...and opcall on the struct--
> even though one has value semantics and the other has reference semantics--at least that would nail the construction problem

I would use an allocator template here.  If the array demands a certain interface that isn't present, there needs to be a way to code a bridge.  Requiring a opCall(int) leaves inheritance as the only option, which is somewhat frail.

(templates can have default arguments, so it shouldn't be a burden on everybody else)

 -- andy