profile
viewpoint

pyrtsa/poly 46

Solving the Expression Problem in C++11

pyrtsa/Frameless 1

The spiritual successor to Less Framework

pyrtsa/homebrew-dupes 1

System duplicate formulae for the Homebrew package manager

pyrtsa/nt2 1

The Numerical Template Toolbox - C++ Scientific Computing Made Easy

pyrtsa/alga 0

Algebraic graphs

pyrtsa/atom-language-idris 0

A Idris Mode for Atom.io

pyrtsa/atom-nix 0

Nix syntax highlighting for Atom

pyrtsa/CocoaPods 0

An Objective-C library dependency manager.

pyrtsa/CryptoSwift 0

Crypto related functions and helpers for Swift implemented in Swift programming language

pyrtsa/easyexif 0

Tiny ISO-compliant C++ EXIF parsing library, third-party dependency free.

created tagapple/swift-llbuild

tagswift-DEVELOPMENT-SNAPSHOT-2021-01-23-a

A low-level build system, used by Xcode and the Swift Package Manager

created time in 17 hours

Pull request review commentapple/swift-algorithms

add suffix:while method

+//===----------------------------------------------------------------------===//+//+// This source file is part of the Swift Algorithms open source project+//+// Copyright (c) 2021 Apple Inc. and the Swift project authors+// Licensed under Apache License v2.0 with Runtime Library Exception+//+// See https://swift.org/LICENSE.txt for license information+//+//===----------------------------------------------------------------------===//++//===----------------------------------------------------------------------===//+// Suffix(while:)+//===----------------------------------------------------------------------===//++extension BidirectionalCollection {+  /// Returns a subsequence containing the elements from the end until `predicate`+  /// returns `false` and skipping the remaining elements.+  ///+  /// - Parameter predicate: A closure that takes an element of the+  ///   sequence as its argument and returns `true` if the element should+  ///   be included or `false` if it should be excluded. Once the predicate+  ///   returns `false` it will not be called again.+  ///+  /// - Complexity: O(*n*), where *n* is the length of the collection.+  public func suffix(+    while predicate: (Element) throws -> Bool+  ) rethrows -> SubSequence {+    let start = startIndex+    var result = endIndex+    while result != start {+      let previous = index(before: result)+      guard try predicate(self[previous]) else { break }+
michiboo

comment created time in a day

Pull request review commentapple/swift-algorithms

add suffix:while method

 //===----------------------------------------------------------------------===//  extension BidirectionalCollection {+  /// Returns a subsequence containing the elements from the end until `predicate`+  /// returns `false` and skipping the remaining elements.
  /// Returns a subsequence containing the elements from the end until
  /// `predicate` returns `false` and skipping the remaining elements.
michiboo

comment created time in a day

pull request commentapple/swift-algorithms

add suffix:while method

A lot of similar algorithms in the standard library use != instead of > or < for comparing indexes. I’ll have to do more research as to why that is. My initial guess is perhaps because implementations of custom indexes have slightly faster implementations of != than <. But either way, it would be good to have consistency here.

I agree that we should use != to be consistent with the stdlib.

One of the reasons stdlib uses != is historical. Originally Collection.Index in the stdlib was only Equatable, not Comparable. From SE-0065 which added the Comparable requirement:

It's worth noting that this requirement isn't strictly necessary. Without it, though, indices would have no requirements beyond Equatable, and creation of a Range<T> would have to be allowed for any T conforming to Equatable. As a consequence, most interesting range operations, such as containment checks, would be unavailable unless T were also Comparable, and we'd be unable to provide bounds-checking in the general case.

That said, the requirement has real benefits. For example, it allows us to support distance measurement between arbitrary indices, even in collections without random access traversal. In the old model, x.distance(to: y) for these collections had the undetectable precondition that x precede y, with unpredictable consequences for violation in the general case.

michiboo

comment created time in a day

Pull request review commentapple/swift-algorithms

add suffix:while method

 //===----------------------------------------------------------------------===//  extension BidirectionalCollection {-  @inlinable-  public __consuming func Suffix(while predicate: (Element) throws -> Bool-  ) rethrows -> [Element] {-   var result = ContiguousArray<Element>()-   self.reverse()-    for element in self {-      guard try predicate(element) else {-        break-      }-      result.append(element)+  public func suffix(+    while predicate: (Element) throws -> Bool+  ) rethrows -> SubSequence {+    let start = startIndex+    var result = endIndex+    while result != start {+      let previous = index(before: result)+      guard try predicate(self[previous]) else { break }++      result = previous     }-    result.reverse()-    return Array(result)+    return self[result...]   }-}+}
}

michiboo

comment created time in 2 days

pull request commentapple/swift-algorithms

Add `contains(countIn:where:)` to `Sequence`

I thought that the Sequence level is the wrong approach. Maybe we could start from the IteratorProtcol level. I wrote a core routine as an extension to iterators. However, we generally don't put new API onto IteratorProtcol; we usually take an iterator as an inout argument or as a return value. So I moved the iterator approach as a return value:


extension Sequence {

    /// Returns an iterator into the sequence that is just past the given number
    /// of elements that match the given predicate.
    ///
    /// The following example prints the value after the fifth even element of the range.
    ///
    ///     let range = -3..<20
    ///     if var iterator = range.skippingOver(count: 5, where: { $0.isMultiple(of: 2) }) {
    ///         if let nextValue = iterator.next() {
    ///             print(nextValue)
    ///         } else {
    ///             print("The range ended at its fifth even number.")
    ///         }
    ///     } else {
    ///         print("The range had less than five even numbers.")
    ///     }
    ///
    ///     // Prints: "7"
    ///
    /// - Precondition:
    ///   - `count >= 0`.
    ///   - Either the sequence is finite or at least `count` elements in the
    ///     sequence match `predicate`.
    ///
    /// - Parameters:
    ///   - count: The number of occurrences of matching elements to find before
    ///     stopping.
    ///   - predicate: A closure that takes an element of the sequence as its
    ///     argument and returns a Boolean value indicating whether the element
    ///     is a match.
    /// - Returns: If the sequence has fewer than `count` elements that match
    ///   `predicate`, then `nil`.  Otherwise, an iterator that starts with the
    ///   element after the last match.  If that last match was also the last
    ///   element, then the iterator's virtual sequence will be empty.
    ///
    /// - Complexity: O(*n*), where *n* is the length of the sequence.
    public func skippingOver(
        count: Int,
        where predicate: (Element) throws -> Bool
    ) rethrows -> Iterator? {
        var result = makeIterator()
        counter: for _ in 0..<count {
            while let element = result.next() {
                if try predicate(element) {
                    continue counter
                }
            }
            return nil
        }
        return result
    }

}

extension Sequence where Element: Equatable {

    /// Returns an iterator into the sequence that is just past the given number
    /// of elements that equal the given element.
    ///
    /// The following example prints the character after the third "a".
    ///
    ///     let sample = "Mary had a little lamb"
    ///     if var iterator = sample.skippingOver(count: 3, of: "a") {
    ///         if let nextCharacter = iterator.next() {
    ///             print("The next character is '\(nextCharacter)'.")
    ///         } else {
    ///             print("The third occurence of 'a' is at the last position.")
    ///         }
    ///     } else {
    ///         print("The occurrence count of 'a' is less than 3.")
    ///     }
    ///
    ///     // Prints: "The next character is ' '."
    ///
    /// - Precondition:
    ///   - `count >= 0`.
    ///   - Either the sequence is finite or at least `count` elements in the
    ///     sequence equal `element`.
    ///
    /// - Parameters:
    ///   - count: The number of occurrences of matching elements to find before
    ///     stopping.
    ///   - element: An element to search for in the sequence.
    /// - Returns: If the sequence has fewer than `count` elements that equal
    ///   `element`, then `nil`.  Otherwise, an iterator that starts with the
    ///   element after the last match.  If that last match was also the last
    ///   element, then the iterator's virtual sequence will be empty.
    ///
    /// - Complexity: O(*n*), where *n* is the length of the sequence.
    @inlinable
    public func skippingOver(count: Int, of element: Element) -> Iterator? {
        return skippingOver(count: count, where: { $0 == element })
    }

}

Maybe this could form a building block to a better API.

mdznr

comment created time in 3 days

issue commentapple/swift-algorithms

Partition: Make mutating functions return `@discardableResult`

It's a good question.

I can't recall, but I imagine we just followed the precedent set by partition(by:) from the standard library which does not mark its result as a @discardableResult.

While it could be argued that bringForward(elementsSatisfying:) should return an Index as well, even that return value isn’t always needed to be used and should be marked as @discardableResult.

I do think bringForward(elementsSatisfying:) should probably return an Index (one of Alexander Stepanov's API design principles is "don't throw away useful information"), but I agree that should arguably be marked as @discardableResult.

mdznr

comment created time in 3 days

PR opened apple/swift-algorithms

Precompute LazyChunked's startIndex

<!-- Thanks for contributing to Swift Algorithms!

If this pull request adds new API, please add '?template=new.md'
to the URL to switch to the appropriate template.

Before you submit your request, please replace the paragraph
below with the relevant details, and complete the steps in the
checklist by placing an 'x' in each box:

- [x] I've completed this task
- [ ] This task isn't completed

-->

This PR adds a firstUpperBound stored property to the LazyChunked type to avoid computing the first chunk twice during iteration, similar to what the ChunkedByCount and SlidingWindows types do.

Checklist

  • [x] I've added at least one test that validates that my change is working, if appropriate
  • [x] I've followed the code style of the rest of the project
  • [x] I've read the Contribution Guidelines
  • [x] I've updated the documentation if necessary
+23 -29

0 comment

1 changed file

pr created time in 3 days

issue openedapple/swift-algorithms

Partition: Make mutating functions return `@discardableResult`

Using the mutating partitioning functions are useful even when the returned index isn’t used.

The Embracing Algorithms (WWDC 2018) session implements a bringForward(elementsSatisfying:) function on MutableCollection.<sup>1</sup> It uses stablePartition(by:) in its implementation, but doesn’t need its return value, resulting in a warning.

Actual behavior

extension MutableCollection {
	mutating func bringForward(elementsSatisfying predicate: (Element) -> Bool) {
		if let predecessor = indexBeforeFirst(where: predicate) {
			self[predecessor...].stablePartition(by: { !predicate($0) }) // ⚠️ Result of call to 'stablePartition(by:)' is unused
		}
	}
}

Expected behavior

extension MutableCollection {
	mutating func bringForward(elementsSatisfying predicate: (Element) -> Bool) {
		if let predecessor = indexBeforeFirst(where: predicate) {
			self[predecessor...].stablePartition(by: { !predicate($0) })
		}
	}
}

While it could be argued that bringForward(elementsSatisfying:) should return an Index as well, even that return value isn’t always needed to be used and should be marked as @discardableResult.

Checklist

  • [x] If possible, I've reproduced the issue using the main branch of this package
  • [x] I've searched for existing GitHub issues

  1. This implementation function can be seen on page 218 of the presentation slides PDF.

created time in 3 days

pull request commentapple/swift-algorithms

add suffix:while method

@CTMacUser I think that’s pretty much exactly what I imagined the implementation would look like.

Although, I think we might want to change

while result > start {

to

while result != start {

A lot of similar algorithms in the standard library use != instead of > or < for comparing indexes. I’ll have to do more research as to why that is. My initial guess is perhaps because implementations of custom indexes have slightly faster implementations of != than <. But either way, it would be good to have consistency here.

michiboo

comment created time in 4 days

pull request commentapple/swift-algorithms

add suffix:while method

What about something like (neither compiled nor tested):

extension BidirectionalCollection {
  public func suffix(
    while predicate: (Element) throws -> Bool
  ) rethrows -> SubSequence {
    let start = startIndex
    var result = endIndex
    while result > start {
      let previous = index(before: result)
      guard try predicate(self[previous]) else { break }

      result = previous
    }
    return self[result...]
  }
}

?

michiboo

comment created time in 4 days

pull request commentapple/swift-algorithms

All permutations

@mdznr Oh I see this is still a draft, let us know when you're ready for us to review it!

mdznr

comment created time in 4 days

MemberEvent

startedCreativeCodeBerlin/creative-coding-minilist

started time in 4 days

PR opened apple/swift-algorithms

Index offsetting for Product2

This PR adds implementations of index(_:offsetBy:) and index(_:offsetBy:limitedBy:) to the Product2 collection. There are ways to further reduce the amount of indices traversed, but this should perform well enough.

LIke Chain2, Product2's index offsetting behavior will now unfortunately perform slightly worse for non-random-access collections in specific scenarios, but there's not much we can do about that.

Checklist

  • [x] I've added at least one test that validates that my change is working, if appropriate
  • [x] I've followed the code style of the rest of the project
  • [x] I've read the Contribution Guidelines
  • [x] I've updated the documentation if necessary
+232 -10

0 comment

1 changed file

pr created time in 4 days

Pull request review commentapple/swift-algorithms

add suffix:while method

+//===----------------------------------------------------------------------===//+//+// This source file is part of the Swift Algorithms open source project+//+// Copyright (c) 2020 Apple Inc. and the Swift project authors+// Licensed under Apache License v2.0 with Runtime Library Exception+//+// See https://swift.org/LICENSE.txt for license information+//+//===----------------------------------------------------------------------===//++//===----------------------------------------------------------------------===//+// Suffix(while:)+//===----------------------------------------------------------------------===//++extension BidirectionalCollection {+  @inlinable+  public __consuming func Suffix(while predicate: (Element) throws -> Bool+  ) rethrows -> [Element] {+   var result = ContiguousArray<Element>()+   self.reverse()

I don’t believe reverse() can be used here (won’t compile), because it is a mutating function that reverses the elements of the collection in-place. This function, suffix(while:), isn’t mutating (and should remain that way), so it can’t use self.reverse() in its implementation.

It seems that you might have meant to use the non-mutating version of that function, reversed(), which returns a reversed collection:

    for element in self.reversed() {

However, this comment likely won’t be applicable when changing the function to return SubSequence instead.

michiboo

comment created time in 4 days

Pull request review commentapple/swift-algorithms

add suffix:while method

+//===----------------------------------------------------------------------===//+//+// This source file is part of the Swift Algorithms open source project+//+// Copyright (c) 2020 Apple Inc. and the Swift project authors
// Copyright (c) 2021 Apple Inc. and the Swift project authors
michiboo

comment created time in 4 days

Pull request review commentapple/swift-algorithms

add suffix:while method

+//===----------------------------------------------------------------------===//+//+// This source file is part of the Swift Algorithms open source project+//+// Copyright (c) 2020 Apple Inc. and the Swift project authors+// Licensed under Apache License v2.0 with Runtime Library Exception+//+// See https://swift.org/LICENSE.txt for license information+//+//===----------------------------------------------------------------------===//++//===----------------------------------------------------------------------===//+// Suffix(while:)+//===----------------------------------------------------------------------===//++extension BidirectionalCollection {+  @inlinable+  public __consuming func Suffix(while predicate: (Element) throws -> Bool+  ) rethrows -> [Element] {+   var result = ContiguousArray<Element>()+   self.reverse()

Consistent indentation

    var result = ContiguousArray<Element>()
    self.reverse()
michiboo

comment created time in 4 days

Pull request review commentapple/swift-algorithms

add suffix:while method

+//===----------------------------------------------------------------------===//+//+// This source file is part of the Swift Algorithms open source project+//+// Copyright (c) 2020 Apple Inc. and the Swift project authors
// Copyright (c) 2021 Apple Inc. and the Swift project authors
michiboo

comment created time in 4 days

Pull request review commentapple/swift-algorithms

add suffix:while method

+//===----------------------------------------------------------------------===//+//+// This source file is part of the Swift Algorithms open source project+//+// Copyright (c) 2020 Apple Inc. and the Swift project authors+// Licensed under Apache License v2.0 with Runtime Library Exception+//+// See https://swift.org/LICENSE.txt for license information+//+//===----------------------------------------------------------------------===//++//===----------------------------------------------------------------------===//+// Suffix(while:)+//===----------------------------------------------------------------------===//++extension BidirectionalCollection {+  @inlinable+  public __consuming func Suffix(while predicate: (Element) throws -> Bool+  ) rethrows -> [Element] {+   var result = ContiguousArray<Element>()+   self.reverse()+    for element in self {+      guard try predicate(element) else {+        break+      }+      result.append(element)+    }+    result.reverse()+    return Array(result)

This double-reverse operation and converting to Array shouldn’t be necessary. The last index of the collection can be retrieved with endIndex, then walked backwards using index(before:).

This would be similar to the implementation of prefix(while:)<sup>1</sup>, but a little bit trickier. Since endIndex is beyond the subscript-able range of a collection, the index has to be moved backwards before using it to subscript the collection, and ensuring it doesn’t go before the first element (start index). In SuffixTests.swift, I made some comments about test cases that will be important for ensuring that these cases are accounted for.


  1. https://github.com/apple/swift/blob/main/stdlib/public/core/Collection.swift#L1330
michiboo

comment created time in 4 days

Pull request review commentapple/swift-algorithms

add suffix:while method

+//===----------------------------------------------------------------------===//+//+// This source file is part of the Swift Algorithms open source project+//+// Copyright (c) 2020 Apple Inc. and the Swift project authors+// Licensed under Apache License v2.0 with Runtime Library Exception+//+// See https://swift.org/LICENSE.txt for license information+//+//===----------------------------------------------------------------------===//++import XCTest+import Algorithms++final class SuffixTests: XCTestCase {+  +  func testSuffix() {+    let a = 0...10+    XCTAssertEqualSequences(a.suffix(while: { $0 > 5 }), (6...10))+}
  }
}
michiboo

comment created time in 4 days

Pull request review commentapple/swift-algorithms

add suffix:while method

+//===----------------------------------------------------------------------===//+//+// This source file is part of the Swift Algorithms open source project+//+// Copyright (c) 2020 Apple Inc. and the Swift project authors+// Licensed under Apache License v2.0 with Runtime Library Exception+//+// See https://swift.org/LICENSE.txt for license information+//+//===----------------------------------------------------------------------===//++import XCTest+import Algorithms++final class SuffixTests: XCTestCase {+  
michiboo

comment created time in 4 days

Pull request review commentapple/swift-algorithms

add suffix:while method

+//===----------------------------------------------------------------------===//+//+// This source file is part of the Swift Algorithms open source project+//+// Copyright (c) 2020 Apple Inc. and the Swift project authors+// Licensed under Apache License v2.0 with Runtime Library Exception+//+// See https://swift.org/LICENSE.txt for license information+//+//===----------------------------------------------------------------------===//++import XCTest+import Algorithms++final class SuffixTests: XCTestCase {

Tests should be added to handle:

  • Empty input
  • Empty output (predicate doesn’t match the first element)
  • Predicate matches just the first element
  • Predicate matches all elements
michiboo

comment created time in 4 days

Pull request review commentapple/swift-algorithms

add suffix:while method

+//===----------------------------------------------------------------------===//+//+// This source file is part of the Swift Algorithms open source project+//+// Copyright (c) 2020 Apple Inc. and the Swift project authors+// Licensed under Apache License v2.0 with Runtime Library Exception+//+// See https://swift.org/LICENSE.txt for license information+//+//===----------------------------------------------------------------------===//++//===----------------------------------------------------------------------===//+// Suffix(while:)
// suffix(while:)
michiboo

comment created time in 4 days

Pull request review commentapple/swift-algorithms

add suffix:while method

+//===----------------------------------------------------------------------===//+//+// This source file is part of the Swift Algorithms open source project+//+// Copyright (c) 2020 Apple Inc. and the Swift project authors+// Licensed under Apache License v2.0 with Runtime Library Exception+//+// See https://swift.org/LICENSE.txt for license information+//+//===----------------------------------------------------------------------===//++//===----------------------------------------------------------------------===//+// Suffix(while:)+//===----------------------------------------------------------------------===//++extension BidirectionalCollection {+  @inlinable

Documentation should be added. Mirroring the documentation for prefix(while:) would be a good start.

michiboo

comment created time in 4 days

Pull request review commentapple/swift-algorithms

add suffix:while method

+//===----------------------------------------------------------------------===//+//+// This source file is part of the Swift Algorithms open source project+//+// Copyright (c) 2020 Apple Inc. and the Swift project authors+// Licensed under Apache License v2.0 with Runtime Library Exception+//+// See https://swift.org/LICENSE.txt for license information+//+//===----------------------------------------------------------------------===//++//===----------------------------------------------------------------------===//+// Suffix(while:)+//===----------------------------------------------------------------------===//++extension BidirectionalCollection {+  @inlinable+  public __consuming func Suffix(while predicate: (Element) throws -> Bool+  ) rethrows -> [Element] {

Can this return SubSequence instead?

prefix(while:) on Collection returns a SubSequence.<sup>1</sup>


  1. https://github.com/apple/swift/blob/main/stdlib/public/core/Collection.swift#L1328
michiboo

comment created time in 4 days

Pull request review commentapple/swift-algorithms

add suffix:while method

+//===----------------------------------------------------------------------===//+//+// This source file is part of the Swift Algorithms open source project+//+// Copyright (c) 2020 Apple Inc. and the Swift project authors+// Licensed under Apache License v2.0 with Runtime Library Exception+//+// See https://swift.org/LICENSE.txt for license information+//+//===----------------------------------------------------------------------===//++//===----------------------------------------------------------------------===//+// Suffix(while:)+//===----------------------------------------------------------------------===//++extension BidirectionalCollection {+  @inlinable+  public __consuming func Suffix(while predicate: (Element) throws -> Bool
  public __consuming func suffix(
    while predicate: (Element) throws -> Bool
michiboo

comment created time in 4 days

Pull request review commentapple/swift-algorithms

add suffix:while method

+//===----------------------------------------------------------------------===//+//+// This source file is part of the Swift Algorithms open source project+//+// Copyright (c) 2020 Apple Inc. and the Swift project authors+// Licensed under Apache License v2.0 with Runtime Library Exception+//+// See https://swift.org/LICENSE.txt for license information+//+//===----------------------------------------------------------------------===//++//===----------------------------------------------------------------------===//+// Suffix(while:)+//===----------------------------------------------------------------------===//++extension BidirectionalCollection {+  @inlinable+  public __consuming func Suffix(while predicate: (Element) throws -> Bool
  public __consuming func suffix(while predicate: (Element) throws -> Bool
michiboo

comment created time in 4 days

PR opened apple/swift-algorithms

add suffix:while method

<!-- Thanks for contributing to Swift Algorithms!

- [x] I've completed this task
- [ ] This task isn't completed

#62

Checklist

  • [ ] I've added at least one test that validates that my change is working, if appropriate
  • [ ] I've followed the code style of the rest of the project
  • [ ] I've read the Contribution Guidelines
  • [ ] I've updated the documentation if necessary
+51 -0

0 comment

2 changed files

pr created time in 5 days

issue closedapple/swift-algorithms

Permutations won't compile

Bildschirmfoto 2021-01-20 um 08 41 22

The function that was used is unknown on my side ? I use Swift 5.3 and Xcode 12.3, macOS 11.1

closed time in 5 days

nilsnilsnils
more