www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to foreach over a DList?

reply "Jeroen Bollen" <jbinero gmail.com> writes:
I am trying to foreach over a std.container.DList but it isn't 
working. I have tried the following code: 
https://gist.github.com/Binero/f30e56351baf05f1a2ec

I am getting the following errors:

/usr/include/dlang/dmd/std/container.d(1925): Error: template 
std.container.DList!ubyte.DList.insertBeforeNode cannot deduce 
function from argument types !()(typeof(null), int), candidates 
are:
/usr/include/dlang/dmd/std/container.d(2096):        
std.container.DList!ubyte.DList.insertBeforeNode(Stuff)(Node* n, 
Stuff stuff) if (isInputRange!Stuff && 
isImplicitlyConvertible!(ElementType!Stuff, T))
/usr/include/dlang/dmd/std/container.d(2155):        
std.container.DList!ubyte.DList.insertBeforeNode(Stuff)(Node* n, 
Stuff stuff) if (isImplicitlyConvertible!(Stuff, T))
source/app.d(7): Error: template instance 
std.container.DList!ubyte.DList.insertBack!int error instantiating
source/app.d(11): Error: invalid foreach aggregate list1
Mar 31 2014
next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Mon, Mar 31, 2014 at 05:50:16PM +0000, Jeroen Bollen wrote:
 I am trying to foreach over a std.container.DList but it isn't working. I
 have tried the following code:
[...] Maybe try using opSlice: DList myList; foreach (e; myList[]) { ... } ? T -- Three out of two people have difficulties with fractions. -- Dirk Eddelbuettel
Mar 31 2014
next sibling parent reply "Jeroen Bollen" <jbinero gmail.com> writes:
On Monday, 31 March 2014 at 18:24:39 UTC, H. S. Teoh wrote:
 On Mon, Mar 31, 2014 at 05:50:16PM +0000, Jeroen Bollen wrote:
 I am trying to foreach over a std.container.DList but it isn't 
 working. I
 have tried the following code:
[...] Maybe try using opSlice: DList myList; foreach (e; myList[]) { ... } ? T
Can you explain that syntax?
Mar 31 2014
parent reply "Jeroen Bollen" <jbinero gmail.com> writes:
On Monday, 31 March 2014 at 19:26:23 UTC, Jeroen Bollen wrote:
 On Monday, 31 March 2014 at 18:24:39 UTC, H. S. Teoh wrote:
 On Mon, Mar 31, 2014 at 05:50:16PM +0000, Jeroen Bollen wrote:
 I am trying to foreach over a std.container.DList but it 
 isn't working. I
 have tried the following code:
[...] Maybe try using opSlice: DList myList; foreach (e; myList[]) { ... } ? T
Can you explain that syntax?
nvm figured it out; Are constant DLists supposed to be un-foreach-able? Error: mutable method std.container.DList!(ubyte).DList.opSlice is not callable using a const object
Mar 31 2014
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Mon, Mar 31, 2014 at 07:30:11PM +0000, Jeroen Bollen wrote:
 On Monday, 31 March 2014 at 19:26:23 UTC, Jeroen Bollen wrote:
On Monday, 31 March 2014 at 18:24:39 UTC, H. S. Teoh wrote:
On Mon, Mar 31, 2014 at 05:50:16PM +0000, Jeroen Bollen wrote:
I am trying to foreach over a std.container.DList but it isn't
working. I
have tried the following code:
[...] Maybe try using opSlice: DList myList; foreach (e; myList[]) { ... } ? T
Can you explain that syntax?
nvm figured it out; Are constant DLists supposed to be un-foreach-able? Error: mutable method std.container.DList!(ubyte).DList.opSlice is not callable using a const object
Argh, why is opSlice non-const? :-( Please file a bug. Not sure what you can do in the meantime... probably cast away const? Or avoid using const for containers if you can. The last time I tried that, I got stuck in a quagmire of partially-implemented const support with no way out of the mess, and I decided that non-const is less painful to work with. :-/ T -- English is useful because it is a mess. Since English is a mess, it maps well onto the problem space, which is also a mess, which we call reality. Similarly, Perl was designed to be a mess, though in the nicests of all possible ways. -- Larry Wall
Mar 31 2014
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Monday, 31 March 2014 at 21:41:16 UTC, H. S. Teoh wrote:
 Argh, why is opSlice non-const? :-(  Please file a bug.
If opSlice was const, then you'd get a const slice, with const reference. You wouldn't even be able to iterate on it. With some extra code, you could create some sort of "slice of immutable" type, but you'd still only be able to get const items. We *could* add a const *overload* but...
 Or avoid using const for containers if you can.
That. D's "turtles all the way down" const doesn't work like C++'s "head only" const. As a general rule, don't use too much const in D, *especially* for containers-like objects... At this point, adding a const overload would be nothing more that a still unusable mess, with extra maintenance overhead.
Mar 31 2014
next sibling parent "anonymous" <anonymous example.com> writes:
On Monday, 31 March 2014 at 21:55:03 UTC, monarch_dodra wrote:
 If opSlice was const, then you'd get a const slice, with const 
 reference. You wouldn't even be able to iterate on it.
const opSlice does not mean it returns a const(Range).
 With some extra code, you could create some sort of "slice of 
 immutable" type, but you'd still only be able to get const 
 items.
Iterating over const items is the goal.
 We *could* add a const *overload* but...

 Or avoid using const for containers if you can.
That. D's "turtles all the way down" const doesn't work like C++'s "head only" const. As a general rule, don't use too much const in D, *especially* for containers-like objects... At this point, adding a const overload would be nothing more that a still unusable mess, with extra maintenance overhead.
Gotta disagree violently here. Asking for a const overload of opSlice isn't "too much const". std.container is just in a sorry state regarding const compatibility. That can and should be fixed.
Mar 31 2014
prev sibling next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Mon, Mar 31, 2014 at 09:55:01PM +0000, monarch_dodra wrote:
 On Monday, 31 March 2014 at 21:41:16 UTC, H. S. Teoh wrote:
Argh, why is opSlice non-const? :-(  Please file a bug.
If opSlice was const, then you'd get a const slice, with const reference. You wouldn't even be able to iterate on it.
[...] Um... wat? I didn't say opSlice should return a const object (that would be ridiculous, as you point out). Rather, it should return a tail-const range that iterates over the const items in the const list. A const container that cannot be iterated over makes no sense at all. Iterating over something doesn't modify anything!! T -- Ruby is essentially Perl minus Wall.
Mar 31 2014
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Tuesday, 1 April 2014 at 04:43:44 UTC, H. S. Teoh wrote:
 On Mon, Mar 31, 2014 at 09:55:01PM +0000, monarch_dodra wrote:
 On Monday, 31 March 2014 at 21:41:16 UTC, H. S. Teoh wrote:
Argh, why is opSlice non-const? :-(  Please file a bug.
If opSlice was const, then you'd get a const slice, with const reference. You wouldn't even be able to iterate on it.
[...] Um... wat?
I'm pointing out the fix is not as trivial as slapping "const" onto the signature. It requires a very real investment in terms of development.
 I didn't say opSlice should return a const object (that would be
 ridiculous, as you point out). Rather, it should return a 
 tail-const
 range that iterates over the const items in the const list.
Yes.
 A const container that cannot be iterated over makes no sense 
 at all.
 Iterating over something doesn't modify anything!!
Yes.
Mar 31 2014
parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Apr 01, 2014 at 06:04:48AM +0000, monarch_dodra wrote:
 On Tuesday, 1 April 2014 at 04:43:44 UTC, H. S. Teoh wrote:
On Mon, Mar 31, 2014 at 09:55:01PM +0000, monarch_dodra wrote:
On Monday, 31 March 2014 at 21:41:16 UTC, H. S. Teoh wrote:
Argh, why is opSlice non-const? :-(  Please file a bug.
If opSlice was const, then you'd get a const slice, with const reference. You wouldn't even be able to iterate on it.
[...] Um... wat?
I'm pointing out the fix is not as trivial as slapping "const" onto the signature. It requires a very real investment in terms of development.
[...] Well, yes... I don't expect just adding 'const' to an existing function is going to magically make it work with const types. :-P Though I suppose the way I said it was ambiguous. My bad. T -- Those who don't understand Unix are condemned to reinvent it, poorly.
Apr 01 2014
prev sibling parent reply "Jeroen Bollen" <jbinero gmail.com> writes:
Still no luck:

import std.container;
import std.stdio;

void main()
{
	DList!ubyte list1 = DList!ubyte();
	list1 ~= cast(ubyte) 1;
	list1 ~= cast(ubyte) 2;
	list1 ~= cast(ubyte) 3;

	foreach(ubyte item; list1[]) {
		writeln(item);
	}
}

/usr/include/dlang/dmd/std/container.d(1874): Error: no property 
'_first' for type 'ubyte'
/usr/include/dlang/dmd/std/container.d(1875): Error: no property 
'_first' for type 'ubyte'
/usr/include/dlang/dmd/std/container.d(1875): Error: undefined 
identifier rhs_, did you mean variable rhs?
source/app.d(7): Error: template instance 
std.container.DList!ubyte.DList.opOpAssign!("~", ubyte) error 
instantiating
source/app.d(7): Error: cannot append type ubyte to type 
DList!ubyte
Mar 31 2014
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 03/31/2014 10:32 PM, Jeroen Bollen wrote:
 Still no luck:

 import std.container;
 import std.stdio;

 void main()
 {
      DList!ubyte list1 = DList!ubyte();
      list1 ~= cast(ubyte) 1;
      list1 ~= cast(ubyte) 2;
      list1 ~= cast(ubyte) 3;

      foreach(ubyte item; list1[]) {
          writeln(item);
      }
 }

 /usr/include/dlang/dmd/std/container.d(1874): Error: no property
 '_first' for type 'ubyte'
 /usr/include/dlang/dmd/std/container.d(1875): Error: no property
 '_first' for type 'ubyte'
 /usr/include/dlang/dmd/std/container.d(1875): Error: undefined
 identifier rhs_, did you mean variable rhs?
 source/app.d(7): Error: template instance
 std.container.DList!ubyte.DList.opOpAssign!("~", ubyte) error instantiating
 source/app.d(7): Error: cannot append type ubyte to type DList!ubyte
I think your problem is fixed in a more recent compiler. The code works with git head dmd but fails with e.g. 2.064. (Not tested with 2.065.) Ali
Apr 01 2014
next sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Tuesday, 1 April 2014 at 10:56:40 UTC, Ali Çehreli wrote:
 On 03/31/2014 10:32 PM, Jeroen Bollen wrote:
 Still no luck:

 import std.container;
 import std.stdio;

 void main()
 {
     DList!ubyte list1 = DList!ubyte();
     list1 ~= cast(ubyte) 1;
     list1 ~= cast(ubyte) 2;
     list1 ~= cast(ubyte) 3;

     foreach(ubyte item; list1[]) {
         writeln(item);
     }
 }

 /usr/include/dlang/dmd/std/container.d(1874): Error: no 
 property
 '_first' for type 'ubyte'
 /usr/include/dlang/dmd/std/container.d(1875): Error: no 
 property
 '_first' for type 'ubyte'
 /usr/include/dlang/dmd/std/container.d(1875): Error: undefined
 identifier rhs_, did you mean variable rhs?
 source/app.d(7): Error: template instance
 std.container.DList!ubyte.DList.opOpAssign!("~", ubyte) error 
 instantiating
 source/app.d(7): Error: cannot append type ubyte to type 
 DList!ubyte
I think your problem is fixed in a more recent compiler. The code works with git head dmd but fails with e.g. 2.064. (Not tested with 2.065.) Ali
doesn't work on 2.065
Apr 01 2014
parent "bearophile" <bearophileHUGS lycos.com> writes:
John Colvin:

 doesn't work on 2.065
But it works in the latest alpha. Bye, bearophile
Apr 01 2014
prev sibling parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Tuesday, 1 April 2014 at 10:56:40 UTC, Ali Çehreli wrote:
 On 03/31/2014 10:32 PM, Jeroen Bollen wrote:
 Still no luck:

 import std.container;
 import std.stdio;

 void main()
 {
     DList!ubyte list1 = DList!ubyte();
     list1 ~= cast(ubyte) 1;
     list1 ~= cast(ubyte) 2;
     list1 ~= cast(ubyte) 3;

     foreach(ubyte item; list1[]) {
         writeln(item);
     }
 }

 /usr/include/dlang/dmd/std/container.d(1874): Error: no 
 property
 '_first' for type 'ubyte'
 /usr/include/dlang/dmd/std/container.d(1875): Error: no 
 property
 '_first' for type 'ubyte'
 /usr/include/dlang/dmd/std/container.d(1875): Error: undefined
 identifier rhs_, did you mean variable rhs?
 source/app.d(7): Error: template instance
 std.container.DList!ubyte.DList.opOpAssign!("~", ubyte) error 
 instantiating
 source/app.d(7): Error: cannot append type ubyte to type 
 DList!ubyte
I think your problem is fixed in a more recent compiler. The code works with git head dmd but fails with e.g. 2.064. (Not tested with 2.065.) Ali
I fixed this not too long ago. Long story short, the "~=" implementations were made of fail. Just change those "~=" for "insertBack" and you should be fine.
Apr 01 2014
parent reply "Meta" <jared771 gmail.com> writes:
On Tuesday, 1 April 2014 at 12:30:03 UTC, monarch_dodra wrote:
 I fixed this not too long ago. Long story short, the "~=" 
 implementations were made of fail.

 Just change those "~=" for "insertBack" and you should be fine.
That aside, why is it necessary to cast 1, 2 and 3 to ubyte when adding them to the DList? Is this a problem with DList or with D?
Apr 01 2014
next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 01 Apr 2014 09:30:18 -0400, Meta <jared771 gmail.com> wrote:

 On Tuesday, 1 April 2014 at 12:30:03 UTC, monarch_dodra wrote:
 I fixed this not too long ago. Long story short, the "~="  
 implementations were made of fail.

 Just change those "~=" for "insertBack" and you should be fine.
That aside, why is it necessary to cast 1, 2 and 3 to ubyte when adding them to the DList? Is this a problem with DList or with D?
A limitation with D. The issue is that IFTI interprets numeric literals as type int. There simply is no way to say "if you get a numeric literal that fits within a ubyte, use ubyte as the type for T" See this bug report: http://d.puremagic.com/issues/show_bug.cgi?id=4998 -Steve
Apr 01 2014
prev sibling parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Tuesday, 1 April 2014 at 13:30:21 UTC, Meta wrote:
 On Tuesday, 1 April 2014 at 12:30:03 UTC, monarch_dodra wrote:
 I fixed this not too long ago. Long story short, the "~=" 
 implementations were made of fail.

 Just change those "~=" for "insertBack" and you should be fine.
That aside, why is it necessary to cast 1, 2 and 3 to ubyte when adding them to the DList? Is this a problem with DList or with D?
D has a "feature", where you can't assign something big into something small. EG, you can't assign an int to a byte. This avoids dangerous overflow. That said, this is *usually* transparent, because D *also* has value range analysis. So what this means is that when you write: "ubyte b = 1;" Even though "1" is actually an int, the compiler knows it is int he 0-255 range, so the assignment is fine. In contrast, if you *pass* "1" to the DList, you lose that info, and the DList will complain that you are trying to assign an int to a ubyte. For what it's worth, 2.066 introduces uniform initialization, so this will become valid, and is somewhat less intrusive: list1.insertBack(ubyte(1)); list1.insertBack(ubyte(2)); list1.insertBack(ubyte(3));
Apr 01 2014
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Tuesday, 1 April 2014 at 13:54:00 UTC, monarch_dodra wrote:
 In contrast, if you *pass* "1" to the DList, you lose that 
 info, and the DList will complain that you are trying to assign 
 an int to a ubyte.
EDIT: The issue is actually one of template constraint, but it's essentially equivalent. Without context you can't assign an int to a ubyte.
Apr 01 2014
parent reply "Meta" <jared771 gmail.com> writes:
On Tuesday, 1 April 2014 at 13:55:05 UTC, monarch_dodra wrote:
 On Tuesday, 1 April 2014 at 13:54:00 UTC, monarch_dodra wrote:
 In contrast, if you *pass* "1" to the DList, you lose that 
 info, and the DList will complain that you are trying to 
 assign an int to a ubyte.
EDIT: The issue is actually one of template constraint, but it's essentially equivalent. Without context you can't assign an int to a ubyte.
I thought that maybe VRP might work here (as you detailed in your other post), as it works elsewhere. Is is possible to extend VRP to cover this situation?
Apr 01 2014
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Tuesday, 1 April 2014 at 15:16:41 UTC, Meta wrote:
 On Tuesday, 1 April 2014 at 13:55:05 UTC, monarch_dodra wrote:
 On Tuesday, 1 April 2014 at 13:54:00 UTC, monarch_dodra wrote:
 In contrast, if you *pass* "1" to the DList, you lose that 
 info, and the DList will complain that you are trying to 
 assign an int to a ubyte.
EDIT: The issue is actually one of template constraint, but it's essentially equivalent. Without context you can't assign an int to a ubyte.
I thought that maybe VRP might work here (as you detailed in your other post), as it works elsewhere. Is is possible to extend VRP to cover this situation?
*Maybe*, but it would require getting rid of the constraints. However, those template constraints are necessary to resolve the overloads to begin with ("insertBack(value)" vs "insertBack(range)"). So VRP wouldn't even get a chance to trigger :/
Apr 01 2014
parent "Jeroen Bollen" <jbinero gmail.com> writes:
Just for reference, this is the compiling code:

https://gist.github.com/Binero/f30e56351baf05f1a2ec
Apr 01 2014
prev sibling parent "Jeroen Bollen" <jbinero gmail.com> writes:
Still not working:

https://gist.github.com/Binero/f30e56351baf05f1a2ec
/usr/include/dlang/dmd/std/container.d(1925): Error: template 
std.container.DList!ubyte.DList.insertBeforeNode cannot deduce 
function from argument types !()(typeof(null), int), candidates 
are:
/usr/include/dlang/dmd/std/container.d(2096):        
std.container.DList!ubyte.DList.insertBeforeNode(Stuff)(Node* n, 
Stuff stuff) if (isInputRange!Stuff && 
isImplicitlyConvertible!(ElementType!Stuff, T))
/usr/include/dlang/dmd/std/container.d(2155):        
std.container.DList!ubyte.DList.insertBeforeNode(Stuff)(Node* n, 
Stuff stuff) if (isImplicitlyConvertible!(Stuff, T))
source/app.d(7): Error: template instance 
std.container.DList!ubyte.DList.insertBack!int error instantiating
source/app.d(11): Error: need upper and lower bound to slice 
pointer
Mar 31 2014
prev sibling next sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 03/31/2014 10:50 AM, Jeroen Bollen wrote:
 I am trying to foreach over a std.container.DList but it isn't working.
 I have tried the following code:
 https://gist.github.com/Binero/f30e56351baf05f1a2ec

 I am getting the following errors:

 /usr/include/dlang/dmd/std/container.d(1925): Error: template
 std.container.DList!ubyte.DList.insertBeforeNode cannot deduce function
 from argument types !()(typeof(null), int), candidates are:
 /usr/include/dlang/dmd/std/container.d(2096):
 std.container.DList!ubyte.DList.insertBeforeNode(Stuff)(Node* n, Stuff
 stuff) if (isInputRange!Stuff &&
 isImplicitlyConvertible!(ElementType!Stuff, T))
 /usr/include/dlang/dmd/std/container.d(2155):
 std.container.DList!ubyte.DList.insertBeforeNode(Stuff)(Node* n, Stuff
 stuff) if (isImplicitlyConvertible!(Stuff, T))
 source/app.d(7): Error: template instance
 std.container.DList!ubyte.DList.insertBack!int error instantiating
 source/app.d(11): Error: invalid foreach aggregate list1
Some notes: 1) DList is a struct. So, there is no need for 'new'. However, new is not an error but then the ~= syntax below cannot work on list1 without dereferencing. (You did not use ~=, I just liked it. :) ) (*list1) ~= cast(ubyte)3; // would work 2) For the same reason, list1[] becomes plain array slicing and the compiler is looking for "upper and lower bound to slice pointer". This would work: (*list1)[] 3) 1, 2, and 3 are ints. So, I had to cast them. import std.container; import std.stdio; void main() { auto list1 = DList!ubyte(); list1.insertBack(cast(ubyte)1); list1.insertBack(cast(ubyte)2); list1 ~= cast(ubyte)3; // alternative syntax foreach(ubyte item; list1[]) { writeln(item); } } Ali
Mar 31 2014
prev sibling parent Jos van Uden <usenet fwend.com> writes:
On 31-3-2014 19:50, Jeroen Bollen wrote:
 I am trying to foreach over a std.container.DList but it isn't working. I have
tried the following code: https://gist.github.com/Binero/f30e56351baf05f1a2ec

 I am getting the following errors:

 /usr/include/dlang/dmd/std/container.d(1925): Error: template
std.container.DList!ubyte.DList.insertBeforeNode cannot deduce function from
argument types !()(typeof(null), int), candidates are:
 /usr/include/dlang/dmd/std/container.d(2096):
std.container.DList!ubyte.DList.insertBeforeNode(Stuff)(Node* n, Stuff stuff)
if (isInputRange!Stuff && isImplicitlyConvertible!(ElementType!Stuff, T))
 /usr/include/dlang/dmd/std/container.d(2155):
std.container.DList!ubyte.DList.insertBeforeNode(Stuff)(Node* n, Stuff stuff)
if (isImplicitlyConvertible!(Stuff, T))
 source/app.d(7): Error: template instance
std.container.DList!ubyte.DList.insertBack!int error instantiating
 source/app.d(11): Error: invalid foreach aggregate list1
http://rosettacode.org/wiki/Strand_sort#D
Mar 31 2014