Jump to page: 1 2
Thread overview
mutable constant?
Jun 25, 2013
Namespace
Jun 25, 2013
Simen Kjaeraas
Jun 25, 2013
Jonathan M Davis
Jun 25, 2013
Namespace
Jun 25, 2013
Jonathan M Davis
Jun 25, 2013
Ali Çehreli
Jun 26, 2013
Namespace
Jun 26, 2013
monarch_dodra
Jun 26, 2013
Jonathan M Davis
Jun 26, 2013
monarch_dodra
Jun 26, 2013
anonymous
Jun 27, 2013
Jonathan M Davis
Jun 27, 2013
anonymous
Jun 27, 2013
Jonathan M Davis
Jun 27, 2013
Namespace
June 25, 2013
I want to ask if this code should compile or if it's a bug, because I circumvent the const system:

----
import std.stdio;

struct Point {
	int x, y;
}

Point*[] points;

struct TplPoint(T) {
public:
	Point _point;

	T x, y;

	const uint id;

	this(T x, T y) {
		this.x = x;
		this.y = y;

		points ~= &this._point;

		id = points.length - 1;
	}

	@property
	inout(Point)* ptr() inout {
		points[this.id].x = cast(int) this.x;
		points[this.id].y = cast(int) this.y;

		return cast(inout Point*) points[this.id];
	}
}

void main() {
	const TplPoint!float my = TplPoint!float(42, 23);
	writeln(my._point, "::", &my._point);
	writeln(*my.ptr, "::", my.ptr);
}
----

Or is the fact that it compiles ok and it's "only" unsafe?
June 25, 2013
On Wed, 26 Jun 2013 00:07:38 +0200, Namespace <rswhite4@googlemail.com> wrote:

> I want to ask if this code should compile or if it's a bug, because I circumvent the const system:
>
> ----
> import std.stdio;
>
> struct Point {
> 	int x, y;
> }
>
> Point*[] points;
>
> struct TplPoint(T) {
> public:
> 	Point _point;
>
> 	T x, y;
>
> 	const uint id;
>
> 	this(T x, T y) {
> 		this.x = x;
> 		this.y = y;
>
> 		points ~= &this._point;
>
> 		id = points.length - 1;
> 	}
>
> 	@property
> 	inout(Point)* ptr() inout {
> 		points[this.id].x = cast(int) this.x;
> 		points[this.id].y = cast(int) this.y;
>
> 		return cast(inout Point*) points[this.id];
> 	}
> }
>
> void main() {
> 	const TplPoint!float my = TplPoint!float(42, 23);
> 	writeln(my._point, "::", &my._point);
> 	writeln(*my.ptr, "::", my.ptr);
> }
> ----
>
> Or is the fact that it compiles ok and it's "only" unsafe?

This is perfectly fine.

-- 
Simen
June 25, 2013
On Wednesday, June 26, 2013 00:07:38 Namespace wrote:
> I want to ask if this code should compile or if it's a bug, because I circumvent the const system:
> 
> ----
> import std.stdio;
> 
> struct Point {
> int x, y;
> }
> 
> Point*[] points;
> 
> struct TplPoint(T) {
> public:
> Point _point;
> 
> T x, y;
> 
> const uint id;
> 
> this(T x, T y) {
> this.x = x;
> this.y = y;
> 
> points ~= &this._point;
> 
> id = points.length - 1;
> }
> 
> @property
> inout(Point)* ptr() inout {
> points[this.id].x = cast(int) this.x;
> points[this.id].y = cast(int) this.y;
> 
> return cast(inout Point*) points[this.id];
> }
> }
> 
> void main() {
> const TplPoint!float my = TplPoint!float(42, 23);
> writeln(my._point, "::", &my._point);
> writeln(*my.ptr, "::", my.ptr);
> }
> ----
> 
> Or is the fact that it compiles ok and it's "only" unsafe?

I could certainly be missing something here, but I don't understand what about the code you're even concerned about. Where in here would you be breaking the type system? I don't see any place in here where you're mutating a const variable or anything like that. The worst thing I see about the code is that it won't compile on 64-bit machines thanks to

id = points.length - 1;

- Jonathan M Davis
June 25, 2013
If you change uint to size_t it works fine AFAIK.
June 25, 2013
On Wednesday, June 26, 2013 00:52:58 Namespace wrote:
> If you change uint to size_t it works fine AFAIK.

Yes. It's easy enough to fix, but it _is_ arguably a bug in the code, and it's the only one that's obvious to me. I don't understand what about the code makes you think that it might be violating the type system.

- Jonathan M Davis


P.S. Please always quote at least a portion of the post that you're replying to. Clients frequently do not manage to thread posts correctly, and it's not always clear which post a post is replying to if it doesn't quote any of its parent. In this particular case, based on what you said, I expect that you were replying to me, but it's threaded in my client as being a responsed to Simen. Also, not all posters even use a threaded view. So, relying on threading to make it clear which post you're replying to is not a good idea.
June 25, 2013
With apologies, I have unrelated comments to make.

On 06/25/2013 03:07 PM, Namespace wrote:

>      this(T x, T y) {
>          this.x = x;
>          this.y = y;
>
>          points ~= &this._point;

I have seen similar designs in the past where constructors had side-effects such as registering the object in a global state. (Exactly what the last line is doing above.)

It has almost always been cause of trouble. It is better to register an object from the outside after constructing it.

Sometimes I had attempted to remove seemingly unused objects only to be reminded by a comment that it should not be:

    // Do not remove! Registers itself in the points array
    auto p = Point();

>      @property
>      inout(Point)* ptr() inout {
>          points[this.id].x = cast(int) this.x;
>          points[this.id].y = cast(int) this.y;

That looks questionable as well: ptr() looks like an accessor but it makes changes to a global state.

Ali

June 26, 2013
On Tuesday, 25 June 2013 at 23:39:45 UTC, Ali Çehreli wrote:
> With apologies, I have unrelated comments to make.
>
> On 06/25/2013 03:07 PM, Namespace wrote:
>
> >      this(T x, T y) {
> >          this.x = x;
> >          this.y = y;
> >
> >          points ~= &this._point;
>
> I have seen similar designs in the past where constructors had side-effects such as registering the object in a global state. (Exactly what the last line is doing above.)
>
> It has almost always been cause of trouble. It is better to register an object from the outside after constructing it.
>
> Sometimes I had attempted to remove seemingly unused objects only to be reminded by a comment that it should not be:
>
>     // Do not remove! Registers itself in the points array
>     auto p = Point();
>
> >      @property
> >      inout(Point)* ptr() inout {
> >          points[this.id].x = cast(int) this.x;
> >          points[this.id].y = cast(int) this.y;
>
> That looks questionable as well: ptr() looks like an accessor but it makes changes to a global state.
>
> Ali

This is no real code. Just a test example to check. ;)
June 26, 2013
On Wednesday, 26 June 2013 at 07:35:08 UTC, Namespace wrote:
> On Tuesday, 25 June 2013 at 23:39:45 UTC, Ali Çehreli wrote:
>> With apologies, I have unrelated comments to make.
>>
>> On 06/25/2013 03:07 PM, Namespace wrote:
>>
>> >     this(T x, T y) {
>> >         this.x = x;
>> >         this.y = y;
>> >
>> >         points ~= &this._point;
>>
>> I have seen similar designs in the past where constructors had side-effects such as registering the object in a global state. (Exactly what the last line is doing above.)
>>
>> It has almost always been cause of trouble. It is better to register an object from the outside after constructing it.
>>
>> Sometimes I had attempted to remove seemingly unused objects only to be reminded by a comment that it should not be:
>>
>>    // Do not remove! Registers itself in the points array
>>    auto p = Point();
>>
>> >     @property
>> >     inout(Point)* ptr() inout {
>> >         points[this.id].x = cast(int) this.x;
>> >         points[this.id].y = cast(int) this.y;
>>
>> That looks questionable as well: ptr() looks like an accessor but it makes changes to a global state.
>>
>> Ali
>
> This is no real code. Just a test example to check. ;)

It seems safe, however, your example seems to show how to indeed break the type system... without a cast (!):

    @property
    Point* ptr() inout {
        points[this.id].x = cast(int) this.x;
        points[this.id].y = cast(int) this.y;

        return points[this.id];
    }


void main() {
    immutable TplPoint!float my = TplPoint!float(42, 23);
    Point* p = my.ptr; //Oops! mutable point!
}

Disturbing...

>     this(T x, T y) {
>         this.x = x;
>         this.y = y;
>
>         points ~= &this._point;

I'd careful with this, you can easily end up with pointers to destroyed temporaries...
June 26, 2013
On Wednesday, June 26, 2013 13:16:16 monarch_dodra wrote:
> It seems safe, however, your example seems to show how to indeed break the type system... without a cast (!):
> 
>      @property
>      Point* ptr() inout {
>          points[this.id].x = cast(int) this.x;
>          points[this.id].y = cast(int) this.y;
> 
>          return points[this.id];
>      }
> 
> 
> void main() {
>      immutable TplPoint!float my = TplPoint!float(42, 23);
>      Point* p = my.ptr; //Oops! mutable point!
> }
> 
> Disturbing...

It doesn't break anything. It just shows the need for pure.

- Jonathan M Davis
June 26, 2013
On Wednesday, 26 June 2013 at 15:48:42 UTC, Jonathan M Davis wrote:
>
> It doesn't break anything. It just shows the need for pure.
>
> - Jonathan M Davis

OOhhhh.... I just got it :(

nevermind then...
« First   ‹ Prev
1 2