digitalmars.D.learn - Why after writeln the binaryHeap become empty?
- lili (10/10) Jun 18 2019 Hi Guys:
- Johannes Loher (22/32) Jun 18 2019 The result of heapify is a BinaryHeap, which is a range. writeln
- lili (3/16) Jun 18 2019 Do you known reason for why Dlang Range are consumed by iterating
- Jonathan M Davis (7/24) Jun 18 2019 If you want an overview of ranges, you can watch this:
- Mike Parker (4/13) Jun 18 2019 And this excerpt from Learning D:
- Jonathan M Davis (15/25) Jun 18 2019 Looking at std/container/binaryheap.d, heapify returns the type BinaryHe...
Hi Guys: see this code ~~~ int[] ar = [1,2,3,4,52,34,22]; auto h = heapify(ar); assert(h.length() == ar.length); writeln("h:",h); assert(h.empty()); ~~~ dmd v2.086.0 run all assert passed. Why?
Jun 18 2019
Am 18.06.19 um 17:45 schrieb lili:Hi Guys: see this code ~~~ int[] ar = [1,2,3,4,52,34,22]; auto h = heapify(ar); assert(h.length() == ar.length); writeln("h:",h); assert(h.empty()); ~~~ dmd v2.086.0 run all assert passed. Why?The result of heapify is a BinaryHeap, which is a range. writeln basically prints ranges by iterating over them and printing each element (except for the types which are special cased, such as dynamic arrays etc.). However, ranges are consumed by iterating over them, which explains the behavior because writeln is not special cased for BinaryHeaps. In order to avoid this, you can make a copy of the BinaryHeap before printing it: ``` import std; void main() { int[] ar = [1, 2, 3, 4, 52, 34, 22]; auto h = heapify(ar); assert(h.length() == ar.length); writeln("h:", h.dup); assert(!h.empty()); } ``` Funnily enough, BinaryHeap does not implement a "save" method, which is the usual way of making ranges copiable, i.e. making them ForwardRanges. In this case I believe save could even simply be an alias to dup.
Jun 18 2019
On Tuesday, 18 June 2019 at 17:25:51 UTC, Johannes Loher wrote:The result of heapify is a BinaryHeap, which is a range. writeln basically prints ranges by iterating over them and printing each element (except for the types which are special cased, such as dynamic arrays etc.). However, ranges are consumed by iterating over them, which explains the behavior because writeln is not special cased for BinaryHeaps. Funnily enough, BinaryHeap does not implement a "save" method, which is the usual way of making ranges copiable, i.e. making them ForwardRanges. In this case I believe save could even simply be an alias to dup.Do you known reason for why Dlang Range are consumed by iterating over them. I this design is strange.
Jun 18 2019
On Tuesday, June 18, 2019 10:27:46 PM MDT lili via Digitalmars-d-learn wrote:On Tuesday, 18 June 2019 at 17:25:51 UTC, Johannes Loher wrote:If you want an overview of ranges, you can watch this: https://www.youtube.com/watch?v=A8Btr8TPJ8c You can also read this: http://ddili.org/ders/d.en/ranges.html - Jonathan M DavisThe result of heapify is a BinaryHeap, which is a range. writeln basically prints ranges by iterating over them and printing each element (except for the types which are special cased, such as dynamic arrays etc.). However, ranges are consumed by iterating over them, which explains the behavior because writeln is not special cased for BinaryHeaps. Funnily enough, BinaryHeap does not implement a "save" method, which is the usual way of making ranges copiable, i.e. making them ForwardRanges. In this case I believe save could even simply be an alias to dup.Do you known reason for why Dlang Range are consumed by iterating over them. I this design is strange.
Jun 18 2019
On Wednesday, 19 June 2019 at 06:00:28 UTC, Jonathan M Davis wrote:On Tuesday, June 18, 2019 10:27:46 PM MDT lili viaAnd this excerpt from Learning D: https://hub.packtpub.com/understanding-ranges/Do you known reason for why Dlang Range are consumed by iterating over them. I this design is strange.If you want an overview of ranges, you can watch this: https://www.youtube.com/watch?v=A8Btr8TPJ8c You can also read this: http://ddili.org/ders/d.en/ranges.html - Jonathan M Davis
Jun 18 2019
On Tuesday, June 18, 2019 9:45:33 AM MDT lili via Digitalmars-d-learn wrote:Hi Guys: see this code ~~~ int[] ar = [1,2,3,4,52,34,22]; auto h = heapify(ar); assert(h.length() == ar.length); writeln("h:",h); assert(h.empty()); ~~~ dmd v2.086.0 run all assert passed. Why?Looking at std/container/binaryheap.d, heapify returns the type BinaryHeap which provides the API for an input range but no toString. As such, writeln likely uses the range API to read the elements and print them. And that's going to pop all of the elements off in the process. In general, if you pass a range to something and you don't want it to be consumed, then you need to call save on it so that you pass a copy (for many ranges, copying them is equivalent to calling save on them, but that's not part of the range API, and it's not true for all ranges). However, from the looks of it, the BinaryHeap is a just a basic input range, not a forward range, so it doesn't have save. That means that reading it will always consume it. Looking over BinaryHeap, I don't think that it's actually possible to iterate through its elements without removing them from the BinaryHeap. As such, you can't print them without removing them from the BinaryHeap. - Jonathan M Davis
Jun 18 2019