digitalmars.D - Implicit dereferencing
- =?UTF-8?B?Ikx1w61z?= Marques" (34/34) Apr 01 2013 Consider this (non-portable) code:
-
Steven Schveighoffer
(17/31)
Apr 01 2013
On Mon, 01 Apr 2013 20:07:30 -0400, Lu=C3=ADs Marques
- =?UTF-8?B?Ikx1w61z?= Marques" (16/22) Apr 01 2013 OK, I think I see where I went astray. I was a case of bad
-
Steven Schveighoffer
(22/43)
Apr 01 2013
On Mon, 01 Apr 2013 23:23:49 -0400, Lu=C3=ADs Marques
- =?UTF-8?B?Ikx1w61z?= Marques" (10/12) Apr 01 2013 Yeah, of course you're right...
-
Steven Schveighoffer
(24/35)
Apr 01 2013
On Tue, 02 Apr 2013 00:12:37 -0400, Lu=C3=ADs Marques
- =?UTF-8?B?Ikx1w61z?= Marques" (21/23) Apr 01 2013 Thanks Steve, I had already looked into that, but then got dense
-
Steven Schveighoffer
(27/48)
Apr 02 2013
On Tue, 02 Apr 2013 01:59:13 -0400, Lu=C3=ADs Marques
- kenji hara (8/25) Apr 01 2013 These are doing that element-wise assignment.
-
=?UTF-8?B?QWxpIMOHZWhyZWxp?=
(8/19)
Apr 01 2013
On 04/01/2013 05:07 PM, "Luís Marques"
" wrote:>...
Consider this (non-portable) code: { int[2] a; int[2] b; int[2] *c; c = &a; c[0] = 7; assert(a[0] == 7); // OK, as expected c[1] = 42; assert(b[0] == 42); // do we really want this semantics? } Because indexing c automatically dereferences the pointer, "c[0] = 7" assigns to a[0], as expected. This is the same as "(*c)[0] = 7", which is useful. But "c[1] = 42" is equivalent to "(*(c+1)) = 42", which might not be obvious. In this case it ends writing to b[0]. Why not make the semantics be ((*c)+1) = 42, instead? Wouldn't that be more useful? Also, why don't we have pointer dereferencing for AAs? { struct Foo { int f; } // given that this works... Foo x; Foo *y = &x; x.f = 1; y.f = 2; // implicit dereferencing // coudln't this be made to work?... int[string] c; int[string] *d; d = &c; c["foo"] = 1; d["foo"] = 2; // fails, dereferencing must be explicit (*d)["foo"] = 2; // works, of course }
Apr 01 2013
On Mon, 01 Apr 2013 20:07:30 -0400, Lu=C3=ADs Marques <luismarques gmail= .com> = wrote:Consider this (non-portable) code: { int[2] a; int[2] b; int[2] *c; c =3D &a; c[0] =3D 7; assert(a[0] =3D=3D 7); // OK, as expected c[1] =3D 42; assert(b[0] =3D=3D 42); // do we really want this semantics? } Because indexing c automatically dereferences the pointer, "c[0] =3D 7=" =assigns to a[0], as expected. This is the same as "(*c)[0] =3D 7", whi=ch =is useful.This is not what is happening. If you add: writeln(a); you will see: 7, 7 You see, indexing does NOT dereference the pointer, it's an index for th= at = pointer. c[0] means *(c + 0). A pointer is essentially an unchecked = slice, with undefined length. This is how it works in C also. c[1] is the same as *(c + 1), completely consistent (and also sets b to = = 42, 42) -Steve
Apr 01 2013
On Tuesday, 2 April 2013 at 02:52:48 UTC, Steven Schveighoffer wrote:You see, indexing does NOT dereference the pointer, it's an index for that pointer. c[0] means *(c + 0). A pointer is essentially an unchecked slice, with undefined length. This is how it works in C also. c[1] is the same as *(c + 1), completely consistent (and also sets b to 42, 42)OK, I think I see where I went astray. I was a case of bad induction from a few tests :-) So, I guess what is happening is the following, right? int[2] a; int[2] *c; c = &a; c[0] = 7; // same thing as below a = 7; // same thing above (cast(int*) c)[0] = 7; // but different from this I verified that c is a pointer to a.ptr, I guess what I didn't consider is that because c points to int[2], the assignment becomes the same as a = 7, and not a[0] = 7. Still, what do you think of the struct vs AA automatic pointer dereferencing?
Apr 01 2013
On Mon, 01 Apr 2013 23:23:49 -0400, Lu=C3=ADs Marques <luismarques gmail= .com> = wrote:On Tuesday, 2 April 2013 at 02:52:48 UTC, Steven Schveighoffer wrote:=You see, indexing does NOT dereference the pointer, it's an index for=that pointer. c[0] means *(c + 0). A pointer is essentially an =so.unchecked slice, with undefined length. This is how it works in C al=to =c[1] is the same as *(c + 1), completely consistent (and also sets b =42, 42)OK, I think I see where I went astray. I was a case of bad induction =from a few tests :-) So, I guess what is happening is the following, right? int[2] a; int[2] *c; c =3D &a; c[0] =3D 7; // same thing as below a =3D 7; // same thing above (cast(int*) c)[0] =3D 7; // but different from this I verified that c is a pointer to a.ptr, I guess what I didn't conside=r =is that because c points to int[2], the assignment becomes the same as=a ==3D 7, and not a[0] =3D 7. Still, what do you think of the struct vs AA automatic pointer =dereferencing?a pointer defines indexing. To have implicit dereferencing for indexing= = on any pointer type would not be good. For example: string[int][2] aas; string[int] *aaptr =3D aas.ptr; auto x =3D aaptr[1]; If x is not a pointer to aas[1], then you would have to access it using = = *(aaptr + 1), which would suck. Plus it would make pointers to indexed = = types inconsistent with all pointers to types that don't define indexing= . -Steve
Apr 01 2013
On Tuesday, 2 April 2013 at 03:36:04 UTC, Steven Schveighoffer wrote:Plus it would make pointers to indexed types inconsistent with all pointers to types that don't define indexing.Yeah, of course you're right... Taking a step back, I think the problem here is that I wanted to have multiple references to the contents of an associative array. With a regular array, while you can't *store* a reference to the array "header" (ptr, length) without using pointers, you can have another array pointing to the same content. I guess you can't do something like that with an associative array, right? (mm... that kinda breaks the ideia of an AA as a more general array)
Apr 01 2013
On Tue, 02 Apr 2013 00:12:37 -0400, Lu=C3=ADs Marques <luismarques gmail= .com> = wrote:On Tuesday, 2 April 2013 at 03:36:04 UTC, Steven Schveighoffer wrote:Plus it would make pointers to indexed types inconsistent with all ==pointers to types that don't define indexing.Yeah, of course you're right... Taking a step back, I think the problem here is that I wanted to have =multiple references to the contents of an associative array. With a =regular array, while you can't *store* a reference to the array "heade=r" =(ptr, length) without using pointers, you can have another array =pointing to the same content. I guess you can't do something like that==with an associative array, right? (mm... that kinda breaks the ideia o=f =an AA as a more general array)An AA is a pImpl, meaning a pointer to implementation. A simple copy is= = an alias. HOWEVER, there is one horrible caveat. You must have assigned an elemen= t = at least once in order to alias: int[int] aa1; // pImpl initialized to null int[int] aa2; // pImpl initialized to null aa2 =3D aa1; // just assigns null to aa2 aa1[1] =3D 1; // allocates and initializes aa2[1] =3D 2; // allocates and initializes separate instance assert(aa1[1] =3D=3D 1 && aa2[1] =3D=3D 2); aa2 =3D aa1; // NOW they are aliased assert(aa2[1] =3D=3D 1); aa2[1] =3D 2; assert(aa1[1] =3D=3D 2); -Steve
Apr 01 2013
On Tuesday, 2 April 2013 at 04:48:54 UTC, Steven Schveighoffer wrote:HOWEVER, there is one horrible caveat. You must have assigned an element at least once in order to alias:Thanks Steve, I had already looked into that, but then got dense and I was treating the AA as having value semantics. I don't need the pointer. Is there a way to ensure the AA is initialized as not null, besides adding and removing an element? (I couldn't use a literal) Is the null initializer a consequence of the current opaque implementation, or just of the reference semantics? (I saw on the wiki that there was a desire to use a less opaque implementation. I think the AA ABI should be documented, like the other arrays) Slightly related, it doesn't seem very reasonable to me that the get method of AAs is not safe: safe: void main() { int[string] x; x.get("b", 0); } Error: safe function 'D main' cannot call system function 'object.AssociativeArray!(string, int).AssociativeArray.get'
Apr 01 2013
On Tue, 02 Apr 2013 01:59:13 -0400, Lu=C3=ADs Marques <luismarques gmail= .com> = wrote:On Tuesday, 2 April 2013 at 04:48:54 UTC, Steven Schveighoffer wrote:HOWEVER, there is one horrible caveat. You must have assigned an ==element at least once in order to alias:Thanks Steve, I had already looked into that, but then got dense and I=was treating the AA as having value semantics. I don't need the pointe=r.Is there a way to ensure the AA is initialized as not null, besides =adding and removing an element? (I couldn't use a literal)Not sure. Looking... can't find anything. So no. There really should be.Is the null initializer a consequence of the current opaque =implementation, or just of the reference semantics? (I saw on the wiki==that there was a desire to use a less opaque implementation. I think t=he =AA ABI should be documented, like the other arrays)The AA ABI is defined by druntime in object.di. AA's are currently a = hybrid between a compiler-magic type and a template. The plan is to mak= e = it completely a template, that is, the compiler simply always treats T[U= ] = as AssociativeArray!(T, U). The null initializer is a result of D's policy on struct initialization.= = Default constructors are not allowed on structs, they must be able to be= = initialized with static data when declared without a constructor.Slightly related, it doesn't seem very reasonable to me that the get =method of AAs is not safe: safe: void main() { int[string] x; x.get("b", 0); } Error: safe function 'D main' cannot call system function ='object.AssociativeArray!(string, int).AssociativeArray.get'Someone (can't remember who) went through a lot of effort to try and = re-implement AAs as object.AssociativeArray and ran into a lot of proble= ms = with things like safe and pure. It really should be safe, but I don't= = know if there was a specific reason why it wasn't tagged that way. -Steve
Apr 02 2013
2013/4/2 <luismarques gmail.com>" puremagic.com <"\"Lu=C3=ADs".Marques">On Tuesday, 2 April 2013 at 02:52:48 UTC, Steven Schveighoffer wrote:edYou see, indexing does NOT dereference the pointer, it's an index for that pointer. c[0] means *(c + 0). A pointer is essentially an uncheck=These are doing that element-wise assignment. c[0][] =3D 7; // same as c[0][0] =3D c[0][1] =3D 7; a[] =3D 7; // same as a[0] =3D a[1] =3D 7; As a side note:slice, with undefined length. This is how it works in C also. c[1] is the same as *(c + 1), completely consistent (and also sets b to 42, 42)OK, I think I see where I went astray. I was a case of bad induction from a few tests :-) So, I guess what is happening is the following, right? int[2] a; int[2] *c; c =3D &a; c[0] =3D 7; // same thing as below a =3D 7; // same thing aboveFrom 2.063, lack of [] for array operation would be warned with -w switch.So, there is no "implicit dereferencing". Kenji Hara
Apr 01 2013
On 04/01/2013 05:07 PM, "Luís Marques" <luismarques gmail.com>" wrote:> Consider this (non-portable) code: Perhaps it is obvious to everyone but allow me still: It is not non-portable code, but its behavior is undefined.{ int[2] a; int[2] b; int[2] *c;c is a pointer to a single int[2].c = &a; c[0] = 7; assert(a[0] == 7); // OK, as expected c[1] = 42; assert(b[0] == 42); // do we really want this semantics?A manifestation of undefined behavior.But "c[1] = 42" is equivalent to "(*(c+1)) = 42", which might not be obvious. In this case it ends writing to b[0].It seems to be so but it is not defined to work that way. Ali
Apr 01 2013