www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Referencer

reply HaraldZealot <harald_zealot tut.by> writes:
All ranges in Phobos pass by value, but if I have output range 
with state like cumulative statistics this is useless.

After discussion with Dicebot I try this work-arround:
http://dpaste.dzfl.pl/8af8eb8d0007

It is unfinished. But direction is observable.

Is this good solution? And how about to include something like 
this tool in Phobos?
Nov 20 2015
next sibling parent reply Alex Parrill <initrd.gz gmail.com> writes:
On Friday, 20 November 2015 at 18:23:57 UTC, HaraldZealot wrote:
 All ranges in Phobos pass by value, but if I have output range 
 with state like cumulative statistics this is useless.

 After discussion with Dicebot I try this work-arround:
 http://dpaste.dzfl.pl/8af8eb8d0007

 It is unfinished. But direction is observable.

 Is this good solution? And how about to include something like 
 this tool in Phobos?
I'm not sure how useful this is as opposed to plain pointers. For structs, since `foo.bar` is the same as `(&foo).bar`, you may as well use a pointer, and the only thing it saves for numbers is a pointer deference or two. You say ranges are pass-by-value, but that's not entirely true. Ranges themselves can be classes, or be made references via std.range.refRange. Range elements can be made lvalues by using ref functions [1]. As for the code: * Your example usage (x = x += x = (x * 5)) is confusing, due to the chained assignments. * I wouldn't mark this struct as safe because the passed value may leave scope, causing invalid dereferences. * There's no point in making the Reference struct a template, as the function its defined in is also a template. Just replace usages of U with T. [1]: http://dlang.org/function.html#ref-functions see also std.range.interface.hasLvalueElements
Nov 20 2015
next sibling parent reply HaraldZealot <harald_zealot tut.by> writes:
On Friday, 20 November 2015 at 18:48:51 UTC, Alex Parrill wrote:
 On Friday, 20 November 2015 at 18:23:57 UTC, HaraldZealot wrote:

 I'm not sure how useful this is as opposed to plain pointers. 
 For structs, since `foo.bar` is the same as `(&foo).bar`, you 
 may as well use a pointer, and the only thing it saves for 
 numbers is a pointer deference or two.
I realized that for my initial purposes simple pointer simply work, but when I'm trying make as possible universal template as it can be, I discover that the main problem with direct operators (and this touches not only numbers).
 You say ranges are pass-by-value, but that's not entirely true. 
 Ranges themselves can be classes, or be made references via 
 std.range.refRange. Range elements can be made lvalues by using 
 ref functions [1].
Possible refRange is what I was looking for. Thanks.
 As for the code:

 * Your example usage (x = x += x = (x * 5)) is confusing, due 
 to the chained assignments.
This is special one of boundary cases, that clarify why is it so complicated to create full-functional wrapper.
Nov 20 2015
parent reply HaraldZealot <harald_zealot tut.by> writes:
On Friday, 20 November 2015 at 19:53:23 UTC, HaraldZealot wrote:
 On Friday, 20 November 2015 at 18:48:51 UTC, Alex Parrill wrote:
 On Friday, 20 November 2015 at 18:23:57 UTC, HaraldZealot 
 wrote:

 You say ranges are pass-by-value, but that's not entirely 
 true. Ranges themselves can be classes, or be made references 
 via std.range.refRange. Range elements can be made lvalues by 
 using ref functions [1].
Possible refRange is what I was looking for. Thanks.
Unfortunately current RefRange and refRange implementation doesn't work with out-range :( Ridiculous, because reference semantic for out-range even is more important. So I'm found myself at fork point which from my next work for community is better: * add support for out range in `RefRange` * or implement further my universal referencer?
Nov 23 2015
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday, 23 November 2015 at 11:31:32 UTC, HaraldZealot wrote:
 On Friday, 20 November 2015 at 19:53:23 UTC, HaraldZealot wrote:
 On Friday, 20 November 2015 at 18:48:51 UTC, Alex Parrill 
 wrote:
 On Friday, 20 November 2015 at 18:23:57 UTC, HaraldZealot 
 wrote:

 You say ranges are pass-by-value, but that's not entirely 
 true. Ranges themselves can be classes, or be made references 
 via std.range.refRange. Range elements can be made lvalues by 
 using ref functions [1].
Possible refRange is what I was looking for. Thanks.
Unfortunately current RefRange and refRange implementation doesn't work with out-range :( Ridiculous, because reference semantic for out-range even is more important. So I'm found myself at fork point which from my next work for community is better: * add support for out range in `RefRange` * or implement further my universal referencer?
RefRange is not intended to work with output ranges, and output ranges are very different beasts from input ranges, so any kind of reference type wrapper for output ranges should be a separate construct. That being said, I'd be inclined to argue that anything taking an output range should always take it by ref, precisely because copying an output range almost never results in the correct semantics. So, we should probably make it a general policy that anything accepting an output range should accept it by ref. Now, if you need to work around the fact that a function doesn't take its arguments by ref, you could probably just pass a pointer to your output range rather than passing it by value. The syntax of calling a function on a pointer is the same as calling it on the object directly, so it should just work. And if it doesn't for some reason, then given the fact that the only function that output ranges recognize is put, creating a reference type wrapper would be pretty trivial; you only have one function to worry about. Certainly, I would think that your Referencer type is going in the wrong direction, because it's declaring a bunch of functions that have nothing to do with output ranges. - Jonathan M Davis
Nov 23 2015
parent reply HaraldZealot <harald_zealot tut.by> writes:
On Monday, 23 November 2015 at 12:09:13 UTC, Jonathan M Davis 
wrote:
 On Monday, 23 November 2015 at 11:31:32 UTC, HaraldZealot wrote:

 RefRange is not intended to work with output ranges, and output 
 ranges are very different beasts from input ranges, so any kind 
 of reference type wrapper for output ranges should be a 
 separate construct. That being said, I'd be inclined to argue 
 that anything taking an output range should always take it by 
 ref, precisely because copying an output range almost never 
 results in the correct semantics. So, we should probably make 
 it a general policy that anything accepting an output range 
 should accept it by ref.
So, you see that to open a PR about changes _by value_ to _by ref_ semantic for all functions operate with out range (especially for copy) is better way? But this breaks existing API...
 Certainly, I would think that your Referencer type is going in 
 the wrong direction, because it's declaring a bunch of 
 functions that have nothing to do with output ranges.
I see my referencer as universal wrapper to any value-like stuff (e.g. structs or even simple POD variable), not only for out ranges (or input ranges). But possibly it is to general (and so not perfect) solution.
Nov 23 2015
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday, 23 November 2015 at 14:25:19 UTC, HaraldZealot wrote:
 On Monday, 23 November 2015 at 12:09:13 UTC, Jonathan M Davis 
 wrote:
 On Monday, 23 November 2015 at 11:31:32 UTC, HaraldZealot 
 wrote:

 RefRange is not intended to work with output ranges, and 
 output ranges are very different beasts from input ranges, so 
 any kind of reference type wrapper for output ranges should be 
 a separate construct. That being said, I'd be inclined to 
 argue that anything taking an output range should always take 
 it by ref, precisely because copying an output range almost 
 never results in the correct semantics. So, we should probably 
 make it a general policy that anything accepting an output 
 range should accept it by ref.
So, you see that to open a PR about changes _by value_ to _by ref_ semantic for all functions operate with out range (especially for copy) is better way? But this breaks existing API...
That would require a larger discussion. It's come up before, but I don't recall if anything was ever decided. Output ranges pretty much have to be reference types or be passed by ref to work properly though. Pseudo-reference types might work under some circumstances (e.g. dynamic arrays), but outright value types won't. So, we almost have to make it so that they're passed by ref in order for them to work. But output ranges probably are long past due for a more in-depth discussion of their problems and how we should address them (e.g. how is code supposed to deal with the possibility of the output range being full) - though at this point, we're mostly trying to move to using lazy input ranges in most cases, since they're more flexible, and that will limit the scope of output ranges and make their deficiencies less of an issue (though we really should fix them). In any case, no, you probably shouldn't just start creating PRs which put ref on various output range parameters in Phobos.
 Certainly, I would think that your Referencer type is going in 
 the wrong direction, because it's declaring a bunch of 
 functions that have nothing to do with output ranges.
I see my referencer as universal wrapper to any value-like stuff (e.g. structs or even simple POD variable), not only for out ranges (or input ranges). But possibly it is to general (and so not perfect) solution.
Well, if all you want is to get a reference type out of a value type, then putting it on the heap and using a pointer to it would be a solution. Using RefCounted would be another, and I would think that it would be similar to what you're trying to do, since what you're trying to do sounds like it would be something like a RefCounted that doesn't actually involve reference counting. - Jonathan M Davis
Nov 23 2015
parent HaraldZealot <harald_zealot tut.by> writes:
On Monday, 23 November 2015 at 15:35:32 UTC, Jonathan M Davis 
wrote:
 Well, if all you want is to get a reference type out of a value 
 type, then putting it on the heap and using a pointer to it 
 would be a solution. Using RefCounted would be another, and I 
 would think that it would be similar to what you're trying to 
 do, since what you're trying to do sounds like it would be 
 something like a RefCounted that doesn't actually involve 
 reference counting.
Hmm, interesting. I'm looking deeper to `RefCounted`
Nov 23 2015
prev sibling parent Kagamin <spam here.lot> writes:
On Friday, 20 November 2015 at 18:48:51 UTC, Alex Parrill wrote:
 * I wouldn't mark this struct as  safe because the passed value 
 may leave scope, causing invalid dereferences.
Interestingly, it's not enough to not mark it as safe: the templated methods will still be inferred as safe. At last the price of automatic attribute inference is stated and everyone must pay :3
Nov 21 2015
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, 20 November 2015 at 18:23:57 UTC, HaraldZealot wrote:
 All ranges in Phobos pass by value, but if I have output range 
 with state like cumulative statistics this is useless.
Realistically, output ranges really should be passed by ref, but I'm not sure whether that's really being done in Phobos at this point - though output ranges aren't used all that much in Phobos anyway. It's mostly input ranges, which are a very different beast. But if you just make it so that your output range is a reference type (e.g a class or a struct with a single pointer to its state), then you get around any issues caused by a function not accepting its output range by ref. - Jonathan M Davis
Nov 20 2015