On Fri, Sep 29, 2017 at 6:17 PM, Andrew Trick <[email protected]> wrote:
> > > On Sep 29, 2017, at 4:03 PM, Taylor Swift <[email protected]> wrote: > > > > On Sep 29, 2017, at 5:56 PM, Dave Abrahams <[email protected]> wrote: > > > > On Sep 29, 2017, at 3:48 PM, Taylor Swift <[email protected]> wrote: > > > > On Fri, Sep 29, 2017 at 4:13 PM, Andrew Trick <[email protected]> wrote: > >> >> >> On Sep 29, 2017, at 1:23 PM, Taylor Swift <[email protected]> wrote: >> >> Instead of >>> >>> buf.intialize(at: i, from: source) >>> >>> We want to force a more obvious idiom: >>> >>> buf[i..<n].intialize(from: source) >>> >>> >> The problem with subscript notation is we currently get the n argument >> from the source argument. So what would really have to be written is >> >> buf[i ..< i + source.count].initialize(from: source) >> >> which is a lot more ugly and redundant. One option could be to decouple >> the count parameter from the length of the source buffer, but that opens up >> the whole can of worms in which length do we use? What happens if n - i is >> less than or longer than source.count? If we enforce the precondition >> that source.count == n - i, then this syntax seems horribly redundant. >> >> >> Sorry, a better analogy would have been: >> >> buf[i...].intialize(from: source) >> >> Whether you specify the slice’s end point depends on whether you want to >> completely initialize that slice or whether you’re just filling up as much >> of the buffer as you can. It also depends on whether `source` is also a >> buffer (of known size) or some arbitrary Sequence. >> >> Otherwise, point taken. >> >> -Andy >> > > After thinking about this more, one-sided ranges might provide just the > expressivity we need. What if: > > buf[offset...].initialize(from: source) // initializes source.count > elements from source starting from offset > > buf[offset ..< endIndex].initialize(from: source) // initializes up to > source.count elements from source starting from offset > > > The one sided one does not give a full initialization guarantee. The two > sided one guarantees the entire segment is initialized. > > > In every other context, x[i...] is equivalent to x[i..<x.endIndex] > > I don't think breaking that precedent is a good idea. > > For move operations, the one sided one will fully deinitialize the source > buffer while the two sided one will only deinitialize endIndex - offset > elements. > > > — > -Dave > > > well since people want to use subscript notation so much we need some way > of expressing case 1. writing both bounds in the subscript seems to imply a > full initialization (and thus partial movement) guarantee. > > > Presumably, in your use case, you’re working directly with buffers on both > sides (please point us to the real code). With the slicing approach, that > would be done as follows: > > bufA[i ..< i + bufB.count].initialize(from: bufB) > > That will enforce full initialization of the slice: > precondition(self.count == source.count). > > Your point stands that it is redundant. That point will need to be weighed > against other points, which I think should be discussed in another thread. > > -Andy > To this and your other method about the real library code; right now the PNG library doesn’t use buffer methods (since they don’t exist yet) and pixels are plain-old-data so i’m not using the memory state API there anyway (the original proposal didn’t even have anything to do with those APIs actually). However I did take a few minutes to write a quick queue implementation <https://gist.github.com/kelvin13/0860334278aeab5c1cbaefbefb050268#file-dequeue-swift> in Swift which does not make any assumptions about the Element type. I then rewrote it using the hypothetical buffer API I proposed, and then the hypothetical buffer API using subscript notation. *These are the relevant function calls using the current API (the rest of the code has been stripped out)* newBuffer:UnsafeMutablePointer<Element> = UnsafeMutablePointer<Element>.allocate(capacity: newCapacity) newBuffer .moveInitialize( from: buffer + self.zero, count: self.capacity - self.zero) (newBuffer + self.zero).moveInitialize( from: buffer, count: self.zero) buffer.deallocate(capacity: self.capacity) (self.buffer! + self.bufferPosition(of: self.count)).initialize(to: data) let dequeued:Element = (self.buffer! + self.zero).move() *These are the function calls using the SE 184 API * newBuffer:UnsafeMutableBufferPointer<Element> = UnsafeMutableBufferPointer<Element>.allocate(capacity: newCapacity) newBuffer.moveInitialize(at: 0, from: self.buffer[self.zero... ]) newBuffer.moveInitialize(at: self.zero, from: self.buffer[0 ..< self.zero]) self.buffer.deallocate() (self.buffer.baseAddress! + self.bufferPosition(of: self.count)).initialize(to: data) let dequeued:Element = (self.buffer! + self.zero).move() *And with the proposed subscript notation* newBuffer:UnsafeMutableBufferPointer<Element> = UnsafeMutableBufferPointer<Element>.allocate(capacity: newCapacity) newBuffer[0... ].moveInitialize(from: self.buffer[self.zero... ]) newBuffer[self.zero ... self.zero << 1].moveInitialize(from: self.buffer[0 ..< self.zero]) self.buffer.deallocate() (self.buffer.baseAddress! + self.bufferPosition(of: self.count)).initialize(to: data) let dequeued:Element = (self.buffer! + self.zero).move() I took out the rebasing calls since apparently we’re bringing slices into the scope of this proposal.
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
