On Sunday, February 16, 2020 6:52:17 AM MST uranuz via Digitalmars-d-learn wrote: > It's very bad. Because there seem that when I use range based > algorithm I need to take two things into account. The first is > how algrorithm is implemented. If it creates copies of range > inside or pass it by reference. And the second is how the range > is implemented if it has value or reference semantics. So every > time I need to look into implementation and I can't rely on API > description in most of the cases. In a lot of cases Phobos uses > value semantics. But there are cases where I want the range > actually be consumed, but it's not. And the other problemme is > when algorithm expects range to have value semantics, but it's > not. So it's a buggy mess that it's hard to think about. In > trivial cases this is working although. But in more complex cases > it's simplier to implement some algorithms by own hands so that > it would work as I expect it myself rather that thinking about > all these value-ref-range mess. But still can't say that I > implement it correctly, because range specification actually > sucks as yo say. > It's just horrible
The current situation is definitely not ideal, but it can be used quite consistently. Just follow the rule that once you copy a range, you do not use that range ever again unless you assign it a new value. So, if you do something like auto result = r.find(e); then you should not be using r again unless you assign it a new value. e.g. r = r.find(e); r.popFront(); auto result = r.find(e); r = otherRange; r.popFront(); would be fine, because r was assigned a new value, whereas auto result = r.find(e); r.popFront(); should never happen in your code unless you know that typeof(r) is a type where copying it is equivalent to calling save on it. In generic code, that means that you should never use a range again after passing it to a function unless you assign it a new value, or that function accepted the argument by ref (which almost no range-based functions do). If you want to be able to use the range again after passing it to a function without assigning it a new value, then you need to call save so that you pass an independent copy. e.g. auto result = r.find.save(e); r.popFront(); The only copying going on here is with save, so there's no problem, whereas if r were passed to find directly, the behavior is implementation-dependent - hence why you should not be using a range after it's been copied (which includes passing it to a function). The only time that generic code can reuse a range after passing it to a function is if that function accepts its argument by ref, which almost no range-based code does. Far more frequently, it returns the result as a wrapper range, in which case, you can't use the original range any longer unless you used save when calling the function or if the code is not generic and you're coding based on the specific behavior of that particular range type - which usually isn't something that code should be doing. By no means do I claim that the status quo here is desirable, but if you just follow the simple rule that you don't ever use a range once it's been copied (unless that copy came from save), then you shouldn't run into problems related to the fact that different ranges have different copying semantics unless the function that you're calling is buggy. If you're going to run into a bug along those lines though, it's likely going to be because a function didn't call save when it was supposed to, and it was only tested with range types where copying them is equivalent to save. That's why it's important to test range-based code with both range types where copying them is equivalent to save and range types which are full-on reference types (and thus copying just results in another reference). In general though, any range that is a forward range should have copying it be equivalent to save, and using reference types for forward ranges tends to be inefficient and error-prone even if range-based functions (especially those in Phobos) should be able to handle them correctly. - Jonathan M Davis