titaniumdecoy
titaniumdecoy

Reputation: 19251

Why do two distinct array literals equal each other in Swift?

Why does the expression

import Foundation
["a", "b", "c"] == ["c", "b", "a"]

evaluate to true in a Swift playground?

(The expression evaluates to false when Foundation is not imported.)

Upvotes: 3

Views: 135

Answers (2)

user652038
user652038

Reputation:

Josh's answer is close, but not quite right. Option-click on the equals operator. Your literals are Foundation.CharacterSets.

public static func == (lhs: CharacterSet, rhs: CharacterSet) -> Bool

For literal resolution, the compiler is going to search

  1. The module you're working in.
  2. Your imports.
  3. The Swift standard library. (Which has some special module-scope-disambiguation rule where implicitly-typed literals are Arrays, because that makes working with the language easier for the most part.)

enter image description here

Is this a bug of ambiguity? Yes. Is it resolvable? I doubt it. I bet it's broken because nobody has been able to get the performance to be good enough if it did an exhaustive search. But please, log a bug, find out, and report back!

Upvotes: 5

Josh Homann
Josh Homann

Reputation: 16327

Swift.Set conforms to ExpressibleByArrayLiteral and it appears that when you compare two ArrayLiterals the compiler does in fact choose to evaluate them as Set's. you can confirm that its true by doing this:

import Foundation
let a = ["a", "b", "c"]
let b = ["c", "b", "a"]

print(["a", "b", "c"] == ["c", "b", "a"])
print(["a", "b", "c"] as Set<String> == ["c", "b", "a"] as Set<String>)
print(["a", "b", "c"] as [String] == ["c", "b", "a"] as [String])
print(a == b)
true
true
false
false

TLDR if you don't annotate the type of an array literal the compiler is free to coerce the type to any type that it chooses to infer as long as it conforms to ExpressibleByArrayLiteral.

Upvotes: 2

Related Questions