Skip to content

Commit dd5e6b6

Browse files
Add custom implementations of removeLast and remove(at:) to Array (#14273)
1 parent c12b0a5 commit dd5e6b6

File tree

1 file changed

+80
-61
lines changed

1 file changed

+80
-61
lines changed

stdlib/public/core/Arrays.swift.gyb

Lines changed: 80 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1493,17 +1493,6 @@ extension ${Self} : RangeReplaceableCollection, ArrayProtocol {
14931493
}
14941494

14951495
%if Self == 'ArraySlice':
1496-
/// Removes and returns the last element of the array.
1497-
///
1498-
/// The array must not be empty. This example removes the last number from an
1499-
/// array of `Double` values.
1500-
///
1501-
/// var measurements: [Double] = [1.1, 1.5, 2.9, 1.2, 1.5, 1.3, 1.2]
1502-
/// let removed = measurements.removeLast()
1503-
/// print(measurements)
1504-
/// // Prints "[1.1, 1.5, 2.9, 1.2, 1.5, 1.3]"
1505-
///
1506-
/// - Returns: The element that was removed.
15071496
@_inlineable
15081497
public mutating func _customRemoveLast() -> Element? {
15091498
_precondition(count > 0, "Can't removeLast from an empty ${Self}")
@@ -1519,31 +1508,58 @@ extension ${Self} : RangeReplaceableCollection, ArrayProtocol {
15191508
self.replaceSubrange((i &- 1)..<i, with: EmptyCollection())
15201509
return result
15211510
}
1522-
%end
1523-
1524-
/// Inserts a new element at the specified position.
1525-
///
1526-
/// The new element is inserted before the element currently at the specified
1527-
/// index. If you pass the array's `endIndex` property as the `index`
1528-
/// parameter, the new element is appended to the array.
1511+
1512+
/// Removes and returns the element at the specified position.
15291513
///
1530-
/// var numbers = [1, 2, 3, 4, 5]
1531-
/// numbers.insert(100, at: 3)
1532-
/// numbers.insert(200, at: numbers.endIndex)
1514+
/// All the elements following the specified position are moved up to
1515+
/// close the gap.
15331516
///
1534-
/// print(numbers)
1535-
/// // Prints "[1, 2, 3, 100, 4, 5, 200]"
1517+
/// var measurements: [Double] = [1.1, 1.5, 2.9, 1.2, 1.5, 1.3, 1.2]
1518+
/// let removed = measurements.remove(at: 2)
1519+
/// print(measurements)
1520+
/// // Prints "[1.1, 1.5, 1.2, 1.5, 1.3, 1.2]"
15361521
///
1537-
/// - Parameter newElement: The new element to insert into the array.
1538-
/// - Parameter i: The position at which to insert the new element.
1539-
/// `index` must be a valid index of the array or equal to its `endIndex`
1540-
/// property.
1522+
/// - Parameter index: The position of the element to remove. `index` must
1523+
/// be a valid index of the array.
1524+
/// - Returns: The element at the specified index.
15411525
///
15421526
/// - Complexity: O(*n*), where *n* is the length of the array.
15431527
@_inlineable
1544-
public mutating func insert(_ newElement: Element, at i: Int) {
1545-
_checkIndex(i)
1546-
self.replaceSubrange(i..<i, with: CollectionOfOne(newElement))
1528+
@discardableResult
1529+
public mutating func remove(at index: Int) -> Element {
1530+
let result = self[index]
1531+
self.replaceSubrange(index..<(index + 1), with: EmptyCollection())
1532+
return result
1533+
}
1534+
1535+
%else:
1536+
/// Removes and returns the last element of the array.
1537+
///
1538+
/// - Returns: The last element of the array if the array is not empty;
1539+
/// otherwise, `nil`.
1540+
///
1541+
/// - Complexity: O(*n*) if the array is bridged, where *n* is the length
1542+
/// of the array; otherwise, O(1).
1543+
@_inlineable
1544+
public mutating func popLast() -> Element? {
1545+
let newCount = _getCount() - 1
1546+
guard newCount >= 0 else { return nil }
1547+
_makeUniqueAndReserveCapacityIfNotUnique()
1548+
let pointer = (_buffer.firstElementAddress + newCount)
1549+
let element = pointer.move()
1550+
_buffer.count = newCount
1551+
return element
1552+
}
1553+
1554+
@_inlineable
1555+
public mutating func _customRemoveLast() -> Element? {
1556+
let newCount = _getCount() - 1
1557+
_precondition(newCount >= 0, "Can't removeLast from an empty ${Self}")
1558+
_makeUniqueAndReserveCapacityIfNotUnique()
1559+
let pointer = (_buffer.firstElementAddress + newCount)
1560+
let element = pointer.move()
1561+
_buffer.count = newCount
1562+
return element
15471563
}
15481564

15491565
/// Removes and returns the element at the specified position.
@@ -1564,10 +1580,42 @@ extension ${Self} : RangeReplaceableCollection, ArrayProtocol {
15641580
@_inlineable
15651581
@discardableResult
15661582
public mutating func remove(at index: Int) -> Element {
1567-
let result = self[index]
1568-
self.replaceSubrange(index..<(index + 1), with: EmptyCollection())
1583+
_precondition(index < endIndex, "Index out of range")
1584+
_precondition(index >= startIndex, "Index out of range")
1585+
_makeUniqueAndReserveCapacityIfNotUnique()
1586+
let newCount = _getCount() - 1
1587+
let pointer = (_buffer.firstElementAddress + index)
1588+
let result = pointer.move()
1589+
pointer.moveInitialize(from: pointer + 1, count: newCount - index)
1590+
_buffer.count = newCount
15691591
return result
15701592
}
1593+
%end
1594+
1595+
/// Inserts a new element at the specified position.
1596+
///
1597+
/// The new element is inserted before the element currently at the specified
1598+
/// index. If you pass the array's `endIndex` property as the `index`
1599+
/// parameter, the new element is appended to the array.
1600+
///
1601+
/// var numbers = [1, 2, 3, 4, 5]
1602+
/// numbers.insert(100, at: 3)
1603+
/// numbers.insert(200, at: numbers.endIndex)
1604+
///
1605+
/// print(numbers)
1606+
/// // Prints "[1, 2, 3, 100, 4, 5, 200]"
1607+
///
1608+
/// - Parameter newElement: The new element to insert into the array.
1609+
/// - Parameter i: The position at which to insert the new element.
1610+
/// `index` must be a valid index of the array or equal to its `endIndex`
1611+
/// property.
1612+
///
1613+
/// - Complexity: O(*n*), where *n* is the length of the array.
1614+
@_inlineable
1615+
public mutating func insert(_ newElement: Element, at i: Int) {
1616+
_checkIndex(i)
1617+
self.replaceSubrange(i..<i, with: CollectionOfOne(newElement))
1618+
}
15711619

15721620
/// Removes all elements from the array.
15731621
///
@@ -2358,35 +2406,6 @@ extension Array {
23582406
}
23592407
#endif
23602408

2361-
extension Array {
2362-
/// Removes and returns the last element of the array.
2363-
///
2364-
/// - Returns: The last element of the array if the array is not empty;
2365-
/// otherwise, `nil`.
2366-
///
2367-
/// - Complexity: O(*n*) if the array is bridged, where *n* is the length
2368-
/// of the array; otherwise, O(1).
2369-
@_inlineable
2370-
public mutating func popLast() -> Element? {
2371-
guard !isEmpty else { return nil }
2372-
return removeLast()
2373-
}
2374-
}
2375-
2376-
extension ContiguousArray {
2377-
/// Removes and returns the last element of the array.
2378-
///
2379-
/// - Returns: The last element of the array if the array is not empty;
2380-
/// otherwise, `nil`.
2381-
///
2382-
/// - Complexity: O(1)
2383-
@_inlineable
2384-
public mutating func popLast() -> Element? {
2385-
guard !isEmpty else { return nil }
2386-
return removeLast()
2387-
}
2388-
}
2389-
23902409
extension ArraySlice {
23912410
@_inlineable
23922411
public // @testable

0 commit comments

Comments
 (0)