Jump to page: 1 2 3
Thread overview
Why there are no 'physical' object variables (only references)?
Sep 10, 2006
Kristian
Sep 10, 2006
Frits van Bommel
Sep 10, 2006
Kristian
Sep 10, 2006
Sean Kelly
Sep 11, 2006
BCS
Sep 12, 2006
Lionello Lunesu
Sep 12, 2006
BCS
Sep 12, 2006
Reiner Pope
Sep 13, 2006
Steve Horne
Sep 13, 2006
Reiner Pope
Sep 13, 2006
Steve Horne
Sep 13, 2006
BCS
Sep 10, 2006
Steve Horne
Sep 10, 2006
Sean Kelly
Sep 10, 2006
Kristian
Sep 10, 2006
Reiner Pope
Sep 12, 2006
Kristian
Sep 13, 2006
Steve Horne
Sep 13, 2006
Reiner Pope
Sep 13, 2006
Steve Horne
Sep 14, 2006
Kristian
Sep 10, 2006
Steve Horne
Sep 11, 2006
Lutger
Sep 11, 2006
Steve Horne
Sep 12, 2006
Kristian
Sep 12, 2006
Tydr Schnubbis
Sep 13, 2006
Steve Horne
Sep 22, 2006
Bruno Medeiros
Sep 23, 2006
Kristian
September 10, 2006
I'm used for having both the variable types, 'physical' and reference(/pointer) ones, so it feels strange to work with D (or Java, etc) that have reference types only.

First, there is no way to copy/clone an object (in general). That is, unless you provide a copy/clone function (for all the classes you're using). Second, you cannot create classes that behave like basic types, e.g. like integers.

For example, in C++ you could have:

void func() {
    Coord a, b, c;

    a.set(1, 2);
    b.set(5, 10);
    c = a + b;  //'c' is (6, 12)
    b = c;
    b.setX(2);  //'c' is unchanged, 'b' is (2, 12)
}

The 'Coord' objects have no 'global meaning' here, they are just simple values used in calculations. (So there is no need to reference them from other parts of the code.)

I think it's a big restriction if a language does not have both the variable types (physical + references).
Why D and other similar languages have no physical types?


And, I hope that D will have a 'const' type specifier in the future. Now you cannot know if a function will modify an object that is passed to it as a parameter. Or if a member function of a class will change the internal status of the object.

When these things are summed together, I'm afraid that I (at least) will create a number of situations where the values of objects are incorrectly changed in almost any part of the code. Hopefully not, though.
September 10, 2006
Kristian wrote:
> I'm used for having both the variable types, 'physical' and reference(/pointer) ones, so it feels strange to work with D (or Java, etc) that have reference types only.
> 
> First, there is no way to copy/clone an object (in general). That is, unless you provide a copy/clone function (for all the classes you're using). Second, you cannot create classes that behave like basic types, e.g. like integers.
> 
> For example, in C++ you could have:
> 
> void func() {
>     Coord a, b, c;
> 
>     a.set(1, 2);
>     b.set(5, 10);
>     c = a + b;  //'c' is (6, 12)
>     b = c;
>     b.setX(2);  //'c' is unchanged, 'b' is (2, 12)
> }
> 
> The 'Coord' objects have no 'global meaning' here, they are just simple values used in calculations. (So there is no need to reference them from other parts of the code.)
> 
> I think it's a big restriction if a language does not have both the variable types (physical + references).
> Why D and other similar languages have no physical types?

I think D structs are the "physical" variable type you're looking for.
They allow everything above. The Coord type + minor modifications to your code for testing:

    struct Coord
    {
        int x,y;

        void set(int x_, int y_) { x = x_; y = y_; }

        void setX(int x_) { x = x_; }

        Coord opAdd(Coord c)
        {
            Coord ret;
            ret.x = x + c.x;
            ret.y = y + c.y;
            return ret;
        }
    }

    void main() {
        Coord a, b, c;

        a.set(1, 2);
        b.set(5, 10);
        c = a + b;  //'c' is (6, 12)
        b = c;
        b.setX(2);  //'c' is unchanged, 'b' is (2, 12)

        // Check everything worked as planned:
        assert(a.x == 1);
        assert(a.y == 2);

        assert(b.x == 2);
        assert(b.y == 12);

        assert(c.x == 6);
        assert(c.y == 12);
    }

Runs without any asserts triggering.
Of course that's just a minimal working type, not how one would typically write such a type. For one thing, either make x and y private and add setY, getX and getY or get rid of set and setX. For another, you'll probably want some more operators (equality, subtraction, maybe "multiply by scalar").

Not everything needs to be a class. I see no reason why a type like Coord would need inheritance.

> And, I hope that D will have a 'const' type specifier in the future. Now you cannot know if a function will modify an object that is passed to it as a parameter. Or if a member function of a class will change the internal status of the object.

Yes, "const reference" parameters are something D doesn't do, unfortunately.

> When these things are summed together, I'm afraid that I (at least) will create a number of situations where the values of objects are incorrectly changed in almost any part of the code. Hopefully not, though.
September 10, 2006
On Sun, 10 Sep 2006 16:09:23 +0300, Frits van Bommel <fvbommel@REMwOVExCAPSs.nl> wrote:
[snip]
>>  The 'Coord' objects have no 'global meaning' here, they are just simple values used in calculations. (So there is no need to reference them from other parts of the code.)
>>  I think it's a big restriction if a language does not have both the variable types (physical + references).
>> Why D and other similar languages have no physical types?
>
> I think D structs are the "physical" variable type you're looking for.
> They allow everything above.
[snip]

Ah, of course, basic types can be usually implemented as structures, thanks. :)

Unfortunately some of the types have to be implemented as classes (e.g. a file class) because of the inheritance and/or constructors/destructors.

Hmm, what if structures could have interfaces and constructors/destructors... and what the heck, inheritance too? Hehheh, this way we would have 'physical classes' for local use and 'reference classes' for global use. Or we could have a new data type instead:

type Coord {...}  //like a class except its objects do not use referencing

That would be weird... or would it?
September 10, 2006
Kristian wrote:
> I'm used for having both the variable types, 'physical' and reference(/pointer) ones, so it feels strange to work with D (or Java, etc) that have reference types only.
> 
> First, there is no way to copy/clone an object (in general). That is, unless you provide a copy/clone function (for all the classes you're using).

Yup.  The .dup property is pretty standard, but there's no convention for whether this should represent deep or shallow copy (though shallow seems to make more sense).

> Second, you cannot create classes that behave like basic types,
> e.g. like integers.

True.  You can get pretty close, but D does not support an assignment operator and there is no universal construction syntax as there is in C++.  This was a deliberate decision, as handling copyable objects in C++ is a common source of bugs.

> For example, in C++ you could have:
> 
> void func() {
>     Coord a, b, c;
> 
>     a.set(1, 2);
>     b.set(5, 10);
>     c = a + b;  //'c' is (6, 12)
>     b = c;
>     b.setX(2);  //'c' is unchanged, 'b' is (2, 12)
> }
> 
> The 'Coord' objects have no 'global meaning' here, they are just simple values used in calculations. (So there is no need to reference them from other parts of the code.)
> 
> I think it's a big restriction if a language does not have both the variable types (physical + references).
> Why D and other similar languages have no physical types?

Currently, you can use a struct or construct a class in place using alloca.  Eventually, we will get a stack allocation syntax for classes along the lines of:

    Coord a = Coord(); // note there is no 'new'

I also proposed an '.isizeof' property to return the instance size of a reference/pointer at compile-time, but there was little interest in the idea.  However, it would allow you to do things like this:

    byte[Coord.isizeof] buf; // assume buf is properly aligned
    Coord a = new(&buf[0]) Coord();

> And, I hope that D will have a 'const' type specifier in the future. Now you cannot know if a function will modify an object that is passed to it as a parameter. Or if a member function of a class will change the internal status of the object.

Don't we all.  But wanting it and coming up with a solid proposal for how it should work are entirely different issues, unfortunately.


Sean
September 10, 2006
Kristian wrote:
> 
> Hmm, what if structures could have interfaces and constructors/destructors... and what the heck, inheritance too? Hehheh, this way we would have 'physical classes' for local use and 'reference classes' for global use.

It will never happen :-)  Though ctor support would be nice, at the very least.  That would simplify initialization and eliminate the need for the static opCall trick.


Sean
September 10, 2006
On Sun, 10 Sep 2006 18:59:34 +0300, Sean Kelly <sean@f4.ca> wrote:
> Kristian wrote:
>>  First, there is no way to copy/clone an object (in general). That is, unless you provide a copy/clone function (for all the classes you're using).
>
> Yup.  The .dup property is pretty standard, but there's no convention for whether this should represent deep or shallow copy (though shallow seems to make more sense).

Maybe there should be two properties, .dup and .deepdup (or something,
a name .ddup is probably too similar).


> True.  You can get pretty close, but D does not support an assignment
> operator and there is no universal construction syntax as there is in C++.
> This was a deliberate decision, as handling copyable objects
> in C++ is a common source of bugs.

Really? I mean, a common source of bugs? But isn't it be simple to fix such bugs, just correct the copy methods? With references there may be bugs much harder to find: an object you're referencing is changed somewhere you don't know. You may have to trace a lot of code to find where the object gets modified, and correct things around the code, not just in one class.

And what if you need copy/clone methods? You implement them by yourself (if there is no .deepdub). Using them is not so 'nice' because you can't override the assignment operator, etc. These copyable objects are still 'a source of bugs', even if used via references, of course.

(And I have to also mention :) that nobody forces you to use copy methods in C++. You can use objects via pointers only. But why people don't? Because copyable objects suit better in some situations.)


> Currently, you can use a struct or construct a class in place using alloca.  Eventually, we will get a stack allocation syntax for classes along the lines of:
>
>      Coord a = Coord(); // note there is no 'new'
>

Or maybe using a syntax (I have mentioned earlier):

Coord a();


>> And, I hope that D will have a 'const' type specifier in the future. Now you cannot know if a function will modify an object that is passed to it as a parameter. Or if a member function of a class will change the internal status of the object.
>
> Don't we all.  But wanting it and coming up with a solid proposal for how it should work are entirely different issues, unfortunately.

Well, what's wrong with the way C++ does it?

class Obj {
    void f() const;
    void g();

    int v;
}

void func(const Obj o) {
    o.f();    //ok
    o.g();    //error
    o.v = 1;  //error
}
September 10, 2006
On Sun, 10 Sep 2006 17:55:54 +0300, Kristian <kjkilpi@gmail.com> wrote:

>Hmm, what if structures could have interfaces and constructors/destructors... and what the heck, inheritance too?

I've promissed myself that I'm not going to say anything else about struct inheritance, so I'm keeping quiet ;-)

-- 
Remove 'wants' and 'nospam' from e-mail.
September 10, 2006
Kristian wrote:
> On Sun, 10 Sep 2006 18:59:34 +0300, Sean Kelly <sean@f4.ca> wrote:
>> Kristian wrote:
>>> And, I hope that D will have a 'const' type specifier in the future. Now you cannot know if a function will modify an object that is passed to it as a parameter. Or if a member function of a class will change the internal status of the object.
>>
>> Don't we all.  But wanting it and coming up with a solid proposal for how it should work are entirely different issues, unfortunately.
> 
> Well, what's wrong with the way C++ does it?
> 
> class Obj {
>     void f() const;
>     void g();
> 
>     int v;
> }
> 
> void func(const Obj o) {
>     o.f();    //ok
>     o.g();    //error
>     o.v = 1;  //error
> }

Do some searching for 'const' and 'readonly' on this NG, and you should get the idea:
 - C++ const is ugly, so people don't use it enough;
 - const_cast removes the safety guarantees of const, making const-directed optimizations by the compiler impossible.
 - overloading by const requires duplication of code.
 - a trivial const system like C++ is too strict and may require unnecessary clones to avoid a static const violation, thus necessitating the need for const_cast
 - reference immutability (C++'s 'readonly view') is only one form of const, and can't guarantee other (important) immutability contracts
 - after such a problems, the merits are not so clear, since the usefulness can only really be attributed to two things:
    1. Standardising documentation of variable usage.
    2. Getting the compiler to help catch programmer errors.
  and some people claim that they have never found any bugs by using const.

Cheers,

Reiner
September 10, 2006
On Sun, 10 Sep 2006 22:03:43 +0300, Kristian <kjkilpi@gmail.com> wrote:

>Maybe there should be two properties, .dup and .deepdup (or something, a name .ddup is probably too similar).

How often is there more than one useful meaning for 'duplicate' for a particular class anyway? Shallow vs. deep vs. something in between is usually an implementation detail.

>Really? I mean, a common source of bugs? But isn't it be simple to fix such bugs, just correct the copy methods?

I suspect this is about accidental copying. Parameter passing, implicit conversions, unexpected temporaries etc.

I have an ideological disagreement against making references compulsory in a languages that has mutability (any imperitive language). You can easily get things being changed that weren't intended to be changed. You save info. for later, but the saved info. mutates because it wasn't a copy, for instance. In practice, it sometimes causes me hassles in Python, and probably would in Java if I used it much.

But pragmatism beats ideology every time. In C# and D the implicit references work well, for me. There seems to be an intuitive divide between 'object' and 'value'. For a 'value', I expect parameter passing to have copy semantics. For an 'object' I expect sharing (reference) semantics.

Maybe it's something to do with the real world. It's just natural to work with existing objects - not duplicates of those objects. When I was told to clean my room as a child, I don't think stories about duplicating the room, cleaning the duplicate and discarding it would have worked ;-)

With 'values' - numbers etc - copy semantics seem more sane. In algebra, calculating the unknowns does not alter the known values. Outputs are based on inputs, not the other way around. Even feedback has a time delay - the calculation of the output doesn't change its input, it just provides a new input for the next millisecond or whatever.

The trouble is, this is all subjective. The Python one-size-fits-all everythings-an-object-with-a-reference approach will probably always bug me, but a lot depends on what you're used to.

-- 
Remove 'wants' and 'nospam' from e-mail.
September 11, 2006
Steve Horne wrote:
 > But pragmatism beats ideology every time. In C# and D the implicit
> references work well, for me. There seems to be an intuitive divide
> between 'object' and 'value'. For a 'value', I expect parameter
> passing to have copy semantics. For an 'object' I expect sharing
> (reference) semantics.
> 
> Maybe it's something to do with the real world. It's just natural to
> work with existing objects - not duplicates of those objects. When I
> was told to clean my room as a child, I don't think stories about
> duplicating the room, cleaning the duplicate and discarding it would
> have worked ;-)
> 
> With 'values' - numbers etc - copy semantics seem more sane. In
> algebra, calculating the unknowns does not alter the known values.
> Outputs are based on inputs, not the other way around. Even feedback
> has a time delay - the calculation of the output doesn't change its
> input, it just provides a new input for the next millisecond or
> whatever.

Well said. I needed some time to adjust to the reference semantics of classes in D and it's less (than C++) capable struct type. But now I'm used to it, it really makes sense.

Besides some minor details, in C++ a struct is the same as a class. But in D they really are different beasts, making the distinction and when to use which one easier. In C++ you have to think all the time about reference vs value semantics and take care of what happens in the assignment operator and copy constructor, and not only wrt memory allocation.

Even though you don't have the standard syntactic sugar of struct construction and copying in D, the way it works now is intuitive enough  and - imho - makes for a more productive and safe way of doing things. Assignment can be a dangerous operation and in D you can be sure of what happens at least.
« First   ‹ Prev
1 2 3