www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Linked list as a bidirectional range? I have some questions...

reply "Gary Willoughby" <dev nomad.so> writes:
Just for a bit a fun i've implemented a simple doubly linked list 
and trying out some range based stuff. Whilst doing so i have 
some questions which you guys might be able to answer.

1. In your opinion when accessing the elements of a linked list 
should they yield the data stored within the nodes or the entire 
nodes themselves? Different languages do this differently. For 


2. Suppose when accessing my linked list, it yields data and not 
nodes, how do iterate in reverse? I don't want to add unnecessary 
methods or properties.

3. How would you implement the 'save' method of a forward range 
in the context of a linked list? If my understanding is correct 
the 'saved' range is iterated and discard, so cannot use any 
references to the underlying range. This might also solve 
question 2.

[1]: 
http://msdn.microsoft.com/en-us/library/he2s3bh7(v=vs.110).aspx
[2]: 
http://docs.oracle.com/javase/7/docs/api/java/util/LinkedList.html
Aug 11 2014
parent reply "H. S. Teoh via Digitalmars-d-learn" <digitalmars-d-learn puremagic.com> writes:
On Mon, Aug 11, 2014 at 05:51:11PM +0000, Gary Willoughby via
Digitalmars-d-learn wrote:
 Just for a bit a fun i've implemented a simple doubly linked list and
 trying out some range based stuff. Whilst doing so i have some
 questions which you guys might be able to answer.
 
 1. In your opinion when accessing the elements of a linked list should
 they yield the data stored within the nodes or the entire nodes

 yields nodes[1], Java yields data[2].
 
 2. Suppose when accessing my linked list, it yields data and not
 nodes, how do iterate in reverse? I don't want to add unnecessary
 methods or properties.
 
 3. How would you implement the 'save' method of a forward range in the
 context of a linked list? If my understanding is correct the 'saved'
 range is iterated and discard, so cannot use any references to the
 underlying range. This might also solve question 2.
[...] IMO, it's a bad idea to conflate the container with the range over its contents. If you make your linked list container the same thing as a range over it, then iterating over the range will empty the container as well, which generally isn't what you want. It's much better to separate the container itself from ranges over the container. This then allows you to have separate container methods that return ranges of different types, for example: class LinkedList { ... // implementation here auto byNode() { return ... /* range over nodes */ } auto byData() { return ... /* range over data */ } } LinkedList l = ...; foreach (node; l.byNode()) { // you get nodes here } foreach (data; l.byData()) { // you get data items here } Which answers your original question: you can have it both ways. :-) Unfortunately, built-in arrays are a bad example for this, because it conflates the container (the slice) with the range. This tends to mislead people into thinking it's OK to conflate the container with a range over its contents. In general, you *don't* want to do this. Unless you're trying to simulate built-in arrays. T -- Recently, our IT department hired a bug-fix engineer. He used to work for Volkswagen.
Aug 11 2014
parent reply "Gary Willoughby" <dev nomad.so> writes:
On Monday, 11 August 2014 at 18:20:51 UTC, H. S. Teoh via 
Digitalmars-d-learn wrote:
 If you make your linked list container the same thing as a
 range over it, then iterating over the range will empty the 
 container as
 well, which generally isn't what you want.
Yes but only if it's been implemented purely as an input range. I was wondering if it was implemented as a forward range. Forward ranges allow iteration without destroying the contents. I was wondering how the 'save' method of the forward range could be implemented with a linked list. If my understanding is correct this method yields a copy to iterate over and discard.
 It's much better to separate the container itself from ranges 
 over the
 container. This then allows you to have separate container 
 methods that
 return ranges of different types.
That does answer it partially. This abstraction could return ranges over the nodes or items. but ultimately these have to expose the underlying data or provide a copy. (i.e. the 'save' method of forward ranges.) Also iterating in reverse (which should be possible with a doubly linked list) such ranges will have to be bidirectional ranges. These questions are all kind of inter-linked. I want to iterate forward and back through the list and if possible provide a nice public interface. It doesn't seem right to expose the nodes as that smells of a leaking abstraction. Hiding the nodes make it harder to iterate without a nice interface i.e. bidirectional range. Ranges are nice but the (forward range's) 'save' method needs careful consideration. opApply is nice but i can't see a way to overload it for reverse iteration.
Aug 11 2014
parent reply "H. S. Teoh via Digitalmars-d-learn" <digitalmars-d-learn puremagic.com> writes:
On Mon, Aug 11, 2014 at 07:35:04PM +0000, Gary Willoughby via
Digitalmars-d-learn wrote:
 On Monday, 11 August 2014 at 18:20:51 UTC, H. S. Teoh via
 Digitalmars-d-learn wrote:
If you make your linked list container the same thing as a range over
it, then iterating over the range will empty the container as well,
which generally isn't what you want.
Yes but only if it's been implemented purely as an input range. I was wondering if it was implemented as a forward range. Forward ranges allow iteration without destroying the contents. I was wondering how the 'save' method of the forward range could be implemented with a linked list. If my understanding is correct this method yields a copy to iterate over and discard.
Only if you explicitly call .save when you iterate over it. The following code does NOT preserve the original range: auto fwdRange = LinkedList(...); foreach (e; fwdRange) { ... } while the following does: auto fwdRange = LinkedList(...); foreach (e; fwdRange.save) { ... } which is uglier.
It's much better to separate the container itself from ranges over
the container. This then allows you to have separate container
methods that return ranges of different types.
That does answer it partially. This abstraction could return ranges over the nodes or items. but ultimately these have to expose the underlying data or provide a copy. (i.e. the 'save' method of forward ranges.)
I don't understand your objection here. You just implement your .front method to return the appropriate type. The dirty details of how iteration is implemented need not be exposed.
 Also iterating in reverse (which should be possible with a doubly
 linked list) such ranges will have to be bidirectional ranges.
You could do that, but it's not necessary. Nothing stops you from implementing, say, a byDataReverse() method that returns a forward range that just happens to return items from the original list in reverse order.
 These questions are all kind of inter-linked. I want to iterate
 forward and back through the list and if possible provide a nice
 public interface. It doesn't seem right to expose the nodes as that
 smells of a leaking abstraction. Hiding the nodes make it harder to
 iterate without a nice interface i.e. bidirectional range.
Your original question asked for a range that iterates over either data items or nodes, so what's the problem with "exposing the nodes"? If you didn't want the range to iterate over the nodes in the first place, then don't implement byNodes(), that's all.
 Ranges are nice but the (forward range's) 'save' method needs careful
 consideration.
All you have to do in .save is to return a copy of the range, which is *not* the same thing as a copy of the container. (Again, this shows that it's a bad idea to conflate the container with a range over its elements.)
 opApply is nice but i can't see a way to overload it for reverse
 iteration.
opApplyReverse. Anyway, clearly we're not understanding each other, so let me present some concrete code so that we aren't just talking past each other: // This is the container. It is NOT a range of any sort. class LinkedList(T) { private class Node { T data; Node next, prev; } Node head, tail; /** * Returns: A range over the data in the container in * forward order. */ auto byData() { // This is the range that the user will use to // iterate over the container's contents. struct Result { Node current; property ref T front() { // N.B.: no Node object is // exposed to the public, they // only see the data. return current.data; } property bool empty() { return current is null; } void popFront() { current = current.next; } property Result save() { // N.B.: no copying of data // needed; no container // duplication needed. return Result(current); } } static assert(isForwardRange!Result); return Result(head); } /** * Returns: A range over the data in the container in * reverse order. */ auto byDataReverse() { // Yes I know, most of this code is // copy-n-pasted from byData(); but the whole // point is to explain what I mean, not to write // the most polished code. Factoring out the // common parts is left as an exercise for the // reader. struct Result { Node current; property ref T front() { // N.B.: no Node object is // exposed to the public, they // only see the data. return current.data; } property bool empty() { return current is null; } void popFront() { current = current.prev; } property Result save() { // N.B.: no copying of data // needed; no container // duplication needed. return Result(current); } } static assert(isForwardRange!Result); return Result(tail); } // ... add whatever other methods you want for // manipulating the linked list. } T -- Trying to define yourself is like trying to bite your own teeth. -- Alan Watts
Aug 11 2014
next sibling parent reply "Gary Willoughby" <dev nomad.so> writes:
On Monday, 11 August 2014 at 20:02:38 UTC, H. S. Teoh via 
Digitalmars-d-learn wrote:
 On Mon, Aug 11, 2014 at 07:35:04PM +0000, Gary Willoughby via 
 Digitalmars-d-learn wrote:
 On Monday, 11 August 2014 at 18:20:51 UTC, H. S. Teoh via
 Digitalmars-d-learn wrote:
If you make your linked list container the same thing as a 
range over
it, then iterating over the range will empty the container as 
well,
which generally isn't what you want.
Yes but only if it's been implemented purely as an input range. I was wondering if it was implemented as a forward range. Forward ranges allow iteration without destroying the contents. I was wondering how the 'save' method of the forward range could be implemented with a linked list. If my understanding is correct this method yields a copy to iterate over and discard.
Only if you explicitly call .save when you iterate over it. The following code does NOT preserve the original range: auto fwdRange = LinkedList(...); foreach (e; fwdRange) { ... } while the following does: auto fwdRange = LinkedList(...); foreach (e; fwdRange.save) { ... } which is uglier.
It's much better to separate the container itself from ranges 
over
the container. This then allows you to have separate container
methods that return ranges of different types.
That does answer it partially. This abstraction could return ranges over the nodes or items. but ultimately these have to expose the underlying data or provide a copy. (i.e. the 'save' method of forward ranges.)
I don't understand your objection here. You just implement your .front method to return the appropriate type. The dirty details of how iteration is implemented need not be exposed.
 Also iterating in reverse (which should be possible with a 
 doubly
 linked list) such ranges will have to be bidirectional ranges.
You could do that, but it's not necessary. Nothing stops you from implementing, say, a byDataReverse() method that returns a forward range that just happens to return items from the original list in reverse order.
 These questions are all kind of inter-linked. I want to iterate
 forward and back through the list and if possible provide a 
 nice
 public interface. It doesn't seem right to expose the nodes as 
 that
 smells of a leaking abstraction. Hiding the nodes make it 
 harder to
 iterate without a nice interface i.e. bidirectional range.
Your original question asked for a range that iterates over either data items or nodes, so what's the problem with "exposing the nodes"? If you didn't want the range to iterate over the nodes in the first place, then don't implement byNodes(), that's all.
 Ranges are nice but the (forward range's) 'save' method needs 
 careful
 consideration.
All you have to do in .save is to return a copy of the range, which is *not* the same thing as a copy of the container. (Again, this shows that it's a bad idea to conflate the container with a range over its elements.)
 opApply is nice but i can't see a way to overload it for 
 reverse
 iteration.
opApplyReverse. Anyway, clearly we're not understanding each other, so let me present some concrete code so that we aren't just talking past each other: // This is the container. It is NOT a range of any sort. class LinkedList(T) { private class Node { T data; Node next, prev; } Node head, tail; /** * Returns: A range over the data in the container in * forward order. */ auto byData() { // This is the range that the user will use to // iterate over the container's contents. struct Result { Node current; property ref T front() { // N.B.: no Node object is // exposed to the public, they // only see the data. return current.data; } property bool empty() { return current is null; } void popFront() { current = current.next; } property Result save() { // N.B.: no copying of data // needed; no container // duplication needed. return Result(current); } } static assert(isForwardRange!Result); return Result(head); } /** * Returns: A range over the data in the container in * reverse order. */ auto byDataReverse() { // Yes I know, most of this code is // copy-n-pasted from byData(); but the whole // point is to explain what I mean, not to write // the most polished code. Factoring out the // common parts is left as an exercise for the // reader. struct Result { Node current; property ref T front() { // N.B.: no Node object is // exposed to the public, they // only see the data. return current.data; } property bool empty() { return current is null; } void popFront() { current = current.prev; } property Result save() { // N.B.: no copying of data // needed; no container // duplication needed. return Result(current); } } static assert(isForwardRange!Result); return Result(tail); } // ... add whatever other methods you want for // manipulating the linked list. } T
That..is..awesome! and much more simpler than i thought. I get it now, thanks. Is this pattern repeated in phobos?
Aug 11 2014
parent "H. S. Teoh via Digitalmars-d-learn" <digitalmars-d-learn puremagic.com> writes:
On Mon, Aug 11, 2014 at 08:22:11PM +0000, Gary Willoughby via
Digitalmars-d-learn wrote:
[...]
 That..is..awesome! and much more simpler than i thought. I get it now,
 thanks. Is this pattern repeated in phobos?
This is essentially what byKey and byValue of the built-in associative arrays do. :-) IIRC, std.container also uses a similar setup (albeit using opSlice() instead of byXXX(), but it's the same idea). T -- EMACS = Extremely Massive And Cumbersome System
Aug 11 2014
prev sibling next sibling parent reply "Gary Willoughby" <dev nomad.so> writes:
On Monday, 11 August 2014 at 20:02:38 UTC, H. S. Teoh via
Digitalmars-d-learn wrote:
 opApplyReverse.
Was that a joke or does opApplyReverse exist?
Aug 12 2014
parent reply ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Tue, 12 Aug 2014 16:50:33 +0000
Gary Willoughby via Digitalmars-d-learn
<digitalmars-d-learn puremagic.com> wrote:

 Was that a joke or does opApplyReverse exist?
it's not a joke. http://dlang.org/statement.html ctrl+f, opApplyReverse
Aug 12 2014
parent "Gary Willoughby" <dev nomad.so> writes:
On Tuesday, 12 August 2014 at 17:00:26 UTC, ketmar via
Digitalmars-d-learn wrote:
 On Tue, 12 Aug 2014 16:50:33 +0000
 Gary Willoughby via Digitalmars-d-learn
 <digitalmars-d-learn puremagic.com> wrote:

 Was that a joke or does opApplyReverse exist?
it's not a joke. http://dlang.org/statement.html ctrl+f, opApplyReverse
Ha, awesome!
Aug 12 2014
prev sibling parent reply "Gary Willoughby" <dev nomad.so> writes:
On Monday, 11 August 2014 at 20:02:38 UTC, H. S. Teoh via 
Digitalmars-d-learn wrote:
 Anyway, clearly we're not understanding each other, so let me 
 present
 some concrete code so that we aren't just talking past each 
 other:
I've used your advice and implemented a range over the list as suggested, the problem being i cannot get it to pass the isForwardRange check. Code: http://dpaste.dzfl.pl/cad89406bbcc#line-220 You'll notice the assert on line 220 fails. Any idea what i'm doing wrong?
Aug 13 2014
parent reply "H. S. Teoh via Digitalmars-d-learn" <digitalmars-d-learn puremagic.com> writes:
On Wed, Aug 13, 2014 at 06:31:32PM +0000, Gary Willoughby via
Digitalmars-d-learn wrote:
 On Monday, 11 August 2014 at 20:02:38 UTC, H. S. Teoh via
 Digitalmars-d-learn wrote:
Anyway, clearly we're not understanding each other, so let me present
some concrete code so that we aren't just talking past each other:
I've used your advice and implemented a range over the list as suggested, the problem being i cannot get it to pass the isForwardRange check. Code: http://dpaste.dzfl.pl/cad89406bbcc#line-220 You'll notice the assert on line 220 fails. Any idea what i'm doing wrong?
You need to put property on .save. T -- Valentine's Day: an occasion for florists to reach into the wallets of nominal lovers in dire need of being reminded to profess their hypothetical love for their long-forgotten.
Aug 13 2014
next sibling parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Wednesday, 13 August 2014 at 18:58:59 UTC, H. S. Teoh via 
Digitalmars-d-learn wrote:
 On Wed, Aug 13, 2014 at 06:31:32PM +0000, Gary Willoughby via 
 Digitalmars-d-learn wrote:
 On Monday, 11 August 2014 at 20:02:38 UTC, H. S. Teoh via
 Digitalmars-d-learn wrote:
Anyway, clearly we're not understanding each other, so let me 
present
some concrete code so that we aren't just talking past each 
other:
I've used your advice and implemented a range over the list as suggested, the problem being i cannot get it to pass the isForwardRange check. Code: http://dpaste.dzfl.pl/cad89406bbcc#line-220 You'll notice the assert on line 220 fails. Any idea what i'm doing wrong?
You need to put property on .save.
Hmm... struct Result { public property auto save1() { return this; } public auto save2() { return this; } } pragma(msg, typeof(Result.init.save1)); pragma(msg, typeof(Result.init.save2)); This outputs: Result Result() `Result()` looks bogus.
Aug 13 2014
parent reply "H. S. Teoh via Digitalmars-d-learn" <digitalmars-d-learn puremagic.com> writes:
On Wed, Aug 13, 2014 at 07:23:30PM +0000, via Digitalmars-d-learn wrote:
 On Wednesday, 13 August 2014 at 18:58:59 UTC, H. S. Teoh via
 Digitalmars-d-learn wrote:
On Wed, Aug 13, 2014 at 06:31:32PM +0000, Gary Willoughby via
Digitalmars-d-learn wrote:
[...]
I've used your advice and implemented a range over the list as
suggested, the problem being i cannot get it to pass the
isForwardRange check.

Code: http://dpaste.dzfl.pl/cad89406bbcc#line-220

You'll notice the assert on line 220 fails. Any idea what i'm doing
wrong?
You need to put property on .save.
Hmm... struct Result { public property auto save1() { return this; } public auto save2() { return this; } } pragma(msg, typeof(Result.init.save1)); pragma(msg, typeof(Result.init.save2)); This outputs: Result Result() `Result()` looks bogus.
File a bug. :-) https://issues.dlang.org/enter_bug.cgi T -- What is Matter, what is Mind? Never Mind, it doesn't Matter.
Aug 13 2014
parent "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Wednesday, 13 August 2014 at 19:30:53 UTC, H. S. Teoh via 
Digitalmars-d-learn wrote:
 On Wed, Aug 13, 2014 at 07:23:30PM +0000, via 
 Digitalmars-d-learn wrote:
 On Wednesday, 13 August 2014 at 18:58:59 UTC, H. S. Teoh via
 Digitalmars-d-learn wrote:
On Wed, Aug 13, 2014 at 06:31:32PM +0000, Gary Willoughby via
Digitalmars-d-learn wrote:
[...]
I've used your advice and implemented a range over the list 
as
suggested, the problem being i cannot get it to pass the
isForwardRange check.

Code: http://dpaste.dzfl.pl/cad89406bbcc#line-220

You'll notice the assert on line 220 fails. Any idea what 
i'm doing
wrong?
You need to put property on .save.
Hmm... struct Result { public property auto save1() { return this; } public auto save2() { return this; } } pragma(msg, typeof(Result.init.save1)); pragma(msg, typeof(Result.init.save2)); This outputs: Result Result() `Result()` looks bogus.
File a bug. :-) https://issues.dlang.org/enter_bug.cgi
https://issues.dlang.org/show_bug.cgi?id=13293 And I see that Vladimir already reported a bug about the original problem: https://issues.dlang.org/show_bug.cgi?id=11761
Aug 14 2014
prev sibling parent reply "Gary Willoughby" <dev nomad.so> writes:
On Wednesday, 13 August 2014 at 18:58:59 UTC, H. S. Teoh via 
Digitalmars-d-learn wrote:
 On Wed, Aug 13, 2014 at 06:31:32PM +0000, Gary Willoughby via 
 Digitalmars-d-learn wrote:
 On Monday, 11 August 2014 at 20:02:38 UTC, H. S. Teoh via
 Digitalmars-d-learn wrote:
Anyway, clearly we're not understanding each other, so let me 
present
some concrete code so that we aren't just talking past each 
other:
I've used your advice and implemented a range over the list as suggested, the problem being i cannot get it to pass the isForwardRange check. Code: http://dpaste.dzfl.pl/cad89406bbcc#line-220 You'll notice the assert on line 220 fails. Any idea what i'm doing wrong?
You need to put property on .save. T
Gah! Thanks, i need sleep. :)
Aug 13 2014
parent reply "H. S. Teoh via Digitalmars-d-learn" <digitalmars-d-learn puremagic.com> writes:
On Wed, Aug 13, 2014 at 07:37:09PM +0000, Gary Willoughby via
Digitalmars-d-learn wrote:
 On Wednesday, 13 August 2014 at 18:58:59 UTC, H. S. Teoh via
 Digitalmars-d-learn wrote:
On Wed, Aug 13, 2014 at 06:31:32PM +0000, Gary Willoughby via
Digitalmars-d-learn wrote:
[...]
I've used your advice and implemented a range over the list as
suggested, the problem being i cannot get it to pass the
isForwardRange check.

Code: http://dpaste.dzfl.pl/cad89406bbcc#line-220

You'll notice the assert on line 220 fails. Any idea what i'm doing
wrong?
You need to put property on .save. T
Gah! Thanks, i need sleep. :)
No worries, the only reason I could pinpoint this almost immediately was because I got bitten by exactly the same problem before, and it took me *hours* to figure out what was wrong. :-/ T -- Never ascribe to malice that which is adequately explained by incompetence. -- Napoleon Bonaparte
Aug 13 2014
parent reply "Gary Willoughby" <dev nomad.so> writes:
On Wednesday, 13 August 2014 at 19:43:20 UTC, H. S. Teoh via 
Digitalmars-d-learn wrote:
 On Wed, Aug 13, 2014 at 07:37:09PM +0000, Gary Willoughby via 
 Digitalmars-d-learn wrote:
 On Wednesday, 13 August 2014 at 18:58:59 UTC, H. S. Teoh via
 Digitalmars-d-learn wrote:
On Wed, Aug 13, 2014 at 06:31:32PM +0000, Gary Willoughby via
Digitalmars-d-learn wrote:
[...]
I've used your advice and implemented a range over the list 
as
suggested, the problem being i cannot get it to pass the
isForwardRange check.

Code: http://dpaste.dzfl.pl/cad89406bbcc#line-220

You'll notice the assert on line 220 fails. Any idea what 
i'm doing
wrong?
You need to put property on .save. T
Gah! Thanks, i need sleep. :)
No worries, the only reason I could pinpoint this almost immediately was because I got bitten by exactly the same problem before, and it took me *hours* to figure out what was wrong. :-/ T
Thinking about it why should that matter when not compiled using -property? I'm guessing the template enforces it should be a property?
Aug 13 2014
parent reply "H. S. Teoh via Digitalmars-d-learn" <digitalmars-d-learn puremagic.com> writes:
On Wed, Aug 13, 2014 at 07:58:49PM +0000, Gary Willoughby via
Digitalmars-d-learn wrote:
 On Wednesday, 13 August 2014 at 19:43:20 UTC, H. S. Teoh via
 Digitalmars-d-learn wrote:
On Wed, Aug 13, 2014 at 07:37:09PM +0000, Gary Willoughby via
Digitalmars-d-learn wrote:
On Wednesday, 13 August 2014 at 18:58:59 UTC, H. S. Teoh via
Digitalmars-d-learn wrote:
[...]
You need to put  property on .save.
[...]
Gah! Thanks, i need sleep. :)
No worries, the only reason I could pinpoint this almost immediately was because I got bitten by exactly the same problem before, and it took me *hours* to figure out what was wrong. :-/ T
Thinking about it why should that matter when not compiled using -property? I'm guessing the template enforces it should be a property?
The problem is that this test is used in isForwardRange: static assert (is(typeof(r1.save) == R)); where R is the type of the range. So if .save is not property, then typeof(r1.save) would be a function pointer, rather than the type of the function's return value, and so the test will fail. T -- What do you mean the Internet isn't filled with subliminal messages? What about all those buttons marked "submit"??
Aug 13 2014
parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Wednesday, 13 August 2014 at 20:27:29 UTC, H. S. Teoh via 
Digitalmars-d-learn wrote:
 On Wed, Aug 13, 2014 at 07:58:49PM +0000, Gary Willoughby via 
 Digitalmars-d-learn wrote:
 On Wednesday, 13 August 2014 at 19:43:20 UTC, H. S. Teoh via
 Digitalmars-d-learn wrote:
On Wed, Aug 13, 2014 at 07:37:09PM +0000, Gary Willoughby via
Digitalmars-d-learn wrote:
On Wednesday, 13 August 2014 at 18:58:59 UTC, H. S. Teoh via
Digitalmars-d-learn wrote:
[...]
You need to put  property on .save.
[...]
Gah! Thanks, i need sleep. :)
No worries, the only reason I could pinpoint this almost immediately was because I got bitten by exactly the same problem before, and it took me *hours* to figure out what was wrong. :-/ T
Thinking about it why should that matter when not compiled using -property? I'm guessing the template enforces it should be a property?
The problem is that this test is used in isForwardRange: static assert (is(typeof(r1.save) == R)); where R is the type of the range. So if .save is not property, then typeof(r1.save) would be a function pointer, rather than the type of the function's return value, and so the test will fail.
But wouldn't an & be needed to get a function pointer?
Aug 13 2014
parent "H. S. Teoh via Digitalmars-d-learn" <digitalmars-d-learn puremagic.com> writes:
On Wed, Aug 13, 2014 at 08:52:32PM +0000, via Digitalmars-d-learn wrote:
 On Wednesday, 13 August 2014 at 20:27:29 UTC, H. S. Teoh via
 Digitalmars-d-learn wrote:
On Wed, Aug 13, 2014 at 07:58:49PM +0000, Gary Willoughby via
Digitalmars-d-learn wrote:
On Wednesday, 13 August 2014 at 19:43:20 UTC, H. S. Teoh via
Digitalmars-d-learn wrote:
On Wed, Aug 13, 2014 at 07:37:09PM +0000, Gary Willoughby via
Digitalmars-d-learn wrote:
On Wednesday, 13 August 2014 at 18:58:59 UTC, H. S. Teoh via
Digitalmars-d-learn wrote:
[...]
You need to put  property on .save.
[...]
Gah! Thanks, i need sleep. :)
No worries, the only reason I could pinpoint this almost >immediately
was
because I got bitten by exactly the same problem before, and >it took
me
*hours* to figure out what was wrong. :-/


T
Thinking about it why should that matter when not compiled using -property? I'm guessing the template enforces it should be a property?
The problem is that this test is used in isForwardRange: static assert (is(typeof(r1.save) == R)); where R is the type of the range. So if .save is not property, then typeof(r1.save) would be a function pointer, rather than the type of the function's return value, and so the test will fail.
But wouldn't an & be needed to get a function pointer?
Sorry, my bad. It's just a function, not a function pointer. The type of a function is not the same as the type of its return value (obviously). T -- Study gravitation, it's a field with a lot of potential.
Aug 13 2014