How to write any(s : SequenceType) in Swift - swift

Swift doesn't seem to have functions for any() or all() so I am trying to make my own. The closest I have gotten is
func any<S: SequenceType
where S.Generator.Element: BooleanType>
(sequence: S) -> Bool{
var __g = sequence.generate()
var first_element = __g.next()
if first_element == nil{
return false
}
return reduce(sequence, first_element!, {$0 || $1})
}
Edit: As per comments, this function should really look like this
func any<S: SequenceType
where S.Generator.Element: BooleanType>
(sequence: S) -> Bool{
return reduce(sequence, false, {$0 || $1})
}
The compiler tells me
'S.Generator.Element' is not convertible to 'Bool'
It seems to me I am explicitly telling the compiler that it is on the second line. What am I missing?

Your problem is that next returns an optional. That means reduce is expecting to return an optional and $0 is an optional. You would have to unwrap the optional to be able to use the || operator. You also don't know the the type is a Bool, just that it is a BooleanType. You would have to also convert it to an actual Bool by calling boolValue on it:
func any<S: SequenceType
where S.Generator.Element: BooleanType>
(sequence: S) -> Bool{
var __g = sequence.generate()
var first_element = __g.next()
if first_element == nil{
return false
}
return reduce(sequence, first_element!.boolValue, {$0 || $1})
}
However, in this case, I think simplicity is best:
func any<S: SequenceType
where S.Generator.Element: BooleanType>
(sequence: S) -> Bool{
for element in sequence {
if element.boolValue {
return true
}
}
return false
}
This is actually more efficient too because it returns as soon as it finds the first true instead of always going through the whole thing.

Related

Comparing array of force unwrapped optionals

I'm writing a test:
func test_arrayFromShufflingArray() {
var videos = [MockObjects.mockVMVideo_1(), MockObjects.mockVMVideo_2(), MockObjects.mockVMVideo_3()]
let tuple = ShuffleHelper.arrayFromShufflingArray(videos, currentIndex:1)
var shuffledVideos = tuple.0
let shuffleIndexMap = tuple.1
// -- test order is different
XCTAssert(videos != shuffledVideos, "test_arrayFromShufflingArray fail")
}
But on the last line I get the last line:
Binary operator '!=' cannot be applied to two '[VMVideo!]' operands
Arrays can be compared with == if the element type is Equatable:
/// Returns true if these arrays contain the same elements.
public func ==<Element : Equatable>(lhs: [Element], rhs: [Element]) -> Bool
But neither ImplicitlyUnwrappedOptional<Wrapped> nor Optional<Wrapped> conform to Equatable, even if the
underlying type Wrapped does.
Possible options are (assuming that VMVideo conforms to Equatable):
Change your code so that videos and shuffledVideos are
[VMVideo] arrays instead of [VMVideo!].
Compare the arrays elementwise:
XCTAssert(videos.count == shuffledVideos.count
&& !zip(videos, shuffledVideos).contains {$0 != $1 })
Define a == operator for arrays of implicitly unwrapped equatable
elements:
func ==<Element : Equatable> (lhs: [Element!], rhs: [Element!]) -> Bool {
return lhs.count == rhs.count && !zip(lhs, rhs).contains {$0 != $1 }
}
Swift can't tell how to compare two arrays to see if their contents are identical unless it knows how to compare individual elements. So you need to implement the == function on your class and adopt Equatable:
extension VMVideo: Equatable {
// nothing goes here, == function has to be at global scope
}
func ==(lhs: VMVideo, rhs: VMVideo) -> Bool {
// Up to you to determine what equality means for your object, e.g.:
return lhs.essentialProperty1 == rhs.essentialProperty1 &&
lhs.essentialProperty2 == rhs.essentialProperty2
}
EDIT To clarify how it interacts with NSObject and to troubleshoot your environment, please confirm the following:
class UnderstandsEqual: NSObject {}
let ok1: [UnderstandsEqual] = [UnderstandsEqual(), UnderstandsEqual()]
let ok2: [UnderstandsEqual] = [UnderstandsEqual(), UnderstandsEqual()]
ok1 == ok2 // no problem, evaluates to true
class DoesntUnderstand {}
let bad1: [DoesntUnderstand] = [DoesntUnderstand(), DoesntUnderstand()]
let bad2: [DoesntUnderstand] = [DoesntUnderstand(), DoesntUnderstand()]
bad1 == bad2 // produces a compile-time error
Martin R's answer was the better answer, but for this specific purpose I just converted to NSArray's and was able to use the == operator in Swift:
func test_arrayFromShufflingArray() {
let videos = [MockObjects.mockVMVideo_1(), MockObjects.mockVMVideo_2(), MockObjects.mockVMVideo_3()]
let videosNSArray: NSArray = videos.map { $0 }
let tuple = ShuffleHelper.arrayFromShufflingArray(videos, currentIndex:1)
let shuffledVideos = tuple.0
let shuffledVideosNSArray: NSArray = shuffledVideos.map { $0 }
// -- test order is different
XCTAssert(videosNSArray != shuffledVideosNSArray, "test_arrayFromShufflingArray fail")
// -- test elements are the same
let set = NSSet(array: videos)
let shuffledSet = NSSet(array: shuffledVideos)
XCTAssert(set == shuffledSet, "test_arrayFromShufflingArray fail")
}

Use AnySequence and anyGenerator in combination

Another question asked, essentially, how to implement a take function which would return the first n elements of a sequence. My answer was:
struct TakeFromSequenceSequence<S:SequenceType> : SequenceType {
var limit : Int
var sequence : S
func generate() -> AnyGenerator<S.Generator.Element> {
var generator = sequence.generate()
var limit = self.limit
return anyGenerator {
guard limit > 0 else {
return nil
}
limit = limit - 1
return generator.next()
}
}
}
extension SequenceType {
func take(count:Int) -> TakeFromSequenceSequence<Self> {
return TakeFromSequenceSequence(limit: count, sequence: self)
}
}
but it seems like I ought to be able to use AnySequence and anyGenerator to do it all inline in my take function:
extension SequenceType {
func take(count:Int) -> AnySequence<Self.Generator.Element> {
// cannot invoke initializer for type 'AnySequence<_>' with an argument list of type '(() -> _)'
return AnySequence({
var generator = self.generate()
var limit = count
// cannot invoke 'anyGenerator' with an argument list of type '(() -> _)'
return anyGenerator({
guard limit > 0 else {
return nil
}
limit = limit - 1
return generator.next()
})
})
}
}
Unfortunately, this yields multiple typing errors, mostly (I think) because type inference is failing.
Anybody have any suggestions on how to get this (using AnySequence and anyGenerator inline) to work?
(The answer is now based on Swift 2.2/Xcode 7.3. A solution for Swift 2.1 can be found in the edit history.)
The type of the closure passed to the AnySequence init method
must be specified explicitly:
extension SequenceType {
func take(count:Int) -> AnySequence<Generator.Element> {
return AnySequence { () -> AnyGenerator<Generator.Element> in
var generator = self.generate()
var limit = count
return AnyGenerator {
guard limit > 0 else {
return nil
}
limit = limit - 1
return generator.next()
}
}
}
}
Note that the (redundant) Self. in Self.Generator.Element is omitted, otherwise it does not compile.
Example:
let sequence = [1,2,3,4,5].take(2)
print(Array(sequence)) // [1, 2]
print(Array(sequence)) // [1, 2]
Alternatively, the method can be defined as
extension SequenceType {
func take(count:Int) -> AnySequence<Generator.Element> {
var generator = self.generate()
var limit = count
return AnySequence {
return AnyGenerator {
guard limit > 0 else {
return nil
}
limit = limit - 1
return generator.next()
}
}
}
}
Now the closure passed to the AnySequence init method is a "single-expression closure" and the type is inferred by the compiler.
But – as David Berry noted – the created sequence then behaves differently, the generate() method cannot be called repeatedly
with identical results:
let sequenceX = [1,2,3,4,5].take(2)
print(Array(sequenceX)) // [1, 2]
print(Array(sequenceX)) // []
This is permitted behavior, as stated in the SequenceType protocol reference:
... It is not correct to assume that a sequence will either be
"consumable" and will resume iteration, or that a sequence is a
collection and will restart iteration from the first element. A
conforming sequence that is not a collection is allowed to produce an
arbitrary sequence of elements from the second generator.
So one can choose among these implementations, dependent on the desired behavior.

How to compare one value against multiple values - Swift

Let's say that you have the code
if stringValue == "ab" || stringValue == "bc" || stringValue == "cd" {
// do something
}
Is there a way to shorten this condition or beautify it (preferably without using the switch statement)? I know that this code does NOT work:
if stringValue == ("ab" || "bc" || "cd") {
// do something
}
I've seen some complex solutions on other languages, but they seem language specific and not applicable to Swift. Any solutions would be appreciated.
let valuesArray = ["ab","bc","cd"]
valuesArray.contains(str) // -> Bool
You can create an extension like this:
extension Equatable {
func oneOf(other: Self...) -> Bool {
return other.contains(self)
}
}
and use it like this:
if stringValue.oneOf("ab", "bc", "cd") { ... }
Credit for the impl which saved me typing it: https://gist.github.com/daehn/73b6a08b062c81d8c74467c131f78b55/
Not that i am aware, you can do something like this though,
let validStrings = Set<String>(arrayLiteral:"ab", "bc", "cd")
if validStrings.contains(str) {
//do something
}
Use a Switch Statement.
switch stringValue {
case "ab", "bc", "cd":
print("Yay!")
default:
break
}
The construction ["some", "array"].contains("value") works, but is somewhat annoying:
It inverts the left-to-right order you may want to write.
Items in the array are not declared using Swift's type inference, often forcing you to include unnecessary information to please the compiler.
You can instead use Set(["value"]).isSubset(of: ["some", "array"]).
The benefit is especially apparent when working with enums:
enum SomeReallyReallyLongTypeName {
case one, two
}
struct Thing {
let value: SomeReallyReallyLongTypeName
}
let thing = Thing(value: .one)
if Set([thing.value]).isSubset(of: [.one, .two]){
// :)
// Left-to-right order
// You get nice type inference
}
if [SomeReallyReallyLongTypeName.one, .two].contains(thing.value) {
// :(
// Annoying to have "SomeReallyReallyLongTypeName" in the code
}
if someArray.contains(object) {
// contains
} else {
// does not contains
}
The above function returns bool value, then you write logic accordingly.
Just for fun, how about overloading functions over String:
if a.isOneOf("ab", "bc", "cd") {
print("yes")
}
extension String {
#inlinable
func isOneOf(_ first: String, _ second: String) -> Bool {
self == first || self == second
}
#inlinable
func isOneOf(_ first: String, _ second: String, _ third: String) -> Bool {
self == first || isOneOf(second, third)
}
#inlinable
func isOneOf(_ first: String, _ second: String, _ third: String, _ fourth: String) -> Bool {
self == first || isOneOf(second, third, fourth)
}
}
This gives you full performance benefits, as the compiler will be able to inline and tail call as much as it wants, at the cost of having to write as many overloads as you need in your code, and also not being able to pass arrays - but other answers deal with this too.
let a = 1
let b = 1
let c = 1
let d = 1
if a == b,a==c,a==d {
print("all of them are equal")
}
else {
print("not equal")
}

How do you write a generic function to do conditional downcasting in Swift?

My goal is to write something that can convert something like [AnyObject] to Result<[SomeObject], NSError> to easily do safe and chainable casting while working with a mixed Swift/Obj-C codebase. The conditional downcast operator as? seems to support that just fine, but I can't get a generic function working that utilizes that behavior. I've simplified the problem I'm encountering below:
class A { }
let obj = A()
let array: [AnyObject] = [obj]
func cast<T, U>(x: T, type: U.Type) -> U? {
if let x = x as? U {
return x
} else {
return nil
}
}
// This works
if let array = array as? [A] {
println(array)
}
// This works
println(cast(obj, A.self))
// This doesn't
println(cast(array, [A].self))
Note: This works in Swift 2.0, I don't know about 1.2, try it out
If you want to do something like this you'd have to overload your cast method with one for SequenceTypes:
func cast<T : SequenceType, U : SequenceType>(x: T, type: U.Type) -> [U.Generator.Element]? {
let y = x.map{ $0 as? U.Generator.Element }
if y.contains({ $0 == nil }) {
return nil
} else {
return y.flatMap{ $0 } // Swift 1.2 : y.map{ $0! }
}
}
EDIT: Changed according to your edit
Generally, Swift doesn't support GenericType<A> as? GenericType<B> cast, even if B is a subtype of A. Array<A> as? Array<B> is just a exception for our convenience.
There is a undocumented internal builtin function:
func _arrayConditionalDownCastElements<SourceElement, TargetElement>(a: Array<SourceElement>) -> [TargetElement]?
With my assumption, Swift implicitly calls this function when we do someArray as? [B]. But, with a generics type, just like your case, the Swift compiler cannot bind that to _arrayConditionalDownCastElements because it's unpredictable in compile time.
Anyway, you can call it manually, and implement cast as overloaded function:
func cast<T,U>(x:T, _: U.Type) -> U? {
return x as? U
}
func cast<T,U>(x:[T], _: [U].Type) -> [U]? {
return _arrayConditionalCast(x)
}
Similarly, there is _dictionaryDownCastConditional for Dictionary and _setDownCastConditional for Set:
func _dictionaryDownCastConditional<BaseKey, BaseValue, DerivedKey, DerivedValue>(source: Dictionary<BaseKey, BaseValue>) -> Dictionary<DerivedKey, DerivedValue>?
func _setDownCastConditional<BaseValue, DerivedValue>(source: Set<BaseValue>) -> Set<DerivedValue>?
Using this:
func cast<TKey,TValue, UKey, UValue>(x:[TKey: TValue], _: [UKey:UValue].Type) -> [UKey: UValue]? {
return _dictionaryDownCastConditional(x)
}
func cast<T, U>(x: Set<T>, _: Set<U>.Type) -> Set<U>? {
return _setDownCastConditional(x)
}
Again, they are undocumented. use them at your own risk :)

Recursion over a Swift Sliceable

I feel that I must be missing something obvious. Decomposing a list into the head and tail and then recursing over the tail is a standard functional programming technique, yet I'm struggling to do this for Sliceable types in Swift.
I have a recursive function that follows this pattern:
func recurseArray(arr: [Int]) -> [Int] {
guard let first = arr.first else {
return []
}
let rest = recurseArray(Array(dropFirst(arr)))
let next = rest.first ?? 0
return [first + next] + rest
}
Obviously the real code does a lot more than add each number to the next.
Note the call to Array(dropFirst(seq)). Converting to an Array is required since dropFirst actually returns an ArraySlice, and an ArraySlice isn't a Sliceable, so I can't pass it to my function.
I'm not sure what sort of optimization the compiler is capable of here, but it seems to me that creating a new array from a SubSlice unnecessarily won't be optimal. Is there a solution to this?
Furthermore, what I'd really like to do is create a version of this function that can take any Sliceable type:
func recurseSeq<T: Sliceable where T.Generator.Element == Int>(list: T) -> [Int] {
guard let first = list.first else {
return []
}
let rest = recurseSeq(dropFirst(list)) // <- Error - cannot invoke with argument type T.SubSlice
let next = rest.first ?? 0
return [first + next] + rest
}
This time I don't have a solution to the fact that I have a SubSlice. How can I achieve my goal?
It turns out that there is a generic solution. You need to add these generic requirements:
<
S : Sliceable where S.SubSlice : Sliceable,
S.SubSlice.Generator.Element == S.Generator.Element,
S.SubSlice.SubSlice == S.SubSlice
>
For the question posted, this gives:
func recurseSeq<
S : Sliceable where S.SubSlice : Sliceable,
S.SubSlice.Generator.Element == Int,
S.SubSlice.SubSlice == S.SubSlice,
S.Generator.Element == Int
>(list: S) -> [Int] {
guard let first = list.first else {
return []
}
let rest = recurseSeq(dropFirst(list))
let next = rest.first ?? 0
return [first + next] + rest
}
Here's a useful generic reduce on any sliceable:
extension Sliceable where
SubSlice : Sliceable,
SubSlice.Generator.Element == Generator.Element,
SubSlice.SubSlice == SubSlice {
func recReduce(combine: (Generator.Element, Generator.Element) -> Generator.Element) -> Generator.Element? {
return self.first.map {
head in
dropFirst(self)
.recReduce(combine)
.map {combine(head, $0)}
?? head
}
}
}
[1, 2, 3].recReduce(+) // 6
I can't take credit for this, the solution was posted on the Apple Development Forums.
It's a shame that the generic requirements are so involved for such a a basic operation - it's hardly intuitive! But I'm glad to have a solution...
Actually ArraySlice is Sliceable, so you can recurse on
ArraySlice<Int>:
func recurseArray(arr: ArraySlice<Int>) -> [Int] {
guard let first = arr.first else {
return []
}
let rest = recurseArray(dropFirst(arr))
let next = rest.first ?? 0
return [first + next] + rest
}
with a wrapper function which is called only once at the top level:
func recurseArray(arr: [Int]) -> [Int] {
return recurseArray(arr[arr.startIndex ..< arr.endIndex])
}
I don't have a solution for your second more general problem.
The API docs for Sliceable state that SubSlice should be
Sliceable itself (which is the case for all known Sliceable
types).
I have therefore the feeling that it should be possible by requesting
that T.SubSlice is itself sliceable with the identical SubSlice
type, however this does not compile:
func recurseSeq<T: Sliceable where T.Generator.Element == Int,
T.SubSlice : Sliceable,
T.SubSlice.SubSlice == T.SubSlice>(list: T.SubSlice) -> [Int] {
guard let first = list.first else {
return []
}
let rest = recurseSeq(dropFirst(list) as T.SubSlice)
// error: cannot invoke 'recurseSeq' with an argument list of type '(T.SubSlice)'
let next = rest.first ?? 0
return [first + next] + rest
}
The compiler accepts that dropFirst(list) can be cast to T.SubSlice,
but refuses to call recurseSeq() on that value, which I do not
understand.
Alternatively, you can recurse on a GeneratorType:
func recurseGen<G: GeneratorType where G.Element == Int>(inout gen: G) -> [Int] {
guard let first = gen.next() else {
return []
}
let rest = recurseGen(&gen)
let next = rest.first ?? 0
return [first + next] + rest
}
with a wrapper that takes a SequenceType:
func recurseSeq<T: SequenceType where T.Generator.Element == Int>(list: T) -> [Int] {
var gen = list.generate()
return recurseGen(&gen)
}
Arrays and array slices all conform to SequenceType, so that should
work in all your cases.
Creating an array in every iteration doesn't seem like a good idea. I don't know if the compiler optimizes it somehow, but you could probably find a different solution.
For example, in this case, you could drop de recursion and use a for loop instead that modifies the array in place.
func recurseArray2(var a: [Int]) -> [Int] {
for var i = a.count-1; i > 0; i-- {
a[i-1] += a[i]
}
return a
}