digitalmars.D.learn - Ranges
- pascal111 (48/48) Aug 04 2022 In next code from
- Salih Dincer (2/42) Aug 04 2022 😀
- frame (11/17) Aug 04 2022 - These functions are wrappers to use something as range
- =?UTF-8?Q?Ali_=c3=87ehreli?= (20/24) Aug 04 2022 The function was this:
- pascal111 (3/28) Aug 04 2022 I didn't notice that all what we needs to pop a range forward is
- Salih Dincer (5/7) Aug 04 2022 Ranges and Slices are not the same thing. Slicing an array is
- pascal111 (5/13) Aug 06 2022 What!!! so where's ranges?! I thought slices of any array are
- H. S. Teoh (11/26) Aug 06 2022 A range is any type that supports the Range API defined in std.range
- pascal111 (5/30) Aug 06 2022 You know, the problem is that ranges in D lack the usage of
- =?UTF-8?Q?Ali_=c3=87ehreli?= (13/17) Aug 06 2022 There are a few cases where pointers provide functionality that ranges
- pascal111 (6/9) Aug 07 2022 Everyone knows that slices are not pointers that pointers are
- Salih Dincer (4/21) Aug 07 2022 **Source:** https://tour.dlang.org/tour/en/basics/slices
- ag0aep6g (2/7) Aug 07 2022 I can't tell if this is a joke or not.
- pascal111 (2/9) Aug 07 2022 It's just an opinion.
- =?UTF-8?Q?Ali_=c3=87ehreli?= (11/18) Aug 07 2022 D's slices are "fat pointers": In D's case, that translates to a pointer...
- pascal111 (4/14) Aug 07 2022 I think you are right that this is an old thought, I didn't
- Salih Dincer (5/20) Aug 06 2022 Well, that's very normal. Because as you work with ranges, you
- Salih Dincer (4/6) Aug 06 2022 Edit: Indeed, the slices feel like ranges, don't they?
- =?UTF-8?Q?Ali_=c3=87ehreli?= (17/18) Aug 06 2022 Yes because they are ranges. :) (Maybe you meant they don't have range
- Salih Dincer (6/10) Aug 06 2022 Slices use pointers. Do I need to tell you what the pointers do!
- =?UTF-8?Q?Ali_=c3=87ehreli?= (8/10) Aug 07 2022 You may be right. I've never seen it that way.
- Emanuele Torre (143/158) Aug 07 2022 A range is like an iterator in any other language (Java, C++,
- frame (5/7) Aug 05 2022 I know that :) I just found that this user has problems to
- =?UTF-8?Q?Ali_=c3=87ehreli?= (12/17) Aug 05 2022 And I know that. :) We don't know who else is reading these threads, so
- H. S. Teoh (13/23) Aug 05 2022 [...]
- =?UTF-8?Q?Ali_=c3=87ehreli?= (26/45) Aug 04 2022 That page seems to be adapted from this original:
In next code from "https://www.tutorialspoint.com/d_programming/d_programming_ranges.htm", we have two issues: 1) Why the programmer needs to program "empty()", "front()", and "popFront()" functions for ranges while they exist in the language library? it seems there's no need to exert efforts for that. "https://dlang.org/phobos/std_range_primitives.html" 2) "front()", and "popFront()" are using fixed constants to move forward the range, while they should use variables. '''D import std.stdio; import std.string; struct Student { string name; int number; string toString() const { return format("%s(%s)", name, number); } } struct School { Student[] students; } struct StudentRange { Student[] students; this(School school) { this.students = school.students; } property bool empty() const { return students.length == 0; } property ref Student front() { return students[0]; } void popFront() { students = students[1 .. $]; } } void main() { auto school = School([ Student("Raj", 1), Student("John", 2), Student("Ram", 3)]); auto range = StudentRange(school); writeln(range); writeln(school.students.length); writeln(range.front); range.popFront; writeln(range.empty); writeln(range); } '''
Aug 04 2022
On Thursday, 4 August 2022 at 13:08:21 UTC, pascal111 wrote:```D import std.stdio; import std.string; struct Student { string name; int number; string toString() const { return format("%s(%s)", name, number); } } struct School { Student[] students; } struct StudentRange { Student[] students; this(School school) { this.students = school.students; } property bool empty() const { return students.length == 0; } property ref Student front() { return students[0]; } void popFront() { students = students[1 .. $]; } } void main() { auto school = School([ Student("Raj", 1), Student("John", 2), Student("Ram", 3)]); auto range = StudentRange(school); writeln(range); writeln(school.students.length); writeln(range.front); range.popFront; writeln(range.empty); writeln(range); } ```😀
Aug 04 2022
On Thursday, 4 August 2022 at 13:08:21 UTC, pascal111 wrote:1) Why the programmer needs to program "empty()", "front()", and "popFront()" functions for ranges while they exist in the language library? it seems there's no need to exert efforts for that. "https://dlang.org/phobos/std_range_primitives.html"- These functions are wrappers to use something as range - Ranges need to implement the functions to keep their data private, also there are complex types the need to handle data differently - Ranges must implement the functions so other function can recognize it as such (eg. `isInputRange`) - there is no common interface, it's determined by compile time2) "front()", and "popFront()" are using fixed constants to move forward the range, while they should use variables.`front()` is always using the first element BUT `popFront()` copies all elements except the first one into the variable (and overwrites it), so it moves the data forward.
Aug 04 2022
On 8/4/22 11:05, frame wrote:`popFront()`The function was this: void popFront() { students = students[1 .. $]; }copies all elements except the first one into the variable (and overwrites it), so it moves the data forward.That would be very slow. :) What actually happens is, just the two variables that define a slice is adjusted. Slices consist of two members: struct __an_int_D_array_behind_the_scenes { size_t length; int * ptr; } So, students = students[1..$]; is the same as doing the following: students.length = (students.length - 1); students.ptr = students.ptr + 1; (ptr's value would change by 4 bytes because 'int'.) No element is copied or moved. :) Ali
Aug 04 2022
On Thursday, 4 August 2022 at 22:14:26 UTC, Ali Çehreli wrote:On 8/4/22 11:05, frame wrote:I didn't notice that all what we needs to pop a range forward is just a slice, yes, we don't need variable here.`popFront()`The function was this: void popFront() { students = students[1 .. $]; }copies all elements except the first one into the variable (andoverwrites it), soit moves the data forward.That would be very slow. :) What actually happens is, just the two variables that define a slice is adjusted. Slices consist of two members: struct __an_int_D_array_behind_the_scenes { size_t length; int * ptr; } So, students = students[1..$]; is the same as doing the following: students.length = (students.length - 1); students.ptr = students.ptr + 1; (ptr's value would change by 4 bytes because 'int'.) No element is copied or moved. :) Ali
Aug 04 2022
On Thursday, 4 August 2022 at 22:54:42 UTC, pascal111 wrote:I didn't notice that all what we needs to pop a range forward is just a slice, yes, we don't need variable here.Ranges and Slices are not the same thing. Slicing an array is easy. This is a language possibility. For example, you need an incrementing variable for the Fibonacci Series. SDB 79
Aug 04 2022
On Friday, 5 August 2022 at 04:05:08 UTC, Salih Dincer wrote:On Thursday, 4 August 2022 at 22:54:42 UTC, pascal111 wrote:What!!! so where's ranges?! I thought slices of any array are ranges, and understood it like that, and also there's no data type called ranges, it's like if you are talking about Ghostly data type!I didn't notice that all what we needs to pop a range forward is just a slice, yes, we don't need variable here.Ranges and Slices are not the same thing. Slicing an array is easy. This is a language possibility. For example, you need an incrementing variable for the Fibonacci Series. SDB 79
Aug 06 2022
On Sat, Aug 06, 2022 at 03:37:32PM +0000, pascal111 via Digitalmars-d-learn wrote:On Friday, 5 August 2022 at 04:05:08 UTC, Salih Dincer wrote:A range is any type that supports the Range API defined in std.range (i.e., .empty, .front, .popFront). For more explanations, read: http://www.informit.com/articles/printerfriendly.aspx?p=1407357&rll=1 http://ddili.org/ders/d.en/ranges.html http://dconf.org/2015/talks/davis.html http://tour.dlang.org/tour/en/basics/ranges http://wiki.dlang.org/Component_programming_with_ranges T -- No! I'm not in denial!On Thursday, 4 August 2022 at 22:54:42 UTC, pascal111 wrote:What!!! so where's ranges?! I thought slices of any array are ranges, and understood it like that, and also there's no data type called ranges, it's like if you are talking about Ghostly data type!I didn't notice that all what we needs to pop a range forward is just a slice, yes, we don't need variable here.Ranges and Slices are not the same thing. Slicing an array is easy. This is a language possibility. For example, you need an incrementing variable for the Fibonacci Series. SDB 79
Aug 06 2022
On Saturday, 6 August 2022 at 15:54:57 UTC, H. S. Teoh wrote:On Sat, Aug 06, 2022 at 03:37:32PM +0000, pascal111 via Digitalmars-d-learn wrote:You know, the problem is that ranges in D lack the usage of pointers as an essential tool to make all of ranges functions they need. If ranges exist in C, they would use pointers, and this is a powerful point in the account of C.On Friday, 5 August 2022 at 04:05:08 UTC, Salih Dincer wrote:A range is any type that supports the Range API defined in std.range (i.e., .empty, .front, .popFront). For more explanations, read: http://www.informit.com/articles/printerfriendly.aspx?p=1407357&rll=1 http://ddili.org/ders/d.en/ranges.html http://dconf.org/2015/talks/davis.html http://tour.dlang.org/tour/en/basics/ranges http://wiki.dlang.org/Component_programming_with_ranges TOn Thursday, 4 August 2022 at 22:54:42 UTC, pascal111 wrote:What!!! so where's ranges?! I thought slices of any array are ranges, and understood it like that, and also there's no data type called ranges, it's like if you are talking about Ghostly data type![...]Ranges and Slices are not the same thing. Slicing an array is easy. This is a language possibility. For example, you need an incrementing variable for the Fibonacci Series. SDB 79
Aug 06 2022
On 8/6/22 14:10, pascal111 wrote:the problem is that ranges in D lack the usage of pointers as an essential tool to make all of ranges functions they need. If ranges exist in C, they would use pointers, and this isThere are a few cases where pointers provide functionality that ranges cannot: 1) Some algorithms don't make much sense with ranges. For example, most of the time find() can return just the element that we seek. In D, find() returns a range so that we can chain it with other algorithms. 2) Some algorithms like partition() better use three pointers. Other than that, ranges are superior to pointers in every aspect. (I resent the fact that some C++ "experts" used those two points to decide ranges are inferior and helped deprive the C++ community of ranges for a very long time. The same "experts" did the same with 'static if'.)a powerful point in the account of C.I missed how you made that connection. Ali
Aug 06 2022
On Sunday, 7 August 2022 at 05:12:38 UTC, Ali Çehreli wrote:On 8/6/22 14:10, pascal111 wrote:Everyone knows that slices are not pointers that pointers are real work, but slices are like a simple un-deep technique that is appropriate for beginners, but after that in advanced level in programming, we should use pointers to do same tasks we were doing with slices (the easy way of beginners).a powerful point in the account of C.I missed how you made that connection.
Aug 07 2022
On Sunday, 7 August 2022 at 15:34:19 UTC, pascal111 wrote:Everyone knows that slices are not pointers that pointers are real work, but slices are like a simple un-deep technique that is appropriate for beginners, but after that in advanced level in programming, we should use pointers to do same tasks we were doing with slices (the easy way of beginners).The following information about slices may be helpful:Slices are objects from type T[] for any given type T. Slices provide a view on a subset of an array of T values - or just point to the whole array. Slices and dynamic arrays are the same. A slice consists of two members - a pointer to the starting element and the length of the slice: ```d T* ptr; size_t length; // unsigned 32 bit on 32bit, unsigned 64 bit on 64bit ``` [...]**Source:** https://tour.dlang.org/tour/en/basics/slices SDB 79
Aug 07 2022
On Sunday, 7 August 2022 at 15:34:19 UTC, pascal111 wrote:Everyone knows that slices are not pointers that pointers are real work, but slices are like a simple un-deep technique that is appropriate for beginners, but after that in advanced level in programming, we should use pointers to do same tasks we were doing with slices (the easy way of beginners).I can't tell if this is a joke or not.
Aug 07 2022
On Sunday, 7 August 2022 at 19:53:06 UTC, ag0aep6g wrote:On Sunday, 7 August 2022 at 15:34:19 UTC, pascal111 wrote:It's just an opinion.Everyone knows that slices are not pointers that pointers are real work, but slices are like a simple un-deep technique that is appropriate for beginners, but after that in advanced level in programming, we should use pointers to do same tasks we were doing with slices (the easy way of beginners).I can't tell if this is a joke or not.
Aug 07 2022
On 8/7/22 08:34, pascal111 wrote:Everyone knows that slices are not pointersD's slices are "fat pointers": In D's case, that translates to a pointer plus length.that pointers are real work,Agreed. Pointers are fundamental features of CPUs.but slices are like a simple un-deep technique that is appropriate for beginners,That is not correct. Slices are designed by a C expert to prevent horrible bugs caused by C experts. Most C experts use slices very happily.but after that in advanced level in programming, we should use pointers to do same tasks we were doing with slices (the easy way of beginners).That is an old thought. Today, we see that no matter how experienced, every person needs and appreciates help to prevent bugs. There are many cases of bugs killing people, jeopardizing expensive projects, loss of personal information, etc. Ali
Aug 07 2022
On Sunday, 7 August 2022 at 21:57:50 UTC, Ali Çehreli wrote:On 8/7/22 08:34, pascal111 wrote:I think you are right that this is an old thought, I didn't noticed that, maybe it's because I didn't study C++ and know only about C, so I applied C features on D.but after that in advanced level in programming, we should use pointers to do same tasks we were doing with slices (theeasy way ofbeginners).That is an old thought. Today, we see that no matter how experienced, every person needs and appreciates help to prevent bugs. There are many cases of bugs killing people, jeopardizing expensive projects, loss of personal information, etc. Ali
Aug 07 2022
On Saturday, 6 August 2022 at 15:37:32 UTC, pascal111 wrote:On Friday, 5 August 2022 at 04:05:08 UTC, Salih Dincer wrote:Well, that's very normal. Because as you work with ranges, you will understand better. Indeed, the slices (we can call it a dynamic array) feel like slice, don't they? SDB 79On Thursday, 4 August 2022 at 22:54:42 UTC, pascal111 wrote:What!!! so where's ranges?! I thought slices of any array are ranges, and understood it like that, and also there's no data type called ranges, it's like if you are talking about Ghostly data type!I didn't notice that all what we needs to pop a range forward is just a slice, yes, we don't need variable here.Ranges and Slices are not the same thing. Slicing an array is easy. This is a language possibility. For example, you need an incrementing variable for the Fibonacci Series. SDB 79
Aug 06 2022
On Saturday, 6 August 2022 at 16:30:55 UTC, Salih Dincer wrote:Indeed, the slices (we can call it a dynamic array) feel like slice, don't they?Edit: Indeed, the slices feel like ranges, don't they? Sorry... SDB 79
Aug 06 2022
On 8/6/22 09:33, Salih Dincer wrote:the slices feel like ranges, don't they?Yes because they are ranges. :) (Maybe you meant they don't have range member functions, which is true.) D's slices happen to be the most capable range kind: RandonAccessRange. All of the following operations are supported on them as long as one imports std.array (or std.range, which publicly does so): - empty - front - popFront - save - back - popBack - indexed element access Slices have the optional length property as well (i.e. hasLength). Those operations are not supported by member functions but by free-standing functions. Ali
Aug 06 2022
On Saturday, 6 August 2022 at 17:29:30 UTC, Ali Çehreli wrote:On 8/6/22 09:33, Salih Dincer wrote:Slices use pointers. Do I need to tell you what the pointers do! Each of them points to a data. Ranges are not like that, all they do is generate. Ok, you use a slice just as if it were a range. But they are not ranges. SDB 79the slices feel like ranges, don't they?Yes because they are ranges. :) (Maybe you meant they don't have range member functions, which is true.)
Aug 06 2022
On 8/6/22 22:58, Salih Dincer wrote:Ranges are not like that, all they do is generate.You may be right. I've never seen it that way. I've been under the following impression: - C++'s iterators are based on an existing concept: pointers. Pointers are iterators. - D's ranges are based on an existing concept: slices. Slices are ranges. However, I can't find where I read that. Ali
Aug 07 2022
On Saturday, 6 August 2022 at 15:37:32 UTC, pascal111 wrote:On Friday, 5 August 2022 at 04:05:08 UTC, Salih Dincer wrote:A range is like an iterator in any other language (Java, C++, python3, javascript, etc), it is how D implements (lazy) generators https://en.wikipedia.org/wiki/Lazy_evaluation . Ranges/Iterators don't necessarily have to be backed by memory, they just have to implement the interface. In D, a `empty` bool function that tells you whether you are at the end of the range or not; a `front` function to get the current value if the range is not `empty`; and a void function named `popFront` to advance to the next value if the range is not `empty`. Once you have implemented this interface, you can use your "range" object with any function that accept a range; with `foreach`; etc. Example of a range that is not backed by memory is a range with all the integer numbers. ```D struct Integers { private int z = 0; /* or make it a bool attribute that starts as false, and you set to * true when popFront is called while z is equal to int.min */ public bool empty() { return false; } public int front() { return this.z; } public void popFront() { /* if (this.z == int.min) { this.empty = false; return; } */ this.z *= -1; if (this.z <= 0) --this.z; } } void main() { import std.stdio : writeln; /* foreach is syntax sugar for * for (auto r = Integers(); !r.empty(); r.popFront()) { * auto z = r.front(); /+ or const z = r.front(); or ... +/ * ... * } * that is why it only works with ranges. */ foreach (const z; Integers()) { writeln(z); if (z == 5) break; } } ``` output: ``` 0 -1 1 -2 2 -3 3 -4 4 -5 5 ``` This will iterate all the integers, and the integers are of course, not all in memory, and don't remain in memory after they are used, since that would require infinite memory. (in the case of a range of integers, not infinite, because they are constrained by being int.sizeof bytes, but you could use a bignum implemenation that is not constrained by that and they would actually be infinite.) --- The equivalent in Java is the Iterable/Iterator interface. ```java import java.util.Iterator; public class Integers implements Iterable<Integer> { public class IntegersIterator implements Iterator<Integer> { private int z = 0; private boolean first = true; public IntegersIterator(Integer z) { this.z = z; } Override public boolean hasNext() { return true; } Override public Integer next() { if (this.first) { this.first = false; return this.z; } this.z *= -1; if (this.z <= 0) --this.z; return this.z; } } Override public IntegersIterator iterator() { return new IntegersIterator(0); } public static void main(String[] args) { /* syntax sugar for * { * final var it = newIntegers.iterator(); * while (it.hasNext()) { * final int z = it.next(); * ... * } * } */ for (final int z : new Integers()) { System.out.println(z); if (z == 5) break; } } } ``` The equivalent in python is a generator function: ```python def integers(): z = 0 yield z while True: z *= -1 if z <= 0: z -= 1 yield z for z in integers(): print(z) if z == 5: break ``` etcOn Thursday, 4 August 2022 at 22:54:42 UTC, pascal111 wrote:What!!! so where's ranges?! I thought slices of any array are ranges, and understood it like that, and also there's no data type called ranges, it's like if you are talking about Ghostly data type!I didn't notice that all what we needs to pop a range forward is just a slice, yes, we don't need variable here.Ranges and Slices are not the same thing. Slicing an array is easy. This is a language possibility. For example, you need an incrementing variable for the Fibonacci Series. SDB 79
Aug 07 2022
On Thursday, 4 August 2022 at 22:14:26 UTC, Ali Çehreli wrote:No element is copied or moved. :) AliI know that :) I just found that this user has problems to understand basics in D, so I tried not to go in detail and keep at its kind of logical layer. It seems the better way to help until the user asks specific questions.
Aug 05 2022
On 8/5/22 01:59, frame wrote:On Thursday, 4 August 2022 at 22:14:26 UTC, Ali Çehreli wrote:And I know that. :) We don't know who else is reading these threads, so I didn't want to give wrong impression. Copying would happen if we added slicing on the left-hand side. However, I realized that the following fails with a RangeError: void main() { auto arr = [1, 2, 3]; arr[0..$-1] = arr[1..$]; // <-- Runtime error } I suspect the length of the array is stamped too soon. (?) Should that operation be supported? AliNo element is copied or moved. :) AliI know that :)
Aug 05 2022
On Fri, Aug 05, 2022 at 08:06:00AM -0700, Ali Çehreli via Digitalmars-d-learn wrote:[...] I realized that the following fails with a RangeError: void main() { auto arr = [1, 2, 3]; arr[0..$-1] = arr[1..$]; // <-- Runtime error } I suspect the length of the array is stamped too soon. (?) Should that operation be supported?[...] This is why in C there's a difference between memcpy and memmove. I don't know how to express the equivalent in D, though. In general, you can't tell until runtime whether two slices overlap (`arr` could be aliased by another slice, for example, so you can't just tell by whether you're copying an overlapping range from the same variable). But if you know beforehand the ranges being copied are overlapping, you could use std.algorithm.bringToFront which would do the Right Thing(tm) in this case. T -- Why are you blatanly misspelling "blatant"? -- Branden Robinson
Aug 05 2022
On 8/4/22 06:08, pascal111 wrote:In next code from "https://www.tutorialspoint.com/d_programming/d_programming_ranges.htm",That page seems to be adapted from this original: http://ddili.org/ders/d.en/ranges.htmlwe have two issues: 1) Why the programmer needs to program "empty()", "front()", and "popFront()" functions for rangesThe programmer almost never needs to implement those functions. Existing data structures and algorithms are almost always sufficient. (I did need to implement them but really rarely.) I tried to explain what those functions do. I don't like my Students example much because wrapping a D slice does not make much sense. Again, I just try to explain them.while they exist in the language library?The existing front, popFronh, etc. are only for arrays (slices).it seems there's no need to exert efforts for that.Exactly."https://dlang.org/phobos/std_range_primitives.html" 2) "front()", and "popFront()" are using fixed constants to move forward the range, while they should use variables.Well, 0 is always the first element and 1..$ are always the rest. Variables would not add any value there. However, the example could use the existing library function that you mention:property bool empty() const { return students.length == 0;Better: import std.array : empty; return students.empty;} property ref Student front() { return students[0];Better: import std.array : front; return students.front;} void popFront() { students = students[1 .. $];Better: import std.array : popFront; students.popFront(); But I think those implementations might confuse the reader. Ali
Aug 04 2022