[swift-evolution] Shouldn't ".withUnsafeBufferPointer" and ".withUnsafeMutableBufferPointer" be parts of protocols?

Zach Waldowski zach at waldowski.me
Fri Jan 27 18:36:38 CST 2017


I like the sound of it so far, but my first major thought is that isn't
it modeling a "has-a" relationship instead of an "is-a"? The buffer
methods indicate that the data type *can* be represented as a buffer for
the duration of the method call, but may not necessarily be before or
after. Such a semantic distinction would also allow Data and
DispatchData, as well as other theoretical data structures like a Deque
(I think?) to participate.


Cheers!

  Zachary Waldowski

  zach at waldowski.me





On Fri, Jan 27, 2017, at 06:40 PM, Daryle Walker via swift-evolution wrote:
> I was perusing the library for array ideas, and noticed that several
> types had methods in common, but without a grouping protocol.
> Shouldn’t that be fixed?
> 

> (Oh, if multiple protocols have an associated-type with the same name,
> is that a problem? Is it a problem if they resolve differently for
> each protocol attached to a given type? I’m asking because these
> protocols reuse Sequence’s Element for their own purpose.)
> 

> 

> Formal Protocol for Contiguous Storage Visitation


>  * Proposal: SE-NNNN
>  * Authors: Daryle Walker[1]
>  * Review Manager: TBD
>  * Status: *Awaiting review*
> *During the review process, add the following fields as needed:*


>  * Decision Notes: Rationale[2], Additional Commentary[3]
>  * Bugs: SR-NNNN[4], SR-MMMM[5]
>  * Previous Revision: 1[6]
>  * Previous Proposal: SE-XXXX
> Introduction



> The standard library types Array, ArraySlice, and ContiguousArray have
> an interface for visiting their elements as a contiguous block of
> memory (arranging said elements to that configuration first if
> necessary). These methods are all the same, but not under a common
> protocol (i.e. seeming to match by "coincidence").
> This proposal seeks to correct that with two new protocols that these
> types will implement.
> Swift-evolution thread: Discussion thread topic for that proposal[7]
> Motivation



> Just adding these protocols for consistency is relatively minor, but
> they may be used for other types. Particularly, they would be needed
> if fixed-sized arrays are added to the language.
> Proposed solution



> The library array types will follow the
> MutableContiguousBlockprotocol, which inherits from the
> ContiguousBlock protocol.
> extension Array: MutableContiguousBlock { }  extension ArraySlice:
> MutableContiguousBlock { }  extension ContiguousArray:
> MutableContiguousBlock { }
> For example, a repackaging of the library's example code:



> func change<T: MutableContiguousBlock>(object: inout T) -> T.Element
> where T.Element: Integer { let sum = object.withUnsafeBufferPointer {
> (buffer) -> T.Element in var result: T.Element = 0 for i in
> stride(from: buffer.startIndex, to: buffer.endIndex, by: 2) { result
> += buffer[i] } return result } object.withUnsafeMutableBufferPointer {
> buffer in for j in stride(from: buffer.startIndex, to: buffer.endIndex
> - 1, by: 2) { swap(&buffer[j], &buffer[j + 1]) } } return sum }  var
> numbers = [1, 2, 3, 4, 5] print(change(object: &numbers))  // 9
> print(numbers)                   // [2, 1, 4, 3, 5]
> Detailed design



> /** Visitation protocol of the receiver's contiguous storage of
> immutable elements. */ protocol ContiguousBlock {  /// Inferred alias
> to the element type to visit associatedtype Element  /** Calls a
> closure with a pointer to the receiver's contiguous storage. If no
> such storage exists, it is first created.  Often, the optimizer can
> eliminate bounds checks within an array algorithm, but when that
> fails, invoking the same algorithm on the buffer pointer passed into
> your closure lets you trade safety for speed.  The following example
> shows how you can iterate over the contents of the buffer pointer:
> let numbers = [1, 2, 3, 4, 5] let sum =
> numbers.withUnsafeBufferPointer { buffer -> Int in var result = 0 for
> i in stride(from: buffer.startIndex, to: buffer.endIndex, by: 2) {
> result += buffer[i] } return result } // 'sum' == 9  - Parameter body:
> A closure with an `UnsafeBufferPointer` parameter that points to the
> contiguous storage for the receiver. If `body` has a return value, it
> is used as the return value for this method. The pointer argument is
> valid only for the duration of the closure's execution.  - Returns:
> The return value of the `body` closure parameter, if any.  - SeeAlso:
> Swift.UnsafeBufferPointer */ func withUnsafeBufferPointer<R>(_ body:
> (UnsafeBufferPointer<Element>) throws -> R) rethrows -> R  }  /**
> Visitation protocol of the receiver's contiguous storage of elements,
> allowing mutation. */ protocol MutableContiguousBlock: ContiguousBlock
> {  /** Calls the given closure with a pointer to the receiver's
> mutable contiguous storage. If no such storage exists, it is first
> created.  Often, the optimizer can eliminate bounds checks within an
> array algorithm, but when that fails, invoking the same algorithm on
> the buffer pointer passed into your closure lets you trade safety for
> speed.  The following example shows modifying the contents of the
> `UnsafeMutableBufferPointer` argument to `body` alters the contents of
> the receiver:  var numbers = [1, 2, 3, 4, 5]
> numbers.withUnsafeMutableBufferPointer { buffer in for i in
> stride(from: buffer.startIndex, to: buffer.endIndex - 1, by: 2) {
> swap(&buffer[i], &buffer[i + 1]) } } print(numbers) // Prints "[2, 1,
> 4, 3, 5]"  - Warning: Do not rely on anything about `self` (the
> receiver of this method) during the execution of the `body` closure:
> It may not appear to have its correct value. Instead, use only the
> `UnsafeMutableBufferPointer` argument to `body`.  - Parameter body: A
> closure with an `UnsafeMutableBufferPointer` parameter that points to
> the contiguous storage for the receiver. If `body` has a return value,
> it is used as the return value for this method. The pointer argument
> is valid only for the duration of the closure's execution.  - Returns:
> The return value of the `body` closure parameter, if any.  - SeeAlso:
> withUnsafeBufferPointer, Swift.UnsafeMutableBufferPointer */ mutating
> func withUnsafeMutableBufferPointer<R>(_ body: (inout
> UnsafeMutableBufferPointer<Element>) throws -> R) rethrows -> R  }
> I don't know how the 3 library types implement this methods, but we
> know it can be done. If added as an implicit interface to built-in fixed-
> sized arrays, the implementers can use similar techniques or compiler
> magic. I don't know the difficulty to adapt these interfaces with third-
> party code.
> Source compatibility



> The changes are strictly additive, and at the library level, so there
> should be no impact to existing code.
> Effect on ABI stability



> These changes should not affect ABI stability.



> Effect on API resilience



> As just stated, the addition of two protocol names to the API
> shouldn't affect the ABI.
> Alternatives considered



> The main alternative is to do nothing. If fixed-sized arrays are later
> added, they could have the same methods too, but there would still be
> no common link.
> Another alternative would make MutableContiguousBlock not inherit from
> ContiguousBlock, meaning the former would need to define an Element
> associated type. But don't see a need for a protocol with a read-write
> method without its read-only counterpart available.
> 

> 

>
> Daryle Walker

> Mac, Internet, and Video Game Junkie

> darylew AT mac DOT com 

> 

> _________________________________________________

> swift-evolution mailing list

> swift-evolution at swift.org

> https://lists.swift.org/mailman/listinfo/swift-evolution




Links:

  1. https://github.com/CTMacUser
  2. https://lists.swift.org/pipermail/swift-evolution/
  3. https://lists.swift.org/pipermail/swift-evolution/
  4. https://bugs.swift.org/browse/SR-NNNN
  5. https://bugs.swift.org/browse/SR-MMMM
  6. https://github.com/apple/swift-evolution/blob/...commit-ID.../proposals/NNNN-filename.md
  7. https://lists.swift.org/pipermail/swift-evolution/
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170127/09365122/attachment.html>


More information about the swift-evolution mailing list