December 10, 2006
Tom S wrote:
> A static opCall won't handle the following case:
> 
> ----
> 
> void delegate() globalDG;
> 
> 
> struct Foo {
>     void func() {
>         printf("myVal = %d\n", myVal);
>     }
> 
>     static Foo opCall(int v) {
>         Foo res;
>         res.myVal = v;
>         globalDG = &res.func;
>         return res;
>     }
> 
>     int myVal;
> }
> 
> 
> void main() {
>     Foo f = Foo(5);
>     globalDG();  // prints garbage instead of '5'
> }
> 
> ----

Ok, you're right on that one. But I am going to argue on philosophical grounds that this kind of code is incorrect for a couple of reasons:

1) constructors should construct objects, not set state outside themselves.

2) trying to keep track of every struct created is going to put a hole below the waterline in some new capabilities planned for the future. The compiler needs to be able to willy-nilly create bit copies of structs for this to work. C++ has this problem in spades (just follow the skin-rending and hair-pulling going on with the "move constructor" issues). Allowing the compiler to be able to create bit copied temporaries without needing to call constructors is going to be worthwhile by enabling some pretty cool stuff.

I'm going to put forward the idea that this kind of thing should be done with classes, not structs.


> The Foo instance returned from static opCall is copied, thus the 'ctor hack' doesn't have real access to the object it's constructing, not to mention the overhead of copying the struct to another place on stack...

It's time to put the recurring efficiency argument to bed. Consider this D code:
-------------------
 struct S
 {
     static S opCall(int v)
     {
         S result;
         result.v = v;
         return result;
     }
     int v;
 }

 int test()
 {
    auto s = S(5);
    return s.v;
 }
------------compiles to----------
 _D4test1S6opCallFiZS4test1S     comdat
                 ret
 _D4test4testFZi comdat
                 mov     EAX,5
                 ret
---------------------------------
It doesn't get any better than that.


> Also,  new Foo(5)  isn't going to work without real ctors or more hacks.

That can be supported without any more work than supporting it with ctors.
December 10, 2006
Walter Bright wrote:
> More ABI changes, and implicit [] => * no longer allowed.
> 
> http://www.digitalmars.com/d/changelog.html
> 
> http://ftp.digitalmars.com/dmd.175.zip

I'm not sure if this is a bug or what, but to get derelict from not spitting out this error message...

derelict\opengl\glu.obj(glu)
 Error 42: Symbol Undefined _D8derelict6opengl3glu8GLUnurbs6__initZ
derelict\opengl\glu.obj(glu)
 Error 42: Symbol Undefined _D8derelict6opengl3glu10GLUquadric6__initZ
derelict\opengl\glu.obj(glu)
 Error 42: Symbol Undefined _D8derelict6opengl3glu13GLUtesselator6__initZ

In glu.d line 287-289 I had to change

struct GLUnurbs;
struct GLUquadric;
struct GLUtesselator;

to

struct GLUnurbs{}
struct GLUquadric{}
struct GLUtesselator{}

In order for the compiler to recognize the symbols.

Thanks for the release.
~ Clay
December 10, 2006
Walter, you forgot to change this line in the docs:

"The operators =, !, ., &&, ||, ?:, and a few others will likely never be
overloadable. "
http://www.digitalmars.com/d/operatoroverloading.html

: )

L.


December 10, 2006
<g>
December 10, 2006
== Quote from Walter Bright (newshound@digitalmars.com)'s article
> Jarrett Billingsley wrote:
> >> It turns out that static opCall() and this() are equivalent. C++ has some
> >> obscure rules to try to disambiguate them. I wished to avoid that problem,
> >> and since static opCall() is routinely in use, picked them.
> > For classes they're not.  Why should structs be any different?  And even if static opCalls are routinely in use, are they the best solution?
> I've found they work well.

Yes, but ctors would work even better:

  this(int a, int b) {
    _a = a;
    _b = b;
  }
  static Foo opCall(int a, int b) {
    Foo foo;
    foo._a = a;
    foo._b = b;
    return foo;
  }

Suggestion: disallow both opCall and ctor for the same struct and there should be no ambiguity issues.

> That's implicit casting from a struct. It'll probably wind up getting supported in one form or another.

That's great :)

It seems that some D issues suffer from "Black hole theory of languages":
"C++ is a Black Hole: if you try to design something that's not C++, but like C++,
you'll find that the gravitational forces on the design will suck it into the
Black Hole, and it will become C++"
December 10, 2006
Walter Bright wrote:

> Burton Radons wrote:
>> Here's the difference:
>> 
>>     struct S
>>     {
>>         this (int x)
>>         {
>>             w = calculate_something (x);
>>         }
>> 
>>         this (int x, int y)
>>         {
>>             this (x);
>>             z = calculate (y);
>>         }
>>     }
> 
> struct S
> {
>      static S opCall(int x)
>      {
> S result;
> result.w = calculate_something(x);
> return result;
>      }
> 
>      static S opCall(int x, int y)
>      {
> auto result = S(x);
> result.z = calculate(y);
> return result;
>      }
> }
> 
> It's 3 more lines of code. The two styles almost completely overlap, and since the latter is already in use, adding ctors just seems redundant.

Struct can have opCall, which is why they were used as a workaround for ctors. This was almost ok, but creating language support (through statement rewriting) for a workaround sounds a very bad thing to add prior to 1.0. This is certainly controversial enough, to think over for more than 2 weeks. I personally agree with those who want struct ctors.

-- 
Lars Ivar Igesund
blog at http://larsivi.net
DSource & #D: larsivi
December 10, 2006
did you recompile linked D libs?
December 10, 2006
Thank you, Walter.

D 1.0 is going to be THE BEST general purpose language ... :D
December 10, 2006
Walter Bright escribió:
> Jarrett Billingsley wrote:
>> What is the TRUE reason you don't want to give structs ctors?  I don't want to know why static opCalls are good, but why ctors are bad. 
> 
> Constructor:
> 
>     S(v);
> 
> static opCall:
> 
>     S(v)
> 
> What's the difference? I just don't see the point for adding constructors.

I don't understand: the current way to go (opCall) *is a workaround*. That means, it's frequently used by D programmers to simulate something that is missing in the language (at least in my case).

What about elegance (one of the most beloved properties of D)? Doesn't it account at all?

Regards,
--
Tom;
December 10, 2006
Frank Benoit (keinfarbton) wrote:
> did you recompile linked D libs?

Yes, I actually don't use any linked libs since D compiles so fast. I just let build pull in what it wants to.