-
-
Notifications
You must be signed in to change notification settings - Fork 746
Range adaptor: cache #1364
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Range adaptor: cache #1364
Conversation
std/algorithm.d
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo on cacheBidir
I think a complete caching proposal would add two more overloads of Also, We should also offer As a rule of thumb for index calculations, |
(Not sure whether that's the best rule.) |
For, say "cache(range, 42)", what would be the semantics (before I get working I mean)? Is this OK? "Calls to Would Implementation wise, this would be implemented via a circular buffer? (Cycle) ? Would it be OK to instead have this signature: I'm not sure how the "cache behind would work"? Ranges don't "grow", and indexes can't be negative...? The semantic usage would seem very strange to me. |
[...] Truth be told I don't see how this design will carry its own weight without a good enough use case. Also I'd say that having I see the immediate value in using singular Fixed-sized look-ahead/look-behind (commonly with length=1) could be useful but it turns out that having these things as "always-on" is a bad idea performance-wise. Now the main trouble with enable/disable and std.algorithm style adapter is that having an Second point is that e.g. parser requires unrestricted length in lookahead.... 3rd point is where and how (as in container/allocation policy) does this adapter store items is important.
No, nor I do think that a limit defined at run-time will suffice. |
So which direction should we take? Truth be told, I don't really see much point to having "cache(range, howMany)": Range are either iterated RA style, or forward style. I know of few algorithms that pop the range, while accessing only the N first elements. I proposed this range, I really only had simple caching in mind. I think it provides useful and simple functionality.
I'm actually unsure it would help much: As soon as popFront is called, the cache is refreshed, and the internal range pop'ed too, so the problem is still here. |
Well by itself no, since one have to deep copy first, but something like: range.map!(x => x.idup).cache will at least avoid allocations per access to front down the pipeline. In short it makes sure you do deep copy only once. In fact the irony is that map used to cache values but then it was fixed not to. Now we finaly allow folks to do it again but explicitly. |
The transient .front problem can't (at the moment) be solved generically, certainly not with Cache. You basically have to know what the element type is, and how to make a copy of it. If it's a shallow array, you can use .idup (you may have to do more than .idup if the array elements themselves are reference types). Otherwise, if it's a reference type, you have to know how to make a copy of said type. Barring a generic deep-copy function in Phobos, this is the best we can do right now. |
ping Might want to rebase this to prod the autotester onward. |
Rebased.
I'm here. I don't recall there is anything else that requires changing? |
Hmm. Now there's a whole bunch of compile errors. Rebase again? |
Fixed. I also did a bit of cleanup. |
I just hit the problem this solves so I'm eager to see this included. I had a long pseudo member chain with a Once this is merged I think it would be useful to add some warnings to functions like |
That's good to hear, because I myself was actually wondering how useful this actually is, and was having trouble coming up with a good usecace. Indeed,
No reason not to do it now :) if it gets merged. |
On Thu, Jan 02, 2014 at 01:54:15PM -0800, monarch dodra wrote:
Just out of curiosity, why can't T People tell me that I'm paranoid, but they're just out to get me. |
@monarchdodra It's actually not just the previous call. The std.net.curl call was several steps further up the chain so everything was getting double called all the way up to the beginning of the chain which is terribly unexpected. I actually had to comment out each step of the chain over and over until I isolated what was causing it. Perhaps |
Intrinsically, I'm not sure it's possible, because of the way it works. Each element must be tested, and then the user calls front, leading to a second call to front. I don't think there's any way to work around that.
filter could cache the result internally, but doing that is actually difficult, and not 100% generic. It'll fail for ranges with const elements, or non-assignable elements. That's a restriction that's not acceptable. In contrast, |
ping all reviewers |
I still think it would be useful to have. It can be a useful complement in otherwise long and costly UFCS chains. But I'm not passionate about it. Anybody of the opinion this range is actually bad/wrong? Semi-on topic, I'm not too sure about providing birdirectional access anymore: 99% of the functionality is in forward iteration anyways. Bidirectional iteration could have a surprising effect, as the "last" element would be evaluated twice. |
IMO we should go with it. Thoughts about cached range as a new kind of range need some public discussion. |
I have this bookmarked for some more detailed experiments during the upcoming weekend. |
I'm 100% in favor of this. Right now I have to use I can't really think of uses for the multi-element cache. Maybe to compartmentalize part of a long chain so there is less pressure on the CPU cache? I welcome the feature in case it becomes handy for something though. Unless there is some huge defect in the concept I'm not seeing it should definitely go forward once everyone who wants to review the implementation has done so. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if @DmitryOlshansky's sliding window range idea could be used here and, more broadly, if there is actually some overlap between cache()
and his concept.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is, which is something I find intriguing after looking at this again. Given that @andralex wasn't objecting adding a couple of primitives which is a good sign.
I'm going to (hopefully soon) do a short writeup on a buffer range design and new i/o.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea of a sliding window range. It could even be applicable to the prospective std.io
.
Looks like we have merge conflicts. Please rebase. |
std/algorithm.d
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/useful a function/a useful function/
s/functons/functions/ (typo)
No need to worry, we'll handle it. |
@AndrejMitrovic Cool. Versionized labels feel just right. |
Note that this won't be in Unless it is going to be restarted, of course. |
I don't get it, 2.066 just came out. 2.067 can't come out that quickly, can it? And what commits is it going to contain anyway, there haven't been that many? |
Everything that went into master while 2.066 was in alpha/beta except for the regression fixes which went into both. |
Ah. I'm clearly out of my depth now for how things are done. I guess we'll have to label it 2.068 then? But isn't that like.. a year from now (judging by how unfrequent our releases are)? :/ |
The ideas is releases should be more frequent. Who knows what will actually happen though. |
Oh, OK. I get it now. |
It seems very close to the idea of Scala's sliding (they had it way back in 2009): |
Addressed points raised by @AndrejMitrovic 's in regards to style. Also improved the unittest to show that the effects of using cache over not using cache (in a fashion I find well expressed mind you). I also removed "support" for objects with disabled this, as it lead to using said objects without actually initializing them, so I wasn't actually supporting them. If all is well and good, I'll give it a squash. |
std/algorithm.d
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: "instantiate" not "instanciate".
Anything else? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be moved to the template constraints?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be hard to express in a short and "grokkable" way for the end user.
Also, I still believe that template constraints is for "logical disambiguation", and not "internal validation". This is the overload that works on input ranges. From there, the static assert is only designed as a way to cleanly express a compile error.
We do not want allow someone else to write a "cache" that could also operates on input ranges, with completly different semantics, just because the element type has a particular trait. This would require an explicit disambiguation (even if one of them wouldn't compile anyways, it is close enough logically to be ambigous).
As discussed in this thread: http://forum.dlang.org/thread/ovbjcmogezbvsxrwfcol@forum.dlang.org This provides a range adaptor that cache the result of another range. Meant as a lazy alternative to array. Not much else to say...? Documentation might suck.
ping |
AFAIK, no. |
Let's do it. |
Auto-merge toggled on |
Cool. Thanks. |
On Thu, Sep 25, 2014 at 04:20:43PM -0700, Михаил Страшун wrote:
Go, team Phobos! :-P |
Filter could just simply cache it's front element like any other range, at least if front has a side-effect. |
The point is that |
Please add new functions to the cheat sheet as well as the function list. |
A regression has been filed, caused by this pull request: |
Maybe too late now, but IMO |
As discussed in this thread:
http://forum.dlang.org/thread/ovbjcmogezbvsxrwfcol@forum.dlang.org
This provides a range adaptor that cache the result of another range.
Meant as a lazy alternative to array. Not much else to say...?
Implemented as obscure type
Wording in documentation might suck.
Please destroy.