www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - "D is so great"

reply Matthias Becker <Matthias_member pathlink.com> writes:
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;
}


Everytime I try to code anything in D I get such behavior that I don't expect
and often I don't find a workaround. But "D is so great". So are my ideas so
strange that nobody else wants to do the things I want to? Why does nobody else
say D is strange with a lot of unexpected behaviors?


BTW: Why structs don't have constructors? I get crazy about this!

Foo foo;
foo.x = bla;
foo.y = blub;
// start using foo
// *ARGH!!!*

It's so messy.



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. So you have to use an even more clumsy workaround:

template MulReturnType (T, U) {
T tValue;
U uValue;
alias typeof(tValue * uValue) ReturnType;
}

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


And this is needed only for one very simple line of ML!

OK, perhaps Andy just expected other programmers to be smart enough to write a
init-property for types that should be useable in istuations like this?



BTW, can somebody tell me for what reason you want to overload opMul for a
class? I expect to use op * only on things like numbers. But numbers are
valu-etypes not reference-types. A number is defined by its value. You can sotre
it a million times at different places, it's allways the same number if it has
the same value. This is totaly different to reference-types. E.g. a Car is
identifyed by its identity, not its value. if you have two cars, both are red
and both are build 1995 it doesn't mean that they are the same cars. Their
values isn't interesting, but their identity.
D is powerfull enough to express something like this: You can use class for
identity-defined-objects and struct for value-defined-objects. (OK, than you
once again have the problem that structs doen't have a c'tor!)

Could anybody explain me, in which I you'd want to overload opMul on classes?


The more I use D the less I like it. But it's defently me, as "D is so great!".
Jul 12 2004
next sibling parent Daniel Horn <hellcatv hotmail.com> writes:
I think you need to do .Baz!(T) recursive;
I complained about this when I was first on the board as well :-)
the . tells the compiler to resolve the symbol from the global scope

Matthias Becker wrote:
 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;
 }
 
 
 Everytime I try to code anything in D I get such behavior that I don't expect
 and often I don't find a workaround. But "D is so great". So are my ideas so
 strange that nobody else wants to do the things I want to? Why does nobody else
 say D is strange with a lot of unexpected behaviors?
 
 
 BTW: Why structs don't have constructors? I get crazy about this!
 
 Foo foo;
 foo.x = bla;
 foo.y = blub;
 // start using foo
 // *ARGH!!!*
 
 It's so messy.
 
 
 
 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. So you have to use an even more clumsy workaround:
 
 template MulReturnType (T, U) {
 T tValue;
 U uValue;
 alias typeof(tValue * uValue) ReturnType;
 }
 
 template mul (T, U) {
 MulReturnType!(T, U).ReturnType mul (T x, U y)
 {
 return x * y;
 }
 }
 
 
 And this is needed only for one very simple line of ML!
 
 OK, perhaps Andy just expected other programmers to be smart enough to write a
 init-property for types that should be useable in istuations like this?
 
 
 
 BTW, can somebody tell me for what reason you want to overload opMul for a
 class? I expect to use op * only on things like numbers. But numbers are
 valu-etypes not reference-types. A number is defined by its value. You can
sotre
 it a million times at different places, it's allways the same number if it has
 the same value. This is totaly different to reference-types. E.g. a Car is
 identifyed by its identity, not its value. if you have two cars, both are red
 and both are build 1995 it doesn't mean that they are the same cars. Their
 values isn't interesting, but their identity.
 D is powerfull enough to express something like this: You can use class for
 identity-defined-objects and struct for value-defined-objects. (OK, than you
 once again have the problem that structs doen't have a c'tor!)
 
 Could anybody explain me, in which I you'd want to overload opMul on classes?
 
 
 The more I use D the less I like it. But it's defently me, as "D is so great!".
 
 

Jul 12 2004
prev sibling next sibling parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
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
Jul 12 2004
parent reply Arcane Jill <Arcane_member pathlink.com> writes:
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. Arcane Jill
Jul 12 2004
parent reply Regan Heath <regan netwin.co.nz> writes:
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/
Jul 12 2004
parent reply Arcane Jill <Arcane_member pathlink.com> writes:
In article <opsa1oztn45a2sq9 digitalmars.com>, Regan Heath says...

 Could anybody explain me, in which I you'd want to overload opMul on 
 classes?



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

No. It is an absolute and unchangeable requirement that my Ints ***MUST*** have destructors, for reasons of security. Therefore they cannot be structs. They are immutable reference types. # ^^^^^^^^^ Jill
Jul 13 2004
parent reply Regan Heath <regan netwin.co.nz> writes:
On Tue, 13 Jul 2004 07:27:15 +0000 (UTC), Arcane Jill 
<Arcane_member pathlink.com> wrote:

 In article <opsa1oztn45a2sq9 digitalmars.com>, Regan Heath says...

 Could anybody explain me, in which I you'd want to overload opMul on
 classes?



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

No. It is an absolute and unchangeable requirement that my Ints ***MUST*** have destructors, for reasons of security. Therefore they cannot be structs. They are immutable reference types. # ^^^^^^^^^

The current implementation of them is sure. The concept however is a value type, just like a normal 'int'. The fact that you cannot write them as a value type, to me, suggests a deficiency in D. So back to the main point, which IMO was 'does opMul make sense for a refence type?' I think it makes sense for a value type, i.e. an int I'm not sure it makes sense for a reference type. Regan. -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 13 2004
next sibling parent Arcane Jill <Arcane_member pathlink.com> writes:
In article <opsa2nh3aa5a2sq9 digitalmars.com>, Regan Heath says...

The current implementation of them is sure. The concept however is a value 
type, just like a normal 'int'. The fact that you cannot write them as a 
value type, to me, suggests a deficiency in D.

It's a feature of D. I don't know if you could call it a deficiency. The "missing thing" (that C++ has and D doesn't) is a "thing" that has copy-by-value semantics, but also has a destructor. I'm sure Walter will be happy to explain how really HARD that is to do. You end up having to implement copy constructors, assignment operators and all sorts. D has it real easy right now - structs get bitwise-copied; classes get copied by reference. To end the "deficiency" you mentioned, D would have to get *MUCH* more compilicated. Even returning a value from a function could involve execution of a copy constructor, an assigment function, and a destructor (as it does in C++). In Walter's view that's way too much overcomplication, and so we should adjust our thinking to "the D way". I adjusted my thinking, and now Ints work just fine, thank you very much.
So back to the main point, which IMO was 'does opMul make sense for a 
refence type?'

I think it makes sense for a value type, i.e. an int
I'm not sure it makes sense for a reference type.

It makes sense in the D paradigm, which is that a struct is a lightweight aggregate, and a class is what you use if you want more powerful features than that. But in partial agreement with you, I would certainly argue that opMulAssign() # ^^^^^^ makes no sense where things are passed by reference. No probs with opMul() itself though. Arcane Jill
Jul 13 2004
prev sibling parent Ben Hinkle <bhinkle4 juno.com> writes:
Regan Heath wrote:

 On Tue, 13 Jul 2004 07:27:15 +0000 (UTC), Arcane Jill
 <Arcane_member pathlink.com> wrote:
 
 In article <opsa1oztn45a2sq9 digitalmars.com>, Regan Heath says...

 Could anybody explain me, in which I you'd want to overload opMul on
 classes?



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

No. It is an absolute and unchangeable requirement that my Ints ***MUST*** have destructors, for reasons of security. Therefore they cannot be structs. They are immutable reference types. # ^^^^^^^^^

The current implementation of them is sure. The concept however is a value type, just like a normal 'int'. The fact that you cannot write them as a value type, to me, suggests a deficiency in D. So back to the main point, which IMO was 'does opMul make sense for a refence type?' I think it makes sense for a value type, i.e. an int I'm not sure it makes sense for a reference type. Regan.

For another perspective on opMul and big-ints, see the wrapper I wrote for GMP's mpz type at http://home.comcast.net/~benhinkle/gmp-d/doc/classmpz.html It uses classes and overloads opMul to return a new value. In order to prevent the GC from getting swamped with all those objects it uses a recycling mechanism. Users can also get to the "low-level" C mpz datatype to just call the GMP C functions if they want to manage the memory allocations by hand. Performance of this wrapper is better (on complex expressions) than the C++ wrapper that ships with GMP since the C++ version has to constantly be creating and destroying temporaries. The code is available at http://home.comcast.net/~benhinkle/gmp-d/ -Ben
Jul 13 2004
prev sibling next sibling parent "Kris" <someidiot earthlink.dot.dot.dot.net> writes:
IMO, there are a number of areas where D blows chunks rather offensively.
And then there's a number places where flaccid hacks (such as alias) are
documented as the "right approach". To my mind, there's so much time spent
trying to include every latest fad into the language that there's not enough
left over to get some of the basics right.

That's not to say that D sucks overall; it doesn't. It's more an issue of
time versus functionality versus getting it right. I've personally avoided
templates specifically because I don't want immature compiler dependencies
in my code, but still I'm frustrated and seriously hindered by a lack of
basic functionality such as function-overloading that actually includes the
method signature in all situations. Imagine that!.

To alleviate some of the pressure, it would likely help if the language
development were much more open in terms of disclosure: what is being
addressed sooner rather than later has a significant perceptive impact.
However, such things take a reasonable amount of effort and I don't see
Walter selecting any lieutenants to help him out ...

- Kris


"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

 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;
 }


 Everytime I try to code anything in D I get such behavior that I don't

 and often I don't find a workaround. But "D is so great". So are my ideas

 strange that nobody else wants to do the things I want to? Why does nobody

 say D is strange with a lot of unexpected behaviors?


 BTW: Why structs don't have constructors? I get crazy about this!

 Foo foo;
 foo.x = bla;
 foo.y = blub;
 // start using foo
 // *ARGH!!!*

 It's so messy.



 Even experienced programmers like Andy F. are fooled by the language. We

 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

 don't have an init-property. So you have to use an even more clumsy

 template MulReturnType (T, U) {
 T tValue;
 U uValue;
 alias typeof(tValue * uValue) ReturnType;
 }

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


 And this is needed only for one very simple line of ML!

 OK, perhaps Andy just expected other programmers to be smart enough to

 init-property for types that should be useable in istuations like this?



 BTW, can somebody tell me for what reason you want to overload opMul for a
 class? I expect to use op * only on things like numbers. But numbers are
 valu-etypes not reference-types. A number is defined by its value. You can

 it a million times at different places, it's allways the same number if it

 the same value. This is totaly different to reference-types. E.g. a Car is
 identifyed by its identity, not its value. if you have two cars, both are

 and both are build 1995 it doesn't mean that they are the same cars. Their
 values isn't interesting, but their identity.
 D is powerfull enough to express something like this: You can use class

 identity-defined-objects and struct for value-defined-objects. (OK, than

 once again have the problem that structs doen't have a c'tor!)

 Could anybody explain me, in which I you'd want to overload opMul on

 The more I use D the less I like it. But it's defently me, as "D is so


Jul 12 2004
prev sibling next sibling parent reply Mike Parker <aldacron71 yahoo.com> writes:
Matthias Becker wrote:

 
 BTW: Why structs don't have constructors? I get crazy about this!
 
 Foo foo;
 foo.x = bla;
 foo.y = blub;
 // start using foo
 // *ARGH!!!*
 
 It's so messy.

struct Foo { int x; static Foo opCall(int i) { Foo f; f.x = i; return f; } } Foo foo = Foo(5); While D has many similarities to other languages, D is D. There are quite a few small things that will bite you if you are thinking in C++ (or Java or whatever). Things won't always work as you expect them to, or you'll find there's a different way of doing something. It's when you've learnt the nuances and begun to 'think in D' that you realize how great D is ;) Spend some time reviewing the tutorials at dsource.org and perhaps the Wiki. In addition to covering common pitfalls and mistakes, they also have tidbits which fill in gaps in the documentation.
Jul 12 2004
next sibling parent Matthias Becker <Matthias_member pathlink.com> writes:
struct Foo
{
    int x;
    static Foo opCall(int i)
    {
        Foo f;
        f.x = i;
        return f;
    }
}

Foo foo = Foo(5);

D'oh. It's so obvious. I should have thougt about that.
Jul 12 2004
prev sibling parent reply Arcane Jill <Arcane_member pathlink.com> writes:
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. Arcane Jill
Jul 12 2004
next sibling parent reply "C. Sauls" <ibisbasenji yahoo.com> writes:
Arcane Jill wrote:
 I mean - I've never seen static
 opCall used for any purpose OTHER than emulating constructors.

In my quietly-under-development Neo server project, the DBObject class defines an opIndex for accessing its .properties and an opCall for accessing its .verbs. Observe... class DBObject { public: this(int _dbref) { dbref = _dbref; } // . . . DBProperty opIndex(int idx) { if (idx >= properties.length) return null; return properties[properties.keys[idx]]; } DBProperty opIndex(char[] name) { if (name in properties) return properties[name]; return null; } DBVerb opCall(int idx) { if (idx >= verbs.length) return null; return verbs[idx]; } DBVerb opCall(char[] name) { foreach (DBVerb v; verbs) { if (v.matchName(name)) // because verb names are patterns return v; } return null; } } So there you go... if the code wants to access the ".(name)" property of an object in the database, it just uses 'obj["name"]'. If it wants to get an assumed verb, it uses something like 'db[0]("do_login_command")' and voila. The opCall overload has its uses besides emulating constructors. And frankly, since we have the {...} literal syntax for structs, I don't see much need for struct constructors. -Chris S. -Invironz
Jul 12 2004
parent reply Arcane Jill <Arcane_member pathlink.com> writes:
In article <ccu6cn$1uu9$1 digitaldaemon.com>, C. Sauls says...

     DBVerb opCall(int idx) {

That's an opCall, not a static opCall. I can think of squillions of uses for opCall. But the only use I can think of for /static/ opCall is emulating constructors. Jill
Jul 12 2004
parent "C. Sauls" <ibisbasenji yahoo.com> writes:
Arcane Jill wrote:
 In article <ccu6cn$1uu9$1 digitaldaemon.com>, C. Sauls says...
    DBVerb opCall(int idx) {

That's an opCall, not a static opCall. I can think of squillions of uses for opCall. But the only use I can think of for /static/ opCall is emulating constructors.

Its amazing what a difference one word can make. Point taken. But still, there's no reason to disallow a static opCall, and another recently reply has me thinking of it as a useful thing for singletons now. Its a thing to ponder. And I recently got informed that struct literals don't work for non-static structs, which changes my view a bit as well. I say, make the literals work for non-statics, and then the need for struct constructors will likely diminish. -Chris S. -Invironz
Jul 12 2004
prev sibling next sibling parent Hauke Duden <H.NS.Duden gmx.net> writes:
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. Arcane Jill

I mostly agree with AJ here. The absence of struct constructors is an artificial and totally unnecessary restriction. And the argument that people would expect to have destructors as well is flawed, as has been shown in the numerous discussions of this topic. Also, recent postings here show that people WANT struct constructors and will resolve to hacks if they are not available. However, I don't think the static opCall should be removed just yet. I'm not sure either if it is truly useful, but nothing like this is available in similar languages (C++, C#, Java), so I think it might take a while until its usefulness shows. Besides, the non-static opCall HAS been used for string formatting and stream I/O. And I guess the static version could find similar uses with singleton classes. Hauke
Jul 12 2004
prev sibling next sibling parent reply Daniel Horn <hellcatv hotmail.com> writes:
a good case for this would be when you make a template class that must 
construct it's template argument but does not *know* if that argument is 
a struct or  a class

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. Arcane Jill

Jul 12 2004
parent "Bent Rasmussen" <exo bent-rasmussen.info> writes:
"Daniel Horn" <hellcatv hotmail.com> wrote in message
news:ccubqd$2823$1 digitaldaemon.com...
 a good case for this would be when you make a template class that must
 construct it's template argument but does not *know* if that argument is
 a struct or  a class

But then you might make a static opCall for both. That doesn't appeal to me though. The optional "new" might be nice, at least for structs.
Jul 12 2004
prev sibling next sibling parent reply =?ISO-8859-1?Q?Sigbj=F8rn_Lund_Olsen?= <sigbjorn lundolsen.net> writes:
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".

Wroar. I just realized, static opCall is way better than a constructor since it allows for the construction of the most appropriate subclass in a class hierarchy. Neat. Cheers, Sigbjørn Lund Olsen
Jul 12 2004
parent "Bent Rasmussen" <exo bent-rasmussen.info> writes:
 Wroar. I just realized, static opCall is way better than a constructor
 since it allows for the construction of the most appropriate subclass in
 a class hierarchy. Neat.

No biggie, you can do that with any static method just as well, i.e. a named constructor.
 Cheers,
 Sigbjørn Lund Olsen

Jul 12 2004
prev sibling next sibling parent reply Charlie <Charlie_member pathlink.com> writes:
I've never seen static
opCall used for any purpose OTHER than emulating constructors

Ive used for functors before.
even if only for syntactic consistency.

Consistent to what ? C++ ? In article <cctrk2$1e1t$1 digitaldaemon.com>, Arcane Jill says...
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. Arcane Jill

Jul 12 2004
parent Arcane Jill <Arcane_member pathlink.com> writes:
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
Jul 12 2004
prev sibling next sibling parent reply Andy Friesen <andy ikagames.com> writes:
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
Jul 12 2004
parent reply Daniel Horn <hellcatv hotmail.com> writes:
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

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.
Jul 12 2004
next sibling parent reply Andy Friesen <andy ikagames.com> writes:
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
Jul 12 2004
parent reply Daniel Horn <hellcatv hotmail.com> writes:
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

Jul 12 2004
parent reply Andy Friesen <andy ikagames.com> writes:
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
Jul 12 2004
parent Arcane Jill <Arcane_member pathlink.com> writes:
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);

In article <ccv6te$g7l$1 digitaldaemon.com>, Andy Friesen says...
  Requiring a opCall(int) leaves inheritance as the only option, which 
is somewhat frail.

Of course, you mean /static/ int.opCall() here. Otherwise the syntax would end up as: # int x = 5(5); "static" may be just one little word, but things get awfully confusing when people ignore it or imagine it to be meaningless. Jill
Jul 13 2004
prev sibling parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
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 agree that it would beegood for structs and classes to have the same semantics. However, I thikn that perhaps mucking around with 'new' is the wrong way to solve it. I've thought, right from the very beginning, that classes should use explicit pointer syntax. That is, a class refernce should be declared as a pointer, just like a pointer to a struct. Likewise, it should be possible to 'new' a struct. So, in my opinion, you should write this code: MyClass *ref; // this should be a class refernce MyStruct *ptr; // this is a struct pointer MyClass val; // this would be a syntax error Then, you could write your templates like this: T *ref = new T(foo,bar,baz); Assuming that structs had constructors, and that new was possible on structs, this would work just fine with both structs and classes.
Jul 12 2004
parent Daniel Horn <hellcatv hotmail.com> writes:
the point of structs is to be able to remain on the stack
:-)
otherwise I'd just hack up a class :-)
and that doesn't solve the int problem, does it?

int * i = new int (1); isn't valid

Russ Lewis 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 agree that it would beegood for structs and classes to have the same semantics. However, I thikn that perhaps mucking around with 'new' is the wrong way to solve it. I've thought, right from the very beginning, that classes should use explicit pointer syntax. That is, a class refernce should be declared as a pointer, just like a pointer to a struct. Likewise, it should be possible to 'new' a struct. So, in my opinion, you should write this code: MyClass *ref; // this should be a class refernce MyStruct *ptr; // this is a struct pointer MyClass val; // this would be a syntax error Then, you could write your templates like this: T *ref = new T(foo,bar,baz); Assuming that structs had constructors, and that new was possible on structs, this would work just fine with both structs and classes.

Jul 12 2004
prev sibling next sibling parent reply Regan Heath <regan netwin.co.nz> writes:
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/
Jul 12 2004
next sibling parent Regan Heath <regan netwin.co.nz> writes:
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/
Jul 12 2004
prev sibling parent reply Arcane Jill <Arcane_member pathlink.com> writes:
In article <opsa1n9i1k5a2sq9 digitalmars.com>, Regan Heath says...

 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.

Aaaaargh!! Well, I'll bet that not even you have done this in C++. I certainly haven't: # class A # { # static T operator()(parameters); # //^^^^^^// # } Do correct me if I'm wrong. What is it with people not seeing what I wrote. Was the word "static" invisible or something? For what it's worth, I actually think that *STATIC* opEVERYTHING should be deprecated. Currently, we can override *static* opAdd(), *static* opMul(), and so on, allowing us to write truly mad expressions like: # // A and B are classes or structs, not necessarily related: # # dchar c = A + 0.1; // dchar c = /*static*/ A.opAdd(0.1); # A a = B * new A(); // A a = /*static*/ B.opMul(new A()); This is utterly pointless. And before anyone says "we might think of use for it one day", yes, we might, but there is nothing that the above achieves that can't be equally well achieved with a straightforward named static function. But it gets worse. static opCall is currently used to simulate constructors. But the language permits you to define static A.opCall() to return a value of /any/ type, not just an A. It could return a double, for example. So if you EXPECT it to act like a constructor, you might get surprised one day. What's more, if you initialize a struct with something like: # A a = A(parameters); then what actually happens is this (1) the struct "a" is constructed on the stack; (2) all of a's member variables are initialized to their .init values; (3) _static_ A.opCall() is evaluated, which constructs ANOTHER object of type A on the stack, also with all of its member variables initialized to their .init values; (4) during execution of static A.opCall(), the member variables of the second A are overwritten with new values derived from the function parameters; (5) on return from static opCall(), the second A is bitwise-copied onto a; and finally (6) the second copy is discarded. I would hope that having constructors for structs would eliminate all this needless copying. Jill
Jul 13 2004
next sibling parent reply Derek Parnell <derek psych.ward> writes:
On Tue, 13 Jul 2004 07:22:05 +0000 (UTC), Arcane Jill wrote:

 In article <opsa1n9i1k5a2sq9 digitalmars.com>, Regan Heath says...
 
 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.

Aaaaargh!! Well, I'll bet that not even you have done this in C++. I certainly haven't: # class A # { # static T operator()(parameters); # //^^^^^^// # } Do correct me if I'm wrong. What is it with people not seeing what I wrote. Was the word "static" invisible or something? For what it's worth, I actually think that *STATIC* opEVERYTHING should be deprecated. Currently, we can override *static* opAdd(), *static* opMul(), and so on, allowing us to write truly mad expressions like: # // A and B are classes or structs, not necessarily related: # # dchar c = A + 0.1; // dchar c = /*static*/ A.opAdd(0.1); # A a = B * new A(); // A a = /*static*/ B.opMul(new A()); This is utterly pointless. And before anyone says "we might think of use for it one day", yes, we might, but there is nothing that the above achieves that can't be equally well achieved with a straightforward named static function. But it gets worse. static opCall is currently used to simulate constructors. But the language permits you to define static A.opCall() to return a value of /any/ type, not just an A. It could return a double, for example. So if you EXPECT it to act like a constructor, you might get surprised one day. What's more, if you initialize a struct with something like: # A a = A(parameters); then what actually happens is this (1) the struct "a" is constructed on the stack; (2) all of a's member variables are initialized to their .init values; (3) _static_ A.opCall() is evaluated, which constructs ANOTHER object of type A on the stack, also with all of its member variables initialized to their .init values; (4) during execution of static A.opCall(), the member variables of the second A are overwritten with new values derived from the function parameters; (5) on return from static opCall(), the second A is bitwise-copied onto a; and finally (6) the second copy is discarded. I would hope that having constructors for structs would eliminate all this needless copying. Jill

I'm wondering if I've been doing something really stupid then. I have a this sort of thing happening... struct Foo { . . . whatever . . . void opCall(size_t x) { .... } void opCall(double x) { .... } void opCall(char[] x) { .... } void opCall(char x) { .... } } void main() { Foo a; Foo b; Foo c; Foo d; a(3.4); // Initialize this one to 3.4 b(17); // Initialize this one to 17 c("happy me"); // Initialize this one to "happy me" d('?'); // Initialize this one to '?' } Actually, I didn't like the look of this in code, so I overloaded "<<=" so I could also write ... a <<= 3.4; b <<= 17; c <<= "happy me"; d <<= '?'; to set the value of these structures. I know to the mathematical purists this is 'evil'. Presumably because they can only see "<<=" as shifting bits to the left and assigning the result to itself. But I see "<<=" as a way of saying 'copy the value on the right-side to the thing that's on the left-side'. Gee, much like I see "=" really. Sure wish I could overload "=", 'cos that would make a lot of sense to me. I want to set the value of these structures but I don't want to deal with the internal repesentation all the time. That's why we have method's, right? Am I doing things the kosher 'D' way or am I way off base? -- Derek Melbourne, Australia 13/Jul/04 6:02:33 PM
Jul 13 2004
next sibling parent reply "Matthew Wilson" <dmd synesis.com.au> writes:
"Derek Parnell" <derek psych.ward> wrote in message
news:cd05k8$25b0$1 digitaldaemon.com...
 On Tue, 13 Jul 2004 07:22:05 +0000 (UTC), Arcane Jill wrote:

 In article <opsa1n9i1k5a2sq9 digitalmars.com>, Regan Heath says...

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

I don't agree. opCall has more uses than simply simulating a



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.

Aaaaargh!! Well, I'll bet that not even you have done this in C++. I certainly


 #    class A
 #    {
 #        static T operator()(parameters);
 #      //^^^^^^//
 #    }

 Do correct me if I'm wrong.

 What is it with people not seeing what I wrote. Was the word "static"


 or something?

 For what it's worth, I actually think that *STATIC* opEVERYTHING should


 deprecated. Currently, we can override *static* opAdd(), *static*


 so on, allowing us to write truly mad expressions like:

 #    // A and B are classes or structs, not necessarily related:
 #
 #    dchar c = A + 0.1;  // dchar c = /*static*/ A.opAdd(0.1);
 #    A a = B * new A();  // A a = /*static*/ B.opMul(new A());

 This is utterly pointless. And before anyone says "we might think of use


 one day", yes, we might, but there is nothing that the above achieves


 be equally well achieved with a straightforward named static function.

 But it gets worse. static opCall is currently used to simulate


 the language permits you to define static A.opCall() to return a value


 type, not just an A. It could return a double, for example. So if you


 to act like a constructor, you might get surprised one day.

 What's more, if you initialize a struct with something like:

 #    A a = A(parameters);

 then what actually happens is this (1) the struct "a" is constructed on


 stack; (2) all of a's member variables are initialized to their .init


 (3) _static_ A.opCall() is evaluated, which constructs ANOTHER object of


 on the stack, also with all of its member variables initialized to their


 values; (4) during execution of static A.opCall(), the member variables


 second A are overwritten with new values derived from the function


 (5) on return from static opCall(), the second A is bitwise-copied onto


 finally (6) the second copy is discarded.

 I would hope that having constructors for structs would eliminate all


 needless copying.

 Jill

I'm wondering if I've been doing something really stupid then. I have a this sort of thing happening... struct Foo { . . . whatever . . . void opCall(size_t x) { .... } void opCall(double x) { .... } void opCall(char[] x) { .... } void opCall(char x) { .... } } void main() { Foo a; Foo b; Foo c; Foo d; a(3.4); // Initialize this one to 3.4 b(17); // Initialize this one to 17 c("happy me"); // Initialize this one to "happy me" d('?'); // Initialize this one to '?' } Actually, I didn't like the look of this in code, so I overloaded "<<=" so I could also write ... a <<= 3.4; b <<= 17; c <<= "happy me"; d <<= '?'; to set the value of these structures. I know to the mathematical purists this is 'evil'. Presumably because they can only see "<<=" as shifting

 to the left and assigning the result to itself. But I see "<<=" as a way

 saying 'copy the value on the right-side to the thing that's on the
 left-side'.  Gee, much like I see "=" really. Sure wish I could overload
 "=", 'cos that would make a lot of sense to me.

 I want to set the value of these structures but I don't want to deal with
 the internal repesentation all the time. That's why we have method's,
 right?


 Am I doing things the kosher 'D' way or am I way off base?

It seems like one of these things that is convenient to its author (at the time of writing - you'll be confused by it in six months' time) but is likely to lead to a host of inconsistent behaviours amongst the practitioners. So I'd say "way off base", I'm afraid ;/
Jul 13 2004
parent reply Derek Parnell <derek psych.ward> writes:
On Tue, 13 Jul 2004 18:21:23 +1000, Matthew Wilson wrote:


[snip]

 But I see "<<=" as a way of
 saying 'copy the value on the right-side to the thing that's on the
 left-side'.  Gee, much like I see "=" really. Sure wish I could overload
 "=", 'cos that would make a lot of sense to me.

 I want to set the value of these structures but I don't want to deal with
 the internal repesentation all the time. That's why we have method's,
 right?


 Am I doing things the kosher 'D' way or am I way off base?

It seems like one of these things that is convenient to its author (at the time of writing - you'll be confused by it in six months' time) but is likely to lead to a host of inconsistent behaviours amongst the practitioners. So I'd say "way off base", I'm afraid

Thanks mate. I sorta suspected so. Now if only I could overload '=' so my INTENTIONS to the code reader were a bit more obvious. So what's a better way? An explicit function call to assign a value? eg. a.opAssign("hello") It sort of seems stupid to resort to doing this when the language already has an operator to do it... -- Derek Melbourne, Australia 13/Jul/04 7:01:45 PM
Jul 13 2004
next sibling parent reply Arcane Jill <Arcane_member pathlink.com> writes:
In article <cd08ld$2atb$1 digitaldaemon.com>, Derek Parnell says...

So what's a better way? An explicit function call to assign a value?

eg.

   a.opAssign("hello")

It sort of seems stupid to resort to doing this when the language already
has an operator to do it...

The C++ standard template library uses a function called assign(). Of course, in C++, you can overload operator=(), but sometimes even this isn't enough, because sometimes you want more than one parameter on the right hand side of the equals (if you see what I mean). So in C++ you can end up with stuff like: # myString.assign(ptr, length); This is pretty clear and unambiguous. For D, opAssign() would probably be a better name, even if it /isn't/ overloading =. Jill
Jul 13 2004
parent Derek <derek psyc.ward> writes:
On Tue, 13 Jul 2004 11:21:40 +0000 (UTC), Arcane Jill wrote:

 In article <cd08ld$2atb$1 digitaldaemon.com>, Derek Parnell says...
 
So what's a better way? An explicit function call to assign a value?

eg.

   a.opAssign("hello")

It sort of seems stupid to resort to doing this when the language already
has an operator to do it...

The C++ standard template library uses a function called assign(). Of course, in C++, you can overload operator=(), but sometimes even this isn't enough, because sometimes you want more than one parameter on the right hand side of the equals (if you see what I mean). So in C++ you can end up with stuff like: # myString.assign(ptr, length); This is pretty clear and unambiguous. For D, opAssign() would probably be a better name, even if it /isn't/ overloading =.

Yeah, I'm already using opSliceAssign(int x, int j, T x) in anticipation of of overloading lvalue slices... a[i..j] = x; where 'a' is NOT an array but a class or struct. -- Derek Melbourne, Australia
Jul 13 2004
prev sibling next sibling parent "Bent Rasmussen" <exo bent-rasmussen.info> writes:
 So what's a better way? An explicit function call to assign a value?

 eg.

    a.opAssign("hello")

 It sort of seems stupid to resort to doing this when the language already
 has an operator to do it...

This might do as a temporary solution a.Is = "hello"; The intent is crystal clear and the expression is short.
Jul 13 2004
prev sibling parent reply Daniel Horn <hellcatv hotmail.com> writes:
Derek Parnell wrote:
 On Tue, 13 Jul 2004 18:21:23 +1000, Matthew Wilson wrote:
 
 
 [snip]
 
 
But I see "<<=" as a way of
saying 'copy the value on the right-side to the thing that's on the
left-side'.  Gee, much like I see "=" really. Sure wish I could overload
"=", 'cos that would make a lot of sense to me.

I want to set the value of these structures but I don't want to deal with
the internal repesentation all the time. That's why we have method's,
right?


Am I doing things the kosher 'D' way or am I way off base?

It seems like one of these things that is convenient to its author (at the time of writing - you'll be confused by it in six months' time) but is likely to lead to a host of inconsistent behaviours amongst the practitioners. So I'd say "way off base", I'm afraid

Thanks mate. I sorta suspected so. Now if only I could overload '=' so my INTENTIONS to the code reader were a bit more obvious. So what's a better way? An explicit function call to assign a value? eg. a.opAssign("hello") It sort of seems stupid to resort to doing this when the language already has an operator to do it...

or else adding some sort of new operator like <- for "deep copy"
Jul 13 2004
parent Derek Parnell <derek psych.ward> writes:
On Tue, 13 Jul 2004 10:16:36 -0700, Daniel Horn wrote:

 Derek Parnell wrote:
 On Tue, 13 Jul 2004 18:21:23 +1000, Matthew Wilson wrote:
 
 [snip]
 
But I see "<<=" as a way of
saying 'copy the value on the right-side to the thing that's on the
left-side'.  Gee, much like I see "=" really. Sure wish I could overload
"=", 'cos that would make a lot of sense to me.

I want to set the value of these structures but I don't want to deal with
the internal repesentation all the time. That's why we have method's,
right?


Am I doing things the kosher 'D' way or am I way off base?

It seems like one of these things that is convenient to its author (at the time of writing - you'll be confused by it in six months' time) but is likely to lead to a host of inconsistent behaviours amongst the practitioners. So I'd say "way off base", I'm afraid

Thanks mate. I sorta suspected so. Now if only I could overload '=' so my INTENTIONS to the code reader were a bit more obvious. So what's a better way? An explicit function call to assign a value? eg. a.opAssign("hello") It sort of seems stupid to resort to doing this when the language already has an operator to do it...

or else adding some sort of new operator like <- for "deep copy"

Hmmmmm... the 'deep copy' operator sounds like I decent idea. -- Derek Melbourne, Australia 14/Jul/04 9:28:22 AM
Jul 13 2004
prev sibling parent Arcane Jill <Arcane_member pathlink.com> writes:
In article <cd05k8$25b0$1 digitaldaemon.com>, Derek Parnell says...

   a(3.4);  // Initialize this one to 3.4
   b(17);  // Initialize this one to 17 
   c("happy me");  // Initialize this one to "happy me"
   d('?'); // Initialize this one to '?'

Actually, I didn't like the look of this in code, so I overloaded "<<=" so
I could also write ...

  a <<= 3.4;
  b <<= 17;
  c <<= "happy me";
  d <<= '?';

Am I doing things the kosher 'D' way or am I way off base?

Tee hee. :-) Well, there _IS_ no kosher D way, because opAssign() doesn't exist. Your solutions are kinda neat, and definitely fun.
I know to the mathematical purists
this is 'evil'. Presumably because they can only see "<<=" as shifting bits
to the left and assigning the result to itself.

Ah now, to a REAL mathematical purist, << and >> are relations (they return a boolean result). a << b means "a is much less than b", while a >> b means "a is much greater than b". The use of << and >> to mean bitshifting did not come out of mathematics. C invented that one. Jill
Jul 13 2004
prev sibling next sibling parent "Ivan Senji" <ivan.senji public.srce.hr> writes:
Arcane Jill" <Arcane_member pathlink.com> wrote in message
news:cd02it$1vc4$1 digitaldaemon.com...
 In article <opsa1n9i1k5a2sq9 digitalmars.com>, Regan Heath says...

 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.

Aaaaargh!! Well, I'll bet that not even you have done this in C++. I certainly

 #    class A
 #    {
 #        static T operator()(parameters);
 #      //^^^^^^//
 #    }

 Do correct me if I'm wrong.

 What is it with people not seeing what I wrote. Was the word "static"

 or something?

 For what it's worth, I actually think that *STATIC* opEVERYTHING should be

I must disagree, i think static operators will prove to be usefull!
 deprecated. Currently, we can override *static* opAdd(), *static* opMul(),

 so on, allowing us to write truly mad expressions like:

 #    // A and B are classes or structs, not necessarily related:
 #
 #    dchar c = A + 0.1;  // dchar c = /*static*/ A.opAdd(0.1);
 #    A a = B * new A();  // A a = /*static*/ B.opMul(new A());

 This is utterly pointless. And before anyone says "we might think of use

 one day", yes, we might, but there is nothing that the above achieves that

 be equally well achieved with a straightforward named static function.

 But it gets worse. static opCall is currently used to simulate

 the language permits you to define static A.opCall() to return a value of

 type, not just an A. It could return a double, for example. So if you

 to act like a constructor, you might get surprised one day.

 What's more, if you initialize a struct with something like:

 #    A a = A(parameters);

 then what actually happens is this (1) the struct "a" is constructed on

 stack; (2) all of a's member variables are initialized to their .init

 (3) _static_ A.opCall() is evaluated, which constructs ANOTHER object of

 on the stack, also with all of its member variables initialized to their

 values; (4) during execution of static A.opCall(), the member variables of

 second A are overwritten with new values derived from the function

 (5) on return from static opCall(), the second A is bitwise-copied onto a;

 finally (6) the second copy is discarded.

 I would hope that having constructors for structs would eliminate all this
 needless copying.

With this i agree. Constructors for structs would be great!
 Jill

Jul 13 2004
prev sibling parent reply Regan Heath <regan netwin.co.nz> writes:
I think you'll find if you read *my* reply to *my* post to which you are 
replying below you'll find that I rescinded my comment as I realised I had 
indeed missed the word 'static'.

You make a good point about what goes on when someone uses a static opCall 
to emulate a constructor. I agree structs should have constructors. If 
they have constructors I think they should also have destructors. Thus 
allowing you to write your BigInt stuff with structs, which IMO they 
should be, as they're value types, not reference types.

I also think structs should have inheritance. NOT in the same way as 
classes, NOT with any virtual function overhead, simply inherit methods 
and members. Sure, you can do this with mixins, but IMO they are messy, 
whereas struct inheritance could be quite clean.

My 2c yet again.

Regan

On Tue, 13 Jul 2004 07:22:05 +0000 (UTC), Arcane Jill 
<Arcane_member pathlink.com> wrote:

 In article <opsa1n9i1k5a2sq9 digitalmars.com>, Regan Heath says...

 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.

Aaaaargh!! Well, I'll bet that not even you have done this in C++. I certainly haven't: # class A # { # static T operator()(parameters); # //^^^^^^// # } Do correct me if I'm wrong. What is it with people not seeing what I wrote. Was the word "static" invisible or something? For what it's worth, I actually think that *STATIC* opEVERYTHING should be deprecated. Currently, we can override *static* opAdd(), *static* opMul(), and so on, allowing us to write truly mad expressions like: # // A and B are classes or structs, not necessarily related: # # dchar c = A + 0.1; // dchar c = /*static*/ A.opAdd(0.1); # A a = B * new A(); // A a = /*static*/ B.opMul(new A()); This is utterly pointless. And before anyone says "we might think of use for it one day", yes, we might, but there is nothing that the above achieves that can't be equally well achieved with a straightforward named static function. But it gets worse. static opCall is currently used to simulate constructors. But the language permits you to define static A.opCall() to return a value of /any/ type, not just an A. It could return a double, for example. So if you EXPECT it to act like a constructor, you might get surprised one day. What's more, if you initialize a struct with something like: # A a = A(parameters); then what actually happens is this (1) the struct "a" is constructed on the stack; (2) all of a's member variables are initialized to their .init values; (3) _static_ A.opCall() is evaluated, which constructs ANOTHER object of type A on the stack, also with all of its member variables initialized to their .init values; (4) during execution of static A.opCall(), the member variables of the second A are overwritten with new values derived from the function parameters; (5) on return from static opCall(), the second A is bitwise-copied onto a; and finally (6) the second copy is discarded. I would hope that having constructors for structs would eliminate all this needless copying. Jill

-- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 13 2004
parent reply Arcane Jill <Arcane_member pathlink.com> writes:
In article <opsa2m9oo15a2sq9 digitalmars.com>, Regan Heath says...
I think you'll find if you read *my* reply to *my* post to which you are 
replying below you'll find that I rescinded my comment as I realised I had 
indeed missed the word 'static'.

Yeah I know. Whoops. <embarrassed>. Sometimes I'm just too impatient to read the whole list before posting anything.
You make a good point about what goes on when someone uses a static opCall 
to emulate a constructor. I agree structs should have constructors. If 
they have constructors I think they should also have destructors.

Er... WHOA. They can't. That's just not possible in the D framework. And if you keep suggesting this all it means is that Walter will never give us CONstructors, which is a much more important priority.
Thus allowing you to write your BigInt stuff with structs,

The class is called Int.
which IMO they should be, as they're value types, not reference types.

They are immutable reference types, and I am perfectly happy with this. If you have an Int with a million digits, why on Earth would you want to copy that around by VALUE? (Ints can get indefinitely large. It's part of their definition). I have no complaints about the struct/class distinction, and I'm happy for Int to be a class. Everything works fine, right now (minor bugs aside). I don't wish to change it to a struct, thank you very much.
I also think structs should have inheritance. NOT in the same way as 
classes, NOT with any virtual function overhead, simply inherit methods 
and members. Sure, you can do this with mixins, but IMO they are messy, 
whereas struct inheritance could be quite clean.

You could always just name the first member variable "sooper". :-) Have you considered that instead of wishing all this extra functionality on a struct, you could just use a class? You seem to be locked into this "value semantics therefore MUST be a struct" mentality, but that's not the only solution. D structs are simply lightweight aggregates. Treat them as such, and use classes if you want more. It's really only the intialization of structs that (most) people are complaining about. Arcane Jill
Jul 13 2004
parent reply Regan Heath <regan netwin.co.nz> writes:
On Tue, 13 Jul 2004 11:45:15 +0000 (UTC), Arcane Jill 
<Arcane_member pathlink.com> wrote:

 In article <opsa2m9oo15a2sq9 digitalmars.com>, Regan Heath says...
 I think you'll find if you read *my* reply to *my* post to which you are
 replying below you'll find that I rescinded my comment as I realised I 
 had
 indeed missed the word 'static'.

Yeah I know. Whoops. <embarrassed>. Sometimes I'm just too impatient to read the whole list before posting anything.

I know the feeling.
 You make a good point about what goes on when someone uses a static 
 opCall
 to emulate a constructor. I agree structs should have constructors. If
 they have constructors I think they should also have destructors.

Er... WHOA. They can't. That's just not possible in the D framework.

I think I need a tutorial on how they work then, cos I can't see the problem.
 And if you
 keep suggesting this all it means is that Walter will never give us
 CONstructors, which is a much more important priority.

My impression is that Walter considers each suggestion on it's own merits, he won't throw out one idea simply because it's suggested along with another, at least that is how he seems to me.
 Thus allowing you to write your BigInt stuff with structs,

The class is called Int.

I was not attempting to refer to the class name, I was attempting to refer to the idea.
 which IMO they should be, as they're value types, not reference types.

They are immutable reference types, and I am perfectly happy with this. If you have an Int with a million digits, why on Earth would you want to copy that around by VALUE? (Ints can get indefinitely large. It's part of their definition).

That makes sense.
 I have no complaints about the struct/class distinction, and I'm happy 
 for Int
 to be a class. Everything works fine, right now (minor bugs aside). I 
 don't wish
 to change it to a struct, thank you very much.



 I also think structs should have inheritance. NOT in the same way as
 classes, NOT with any virtual function overhead, simply inherit methods
 and members. Sure, you can do this with mixins, but IMO they are messy,
 whereas struct inheritance could be quite clean.

You could always just name the first member variable "sooper". :-)

Walter suggested something like that. You end up with something like... struct A { void foo() { *this = A.init; } } struct B { alias A.foo foo; int bar = 5; A a; } struct C { alias B.foo foo; alias B.bar bar; B b; } void main() { C c; c.bar = 1; c.foo(); printf("%d\n",c.bar); } basically an alias for every member in every struct you derive from. With complex structs this gets out of hand. When you run the above code the line *this = A.init sets the int bar to 0, I would have thought it would have left it un-changed.
 Have you considered that instead of wishing all this extra functionality 
 on a
 struct, you could just use a class?

Yeah.. but structs have this wonderful ability to allow you to go.. struct A { void foo() { *this = A.init; } } class B { int a = 5; int b = 6; void foo() { *this = B.init; //error: can only * a pointer, not a 'B' this = B.init; //appears to do nothing } } void main() { B b = new B(); b.a = 1; b.b = 2; b.foo(); printf("%d %d\n",b.a,b.b); } I found this when writing the Hashing algorithms, I wanted to use structs for the above and other reasons. The current code in deimos uses structs, it's not perfect, it needs a few tweaks. After writing it, I wrote a few of them as classes, I am un-decided which is better.
 You seem to be locked into this "value
 semantics therefore MUST be a struct" mentality, but that's not the only
 solution. D structs are simply lightweight aggregates. Treat them as 
 such, and
 use classes if you want more.

I can but give it a go.
 It's really only the intialization of structs that (most) people are 
 complaining
 about.

Regan. -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 13 2004
parent reply Arcane Jill <Arcane_member pathlink.com> writes:
In article <opsa3juaum5a2sq9 digitalmars.com>, Regan Heath says...

 You make a good point about what goes on when someone uses a static 
 opCall
 to emulate a constructor. I agree structs should have constructors. If
 they have constructors I think they should also have destructors.

Er... WHOA. They can't. That's just not possible in the D framework.

I think I need a tutorial on how they work then, cos I can't see the problem.

When a return statement is executed to leave a function, or a break statement is executed to leave a statement block, or a goto is executed, things go out of scope. When that happens in C++, destructors are called. In D, however, destructors are NOT called. (There is an exception to this rule - auto classes. I would imagine (though I don't know for sure) that these are implemented with some kind of invisible try/catch substitute). For D structs, this is perfectly fine, since D structs don't have destructors. For D classes, this is also fine, because those objects still exist on the heap. THEIR destructors will be called later, eventually, when the garbage collector gets around to it. So, to unwind the stack, all you have to do is reassign the stack pointer. (It's slightly more complicated in the event of an exception, but exceptions are supposed to be rare). If "things-which-were-stored-on-the-stack" were allowed destructors, this simple model would have to change quite drastically. Essentially, every struct would have to be auto! I imagine it would have to be quite a rewrite of D. Now, you might say, "why not store structs on the heap?. Of course, the problem would then go away. Well, can can store structs on the heap already (like this:) # MyStruct[] s = new MyStruct[1]; but you still can't give it a destructor, because there is still nothing to stop some other user from doing: # MyStruct s; If you want ALL structs to be stored on the heap, then that, again, would involve a rewrite of D (and the distinction between struct and class would start to disappear).
 And if you
 keep suggesting this all it means is that Walter will never give us
 CONstructors, which is a much more important priority.

My impression is that Walter considers each suggestion on it's own merits, he won't throw out one idea simply because it's suggested along with another, at least that is how he seems to me.

Perhaps, but Walter is on record (on this forum) as saying that he will consider giving us constructors for structs providing we can live without destructors, non-bitwise copying and inheritance. I don't want to give him the impression that we can't.
Yeah.. but structs have this wonderful ability to allow you to go..

struct A
{
   void foo()
   {
     *this = A.init;
   }
}

Ah yes. That's completely true. It's curious that you can't do that with classes, and I can't quite see why it should be disallowed. Still, it's not really TOO hard to do this the long way round in classes, like this: # class A # { # void foo() # { # memberVariable1 = T1.init; # memberVariable2 = T2.init; # memberVariable3 = T3.init; # // ... # } # } Arcane Jill
Jul 14 2004
parent Regan Heath <regan netwin.co.nz> writes:
On Wed, 14 Jul 2004 07:29:36 +0000 (UTC), Arcane Jill 
<Arcane_member pathlink.com> wrote:
 In article <opsa3juaum5a2sq9 digitalmars.com>, Regan Heath says...

 You make a good point about what goes on when someone uses a static
 opCall
 to emulate a constructor. I agree structs should have constructors. If
 they have constructors I think they should also have destructors.

Er... WHOA. They can't. That's just not possible in the D framework.

I think I need a tutorial on how they work then, cos I can't see the problem.

When a return statement is executed to leave a function, or a break statement is executed to leave a statement block, or a goto is executed, things go out of scope. When that happens in C++, destructors are called. In D, however, destructors are NOT called. (There is an exception to this rule - auto classes. I would imagine (though I don't know for sure) that these are implemented with some kind of invisible try/catch substitute). For D structs, this is perfectly fine, since D structs don't have destructors. For D classes, this is also fine, because those objects still exist on the heap. THEIR destructors will be called later, eventually, when the garbage collector gets around to it. So, to unwind the stack, all you have to do is reassign the stack pointer. (It's slightly more complicated in the event of an exception, but exceptions are supposed to be rare). If "things-which-were-stored-on-the-stack" were allowed destructors, this simple model would have to change quite drastically. Essentially, every struct would have to be auto! I imagine it would have to be quite a rewrite of D. Now, you might say, "why not store structs on the heap?. Of course, the problem would then go away. Well, can can store structs on the heap already (like this:) # MyStruct[] s = new MyStruct[1]; but you still can't give it a destructor, because there is still nothing to stop some other user from doing: # MyStruct s; If you want ALL structs to be stored on the heap, then that, again, would involve a rewrite of D (and the distinction between struct and class would start to disappear).

Thanks. I'll take my time digesting all this.
 And if you
 keep suggesting this all it means is that Walter will never give us
 CONstructors, which is a much more important priority.

My impression is that Walter considers each suggestion on it's own merits, he won't throw out one idea simply because it's suggested along with another, at least that is how he seems to me.

Perhaps, but Walter is on record (on this forum) as saying that he will consider giving us constructors for structs providing we can live without destructors, non-bitwise copying and inheritance. I don't want to give him the impression that we can't.

Sure.
 Yeah.. but structs have this wonderful ability to allow you to go..

 struct A
 {
   void foo()
   {
     *this = A.init;
   }
 }

Ah yes. That's completely true. It's curious that you can't do that with classes, and I can't quite see why it should be disallowed.

Good point. I'll create a new post asking this.
 Still, it's not
 really TOO hard to do this the long way round in classes, like this:

 #    class A
 #    {
 #        void foo()
 #        {
 #            memberVariable1 = T1.init;
 #            memberVariable2 = T2.init;
 #            memberVariable3 = T3.init;
 #            // ...
 #        }
 #    }

Until the class becomes large and/or you forget to add lines for newly added members.. etc. Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 14 2004
prev sibling parent J Anderson <REMOVEanderson badmama.com.au> writes:
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. Arcane Jill

feature should be generic. One way to do things, please simplify the language in these regards. I like how in many aspects of D how you think it should be done, is how it is done. But in other areas this is worse then C++. I still don't know all of C++, its just has to many odd rules of doing the same things. -- -Anderson: http://badmama.com.au/~anderson/
Jul 13 2004
prev sibling next sibling parent "Bent Rasmussen" <exo bent-rasmussen.info> writes:
 class Baz (T) {
 Baz!(T) recursive;
 }

class Baz(T) { Baz recursive; }
Jul 12 2004
prev sibling next sibling parent reply Norbert Nemec <Norbert.Nemec gmx.de> writes:
Matthias Becker wrote:

 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

The philosophy of ML and D is completely different. If you think ML while trying to program D, the result will definitely be messy. The same happens the other way around. The great strength of ML is the type deduction, allowing you to write generic functions at great ease. The great drawback of ML, though, is type deduction, forbidding you to do function overloading. Actually, I used O'Caml for some time and I really began to love it. Anyhow, after a while, I realized that the lack of function overloading really was weighing too heavily for me. Especially in numerics, function overloading really is an important aspect. D has some room for improvement left, but trying to compare it to ML will never be fair on either of the two languages.
Jul 12 2004
parent reply Matthias Becker <Matthias_member pathlink.com> writes:
The great strength of ML is the type deduction, allowing you to write
generic functions at great ease.

The great drawback of ML, though, is type deduction, forbidding you to do
function overloading.

Actually, I used O'Caml for some time and I really began to love it. Anyhow,
after a while, I realized that the lack of function overloading really was
weighing too heavily for me. Especially in numerics, function overloading
really is an important aspect.

There actualy are languages that can do both. Functional and oo-languages. E.g. in C++ you can have both: void foo (int x) // used for ints {...} template <typename T> // used for everything else void foo (T x) {...}
D has some room for improvement left, but trying to compare it to ML will
never be fair on either of the two languages.

Of course. Something like the powerfull pattern matching mechanism isn't possible in D without making big changes in the language. There is something called JMatch (a Java extension) that allows this. Constructors (and any other function for doing some logical programming) can have a foreward and a backward-modes. I suggested some time ago a possible way. something like: var foo = <expression>; if you use the keyword var the type is deduced/infered from the expression that is assigend. so var foo = 22; means int foo = 22; and var bar = 1.5; means double bar = 1.5;
Jul 12 2004
parent "Matthew Wilson" <dmd synesis.com.au> writes:
"Matthias Becker" <Matthias_member pathlink.com> wrote in message
news:ccu0nl$1lgk$1 digitaldaemon.com...
The great strength of ML is the type deduction, allowing you to write
generic functions at great ease.

The great drawback of ML, though, is type deduction, forbidding you to do
function overloading.

Actually, I used O'Caml for some time and I really began to love it.


after a while, I realized that the lack of function overloading really


weighing too heavily for me. Especially in numerics, function overloading
really is an important aspect.

There actualy are languages that can do both. Functional and oo-languages.

 in C++ you can have both:

 void foo (int x)   // used for ints
 {...}

 template <typename T>   // used for everything else
 void foo (T x)
 {...}

D has some room for improvement left, but trying to compare it to ML will
never be fair on either of the two languages.

Of course. Something like the powerfull pattern matching mechanism isn't possible in D without making big changes in the language. There is

 called JMatch (a Java extension) that allows this. Constructors (and any

 function for doing some logical programming) can have a foreward and a
 backward-modes.


 I suggested some time ago a possible way.

 something like:
 var foo = <expression>;

 if you use the keyword var the type is deduced/infered from the expression

 is assigend.

 so
 var foo = 22;
 means
 int foo = 22;
 and
 var bar = 1.5;
 means
 double bar = 1.5;

I believe this feature is very important, and will be needed. It's likely to be featured in the next version of C++.
Jul 12 2004
prev sibling next sibling parent Norbert Nemec <Norbert.Nemec gmx.de> writes:
Matthias Becker wrote:

 The more I use D the less I like it. But it's defently me, as "D is so
 great!".

Yes, it certainly is you - or better - your background in ML. Switching over to D, you will have to change your way of thinking fundamentally. A Chinese visiting Africa will go through hard times finding that life is different there. In the end, he might either give up, go home and tell people about those crazy Africans that do everything the wrong way. Or he might stay long enough to learn loving the country, learn new things, go home and bring new ideas with him. Or he stays even longer and starts feeling at home and decides to stay there. I just hope that you won't belong to the first group but stay open for intercultural exchange.
Jul 12 2004
prev sibling next sibling parent reply Ben Hinkle <bhinkle4 juno.com> writes:
 BTW: Why structs don't have constructors? I get crazy about this!
 
 Foo foo;
 foo.x = bla;
 foo.y = blub;
 // start using foo
 // *ARGH!!!*
 
 It's so messy.
 

A cleaner syntax for initializing structs (like the one that already exists for static structs) has been requested in the past. Something simple like Foo foo = {bla, blub}; being syntactic sugar for Foo foo; foo.x = bla; foo.y = blub; I'm waiting for post-1.0 to see something like this as well as support for array and struct literals. Full-blown constructors are another story and much harder to justify adding to the language. -Ben
Jul 12 2004
next sibling parent David Medlock <amedlock nospam.org> writes:
Ben Hinkle wrote:
BTW: Why structs don't have constructors? I get crazy about this!

Foo foo;
foo.x = bla;
foo.y = blub;
// start using foo
// *ARGH!!!*

It's so messy.

A cleaner syntax for initializing structs (like the one that already exists for static structs) has been requested in the past. Something simple like Foo foo = {bla, blub}; being syntactic sugar for Foo foo; foo.x = bla; foo.y = blub; I'm waiting for post-1.0 to see something like this as well as support for array and struct literals. Full-blown constructors are another story and much harder to justify adding to the language. -Ben

What is wrong with: Foo foo; with(foo) { x = bla; y = blub; } Clean as a whistle imo.
Jul 12 2004
prev sibling parent reply "C. Sauls" <ibisbasenji yahoo.com> writes:
Ben Hinkle wrote:

BTW: Why structs don't have constructors? I get crazy about this!

Foo foo;
foo.x = bla;
foo.y = blub;
// start using foo
// *ARGH!!!*

It's so messy.

A cleaner syntax for initializing structs (like the one that already exists for static structs) has been requested in the past. Something simple like Foo foo = {bla, blub}; being syntactic sugar for Foo foo; foo.x = bla; foo.y = blub; I'm waiting for post-1.0 to see something like this as well as support for array and struct literals. Full-blown constructors are another story and much harder to justify adding to the language. -Ben

Doesn't this work? Foo foo = {x:blah, y:blub}; -Chris S. -Invironz
Jul 12 2004
parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
"C. Sauls" <ibisbasenji yahoo.com> wrote in message
news:ccu5oc$1snh$2 digitaldaemon.com...
 Ben Hinkle wrote:

BTW: Why structs don't have constructors? I get crazy about this!

Foo foo;
foo.x = bla;
foo.y = blub;
// start using foo
// *ARGH!!!*

It's so messy.

A cleaner syntax for initializing structs (like the one that already


 for static structs) has been requested in the past. Something simple


  Foo foo = {bla, blub};

 being syntactic sugar for

  Foo foo;
  foo.x = bla;
  foo.y = blub;

 I'm waiting for post-1.0 to see something like this as well as support


 array and struct literals. Full-blown constructors are another story and
 much harder to justify adding to the language.

 -Ben

Doesn't this work? Foo foo = {x:blah, y:blub}; -Chris S. -Invironz

That only works for static data - try it in a function and you'll get "variable foo is not a static and cannot have static initializer."
Jul 12 2004
parent "C. Sauls" <ibisbasenji yahoo.com> writes:
Ben Hinkle wrote:
 "C. Sauls" <ibisbasenji yahoo.com> wrote in message
 news:ccu5oc$1snh$2 digitaldaemon.com...
Doesn't this work?

Foo foo = {x:blah, y:blub};

"variable foo is not a static and cannot have static initializer."

Ah.. I didn't realize that. In that case, ew. Maybe it could get a treatment rather like what array literals are getting... something like: {Foo: x:blah, y:blub}; Although then the first : is possibly ambiguous? Maybe array literals should use {} as well, instead of []. Or structs should use [] in literals. Ack, decisions decisions. -Chris S. -Invironz
Jul 12 2004
prev sibling next sibling parent reply =?ISO-8859-1?Q?Sigbj=F8rn_Lund_Olsen?= <sigbjorn lundolsen.net> writes:
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
Jul 12 2004
parent Regan Heath <regan netwin.co.nz> writes:
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/
Jul 12 2004
prev sibling next sibling parent Andy Friesen <andy ikagames.com> writes:
Matthias Becker wrote:
 So is it realy that stupid that this works:
 
 class Baz (T) {
 Baz!(T) recursive;
 }
 
 Everytime I try to code anything in D I get such behavior that I don't expect
 and often I don't find a workaround. But "D is so great". So are my ideas so
 strange that nobody else wants to do the things I want to? Why does nobody else
 say D is strange with a lot of unexpected behaviors?

I agree that something needs to be done here, but I'm not sure what. The whole class Baz(T) notation is shorthand for creating two symbols. (a template and a class of the same name). A solution that comes to mind is to make internal references to the symbol resolve to the template, not the enclosed class. It seems like a weird contradiction in the rules, but I can't think of any case where it might become an issue.
 BTW: Why structs don't have constructors? I get crazy about this!
 
 Foo foo;
 foo.x = bla;
 foo.y = blub;
 // start using foo
 // *ARGH!!!*
 
 It's so messy.

The static opCall idiom is a pretty good hack around this, but there's no reason the 'this()' syntax shouldn't be supported.
 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:
 
 [... terrible code ...]
 
 Of course this doesn't work, as you can overload opMul and structs and classes
 don't have an init-property. So you have to use an even more clumsy workaround:
 
 [... code ...]
 
 And this is needed only for one very simple line of ML!

Agreed: Deducing types is something D isn't so hot at. :)
 OK, perhaps Andy just expected other programmers to be smart enough to write a
 init-property for types that should be useable in istuations like this?

Nope. :) You bring up a good point: T.init should exist for all types. (null would be sufficient for classes) Looking back, I could have just written this: template mul(U, V) { typeof(U.init * V.init) mul(T x, T y) { return x * y; } } Which doesn't seem so bad. (aside from the Class.init thing)
 The more I use D the less I like it. But it's defently me, as "D is so great!".

I think it is. :) It's not perfect, but it's pretty nice. I can write code like it was Java, except I don't have to give up pointers, and I get tiny little binaries like C++. -- andy
Jul 12 2004
prev sibling parent "Walter" <newshound digitalmars.com> writes:
"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

 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

 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

 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; }}
Jul 12 2004