What’s the best way to flip between Enum state?
enum EVEN_ODD { case Even, Odd }
var __mode_bit = EVEN_ODD.Even;
for _ in 1...5 {
__mode_bit = (__mode_bit == .Even) ? .Odd : .Even
}
Could the __mode_bit?: be simplified?
Take a look at the Apple documentation on Booleans, they give an example of a Boolean typed enum: https://developer.apple.com/swift/blog/?id=8
Since you can create an enum from raw, you could toggle the value by:
let true = MyBool(rawValue: false)
Simon
My preference would be to make the enum conform to _Incrementable (which, for some reason, is underscored even though it seems like a reasonable non-internal protocol to me), and make it wrap around.
enum EvenOdd {
case Even, Odd
}
extension EvenOdd: _Incrementable {
func successor() -> EvenOdd {
return self == .Even ? .Odd : .Even
}
}
EvenOdd.Odd.successor() // == .Even
This also gives you a pre/post increment operator for free:
var bit = EvenOdd.Odd
++bit // bit now Even
++bit // bit now Odd
++bit // bit now Even etc
Enums can have the ! operator implemented for them.
enum Parity { case Even, Odd }
prefix func !(a: Parity) -> Parity {
return a == .Even ? .Odd : .Even
}
Now I can stuff like
var parity_mode = Parity.Even
parity_mode = !parity_mode // .Odd
Based on #Simon Gladman answer with reference to Boolean
Related
I just found another way to make a great use of protocols and protocol extensions in Swift by extending the Optional protocol to add a function so I can provide default values.
I wrote a blog post about this here: https://janthielemann.de/random-stuff/providing-default-values-optional-string-empty-optional-string-swift-3-1/
The gist of the post is that I needed a clean and easy way to provide default values for optional String which are nil or empty. To do this, I created a Emptyable protocol end extended the Optional protocol like so:
protocol Emptyable {
var isEmpty: Bool { get }
}
extension Optional where Wrapped: Emptyable {
func orWhenNilOrEmpty<T: Emptyable>(_ defaultValue: T) -> T {
switch(self) {
case .none:
return defaultValue
case .some(let value) where value.isEmpty:
return defaultValue
case .some(let value):
return value as! T
}
}
}
extension String: Emptyable {}
Now the question is: Is there a way I can get rid of the Emptyable protocol and instead have a conditional check whether or not a property or function is implemented by the generic type so that I automatically get orWhenNilOrEmpty() for each and every type which has isEmpty?
UPDATE
As suggested by Paulo, the T generic is actually not needed and I created a operator for even quicker access and more convenient usage (at least I think so. Feel free to correct me, I'm always happy to learn new things and improve myself).
I call it the "not empty nil coalescing" operator (who can come up with a better names? I feel like I suck at naming things :/ ). Hopefully some day it helps somebody:
protocol Emptyable {
var isEmpty: Bool { get }
}
infix operator ???: NilCoalescingPrecedence
extension Optional where Wrapped: Emptyable {
func orWhenNilOrEmpty(_ defaultValue: Wrapped) -> Wrapped {
switch(self) {
case .none:
return defaultValue
case .some(let value) where value.isEmpty:
return defaultValue
case .some(let value):
return value
}
}
static func ???(left: Wrapped?, right: Wrapped) -> Wrapped {
return left.orWhenNilOrEmpty(right)
}
}
extension String: Emptyable {}
extension Array: Emptyable {}
extension MyStruct: Emptyable {
let text: String
let number: Int
var isEmpty: Bool { return text.isEmpty && number == 0 }
init(text: String, number: Int) {
self.text = text
self.number = number
}
}
let mandatoryNotEmptyString = optionalOrEmptyString ??? "Default Value"
let mandatoryNotEmptyStruct = optionalOrEmptyStruct ??? MyStruct(name: "Hello World", number: 1)
No, you cannot query if an object or value has a certain property as a constraint on an extension without using a protocol. That would require reflection in a way that is currently not implemented in Swift. Also, an isEmpty property could have different meanings for different types, so testing for the existence of a method or property instead of a protocol could lead to unexpected behaviour.
You could just write
if let unwrappedString = optionalString, !unwrappedString.isEmpty {
// Do stuff
} else {
// Use default value
}
No protocol or extension required and very readable.
In Swift 4, which is coming out this fall, String will conform to BidirectionalCollection, which inherits from Collection. The Collection protocol provides an isEmpty property, so your extension could be
extension Optional where Wrapped: Collection {
// ...
}
But even then you should consider to set empty strings to nil when storing them in the first place, because you now have two states (nil and empty) which seem to represent the exact same thing.
Consider this code:
enum Type {
case Foo(Int)
case Bar(Int)
var isBar: Bool {
if case .Bar = self {
return true
} else {
return false
}
}
}
That's gross. I would like to write something like this instead:
enum Type {
case Foo(Int)
case Bar(Int)
var isBar: Bool {
return case .Bar = self
}
}
But such a construct does not seem to exist in Swift, or I cannot find it.
Since there's data associated with each case, I don't think it's possible to implement the ~= operator (or any other helper) in a way that's equivalent to the above expression. And in any case, if case statements exist for free for all enums, and don't need to be manually implemented.
Thus my question: is there any more concise/declarative/clean/idiomatic way to implement isBar than what I have above? Or, more directly, is there any way to express if case statements as Swift expressions?
UPDATE 2:
Another workaround... Create a var that returns an Int ONLY based on the case, then use a static (or instance, I thought static looked cleaner) method to test equivalence of just the case. It won't clash with Equatable, you don't have to overload an operator (unless you want to replace the static method with one), and you also wouldn't have to create separate var isFoo, var isBar, etc.
I know you used this example to ask a more generic question (how can I use 'if case' as an expression?) but if that's not possible, this may be a valid workaround. I apologize if this treats "the symptoms" not "the problem"
enum Something{
case Foo(Int)
case Bar(Int)
static func sameCase(a: Something, b: Something) -> Bool {
return a.caseValue == b.caseValue
}
var caseValue: Int {
switch self {
case .Foo(_):
return 0
case .Bar(_):
return 1
}
}
//if necessary
var isBar: Bool {
return Something.sameCase(self, b: Something.Bar(0))
}
}
Something.sameCase(.Bar(0), b: .Foo(0)) // false
Something.sameCase(.Bar(1), b: .Foo(2)) // false
Something.sameCase(.Foo(0), b: .Foo(0)) // true
Something.sameCase(.Bar(1), b: .Bar(2)) // true
Something.Bar(0).isBar // true
Something.Bar(5).isBar // true
Something.Foo(5).isBar // false
UPDATE 1:
Ok, so this seems to work. If you overload the == operator to ignore values and return true only when both enums are the same case, you can pass any value in your isFoo method and still determine the type.
I'm assuming you will need to customize this function to accommodate the the associated values, but it seems like a step in the right direction
enum Something {
case Foo(Int)
case Bar(Int)
var isFoo: Bool {
return self == .Foo(0) // number doesn't matter here... see below
}
}
func ==(a: Something, b: Something) -> Bool {
switch (a,b) {
case (.Bar(_), .Bar(_)):
return true
case (.Foo(_), .Foo(_)):
return true
default:
return false
}
}
let oneFoo = Something.Foo(1)
let twoFoo = Something.Foo(2)
let oneBar = Something.Bar(1)
let twoBar = Something.Bar(2)
oneFoo == twoFoo // true
oneFoo == oneFoo // true
oneFoo == oneBar // false
oneFoo == twoBar // false
OLD:
You can use self and the case name to directly check which case it is, you don't have to use the case keyword. Hopefully this will work for your situation:
enum Something{
case Foo(Int)
case Bar(Int)
var isFoo: Bool {
switch self {
case Foo:
return true
case Bar:
return false
}
}
}
So, there is a neater way, but requires a 3rd-party package: CasePaths
The idea is they work similarly to KeyPaths, and they come with a / operator to trigger it. There is also a ~= operator to check if a CasePath matches an instance.
So, you can achieve something like your original example like so:
import CasePaths
enum Type {
case Foo(Int)
case Bar(Int)
var isBar: Bool {
/Self.Bar ~= self
}
}
You can also get the value:
extension Type {
/// Returns the `Int` if this is a `Bar`, otherwise `nil`.
var barValue: Int? {
(/Self.Bar).extract(from: self)
}
}
You can do several other useful things with CasePaths as well, such as extracting the Foo values in an array of Type values:
let values: [Type] = [.Foo(1), .Bar(2), .Foo(3), .Foo(4), .Bar(5)]
let foos = values.compactMap(/Type.Foo) // [1, 3, 4]
let bars = values.compactMap(/Type.Bar) // [2, 5]
I'm sure there is somewhat of a performance cost, but it may not be an issue in your context.
I have a similar wondering, and I kept searching for some work arounds about this, and landed on this page. I came up with code like this to compromise.
fileprivate enum TypePrimitive {
case foo
case bar
}
enum Type {
case foo(Int)
case bar(Int)
fileprivate var primitiveType: TypePrimitive {
switch self {
case .foo(_): return .foo
case .bar(_): return .bar
}
}
var isFoo: Bool { self.primitiveType == .foo }
var isBar: Bool { self.primitiveType == .bar }
}
I hope Apple will provide better solution by adding some features in Swift language.
Are you looking for the ? operator ?
documentation is here under the Ternary Conditional Operator title.
Can I make an Array extension that applies to, for instance, just Strings?
As of Swift 2, this can now be achieved with protocol extensions,
which provide method and property implementations to conforming types
(optionally restricted by additional constraints).
A simple example: Define a method for all types conforming
to SequenceType (such as Array) where the sequence element is a String:
extension SequenceType where Generator.Element == String {
func joined() -> String {
return "".join(self)
}
}
let a = ["foo", "bar"].joined()
print(a) // foobar
The extension method cannot be defined for struct Array directly, but only for all types
conforming to some protocol (with optional constraints). So one
has to find a protocol to which Array conforms and which provides all the necessary methods. In the above example, that is SequenceType.
Another example (a variation of How do I insert an element at the correct position into a sorted array in Swift?):
extension CollectionType where Generator.Element : Comparable, Index : RandomAccessIndexType {
typealias T = Generator.Element
func insertionIndexOf(elem: T) -> Index {
var lo = self.startIndex
var hi = self.endIndex
while lo != hi {
// mid = lo + (hi - 1 - lo)/2
let mid = lo.advancedBy(lo.distanceTo(hi.predecessor())/2)
if self[mid] < elem {
lo = mid + 1
} else if elem < self[mid] {
hi = mid
} else {
return mid // found at position `mid`
}
}
return lo // not found, would be inserted at position `lo`
}
}
let ar = [1, 3, 5, 7]
let pos = ar.insertionIndexOf(6)
print(pos) // 3
Here the method is defined as an extension to CollectionType because
subscript access to the elements is needed, and the elements are
required to be Comparable.
UPDATE: Please See Martin's answer below for Swift 2.0 updates. (I can't delete this answer since it is accepted; if Doug can accept Martin's answer, I'll delete this one to avoid future confusion.)
This has come up several times in the forums, and the answer is no, you can't do this today, but they get that it's a problem and they hope to improve this in the future. There are things they would like to add to stdlib that also need this. That's why there are so many free functions is stdlib. Most of them are work-arounds for either this problem or the "no default implementation" problem (i.e. "traits" or "mixins").
This has already been answered by the three wise-men above ;-) , but I humbly offer a generalization of #Martin's answer. We can target an arbitrary class by using "marker" protocol that is only implemented on the class that we wish to target. Ie. one does not have to find a protocol per-se, but can create a trivial one for using in targeting the desired class.
protocol TargetType {}
extension Array:TargetType {}
struct Foo {
var name:String
}
extension CollectionType where Self:TargetType, Generator.Element == Foo {
func byName() -> [Foo] { return sort { l, r in l.name < r.name } }
}
let foos:[Foo] = ["c", "b", "a"].map { s in Foo(name: s) }
print(foos.byName())
You still haven't given a use case, despite many requests in comments, so it's hard to know what you're after. But, as I've already said in a comment (and Rob has said in an answer), you won't get it literally; extensions don't work that way (at the moment).
As I said in a comment, what I would do is wrap the array in a struct. Now the struct guards and guarantees the string's type, and we have encapsulation. Here's an example, though of course you must keep in mind that you've given no indication of the kind of thing you'd really like to do, so this might not be directly satisfying:
struct StringArrayWrapper : Printable {
private var arr : [String]
var description : String { return self.arr.description }
init(_ arr:[String]) {
self.arr = arr
}
mutating func upcase() {
self.arr = self.arr.map {$0.uppercaseString}
}
}
And here's how to call it:
let pepboys = ["Manny", "Moe", "Jack"]
var saw = StringArrayWrapper(pepboys)
saw.upcase()
println(saw)
Thus we have effectively insulated our string array into a world where we can arm it with functions that apply only to string arrays. If pepboys were not a string array, we couldn't have wrapped it in a StringArrayWrapper to begin with.
I have an enum in Swift:
enum Orientation: Int
{
case Rot_0 = 0, Rot_90, Rot_180, Rot_270
and a non-static method within my enum designed to shift the orientation clockwise or counterclockwise:
func rotate(clockwise: Bool)
{
var nextRawValue = self.rawValue + (clockwise ? 1 : -1)
if nextRawValue < Orientation.Rot_0.rawValue
{
nextRawValue = Orientation.Rot_270.rawValue
}
else if nextRawValue > Orientation.Rot_270.rawValue
{
nextRawValue = Orientation.Rot_0.rawValue
}
self = Orientation(rawValue: nextRawValue)
}
The the compiler is telling me that you cannot assign to self in a method. I'm having trouble understanding why this isn't possible.
The only thing I can think of is having a static method rotate(orientation: Orientation, clockwise: Bool), but in this case, the return value must be explicitly assigned back to the enum variable, and that just feels like bad coding to me. It seems like it would be much more useful to say myOrientation.rotate() and have the value changed implicitly.
Is there an elegant solution to this problem?
Thanks guys!
When you're going to modify a value type (i.e., struct or enum) in a method, you need to mark it as mutating. This will make the method usable by mutable instances (declared with var ...) but not immutable instances (let ...):
mutating func rotate(clockwise: Bool)
{
var nextRawValue = self.rawValue + (clockwise ? 1 : -1)
if nextRawValue < Orientation.Rot_0.rawValue
{
nextRawValue = Orientation.Rot_270.rawValue
}
else if nextRawValue > Orientation.Rot_270.rawValue
{
nextRawValue = Orientation.Rot_0.rawValue
}
self = Orientation(rawValue: nextRawValue)!
}
Note that fixing the mutating error reveals another -- Orientation(rawValue: nextRawValue) returns an optional, so you need to unwrap it before you can assign to self. If you've implemented the prior logic correctly, you should be safe in using the force unwrapping operator !.
enum have a property named 'hashValue' which is its index inside the enum.
Now my question is, is it possible to access its value by using a number? Ex: let variable:AnEnum = 0
If you want to map enum values to integers, you should do so directly with raw values. For example (from the Swift Programming Language: Enumerations):
enum Planet: Int {
case Mercury = 1, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
}
let possiblePlanet = Planet(rawValue: 7)
I don't believe there's any documentation promising that an enum's hashValue is anything in particular (if you have a link, I've be very interested). In the absence of that, you should be explicit in your assignment of raw values.
enum Opponent: String {
case Player
case Computer
static func fromHashValue(hashValue: Int) -> Opponent {
if hashValue == 0 {
return .Player
} else {
return .Computer
}
}
}
Explanation:
Since there is no way to get back an enum value from its hashValue, you have to do it manually. It's not pretty, but it works. You essentially create a function that allows you to pass in the index of the value you want and manually return that enum value back to the caller. This could get nasty with an enum with tons of cases, but it works like a charm for me.
Swift 4, iOS 12:
Simply make your enum with explicitly setting raw type (like Int in below example):
enum OrderStatus: Int {
case noOrder
case orderInProgress
case orderCompleted
case orderCancelled
}
Usage:
var orderStatus: OrderStatus = .noOrder // default value
print(orderStatus.rawValue) // it will print 0
orderStatus = .orderCompleted
print(orderStatus.rawValue) // it will print 2
Swift 4.2 🔸(Based on previous answer by #Stephen paul)
This answer uses switch instead of if/else clauses. And returns optional as your not garantueed that the hash provided will match.
enum CellType:String{
case primary,secondary,tierary
/**
* NOTE: Since there is no way to get back an enum value from its hashValue, you have to do it manually.
* EXAMPLE: CellType.fromHashValue(hashValue: 1)?.rawValue//👉primary
*/
static func fromHashValue(hashValue: Int) -> CellType? {
switch hashValue {
case 0:
return .primary
case 1:
return .secondary
case 2:
return .tierary
default:
return nil
}
}
}
Your requirement is to have this line of code working, where 0 is the hashValue of the enum variable (note that starting with Xcode 10, 0 is never a valid hashValue...):
let variable:AnEnum = 0
This is simply done by making your enum ExpressibleByIntegerLiteral and CaseIterable:
extension AnEnum: CaseIterable, ExpressibleByIntegerLiteral {
typealias IntegerLiteralType = Int
public init(integerLiteral value: IntegerLiteralType) {
self = AnEnum.allCases.first { $0.hashValue == value }!
}
}
The CaseIterable protocol is natively available with Swift 4.2, and you can implement it yourself for older swift versions (Swift 3.x, 4.x) using the code from https://stackoverflow.com/a/49588446/1033581.
Actually, with Swift 4.2, the hashValue is not the index inside the enum anymore.
Edit: Just found a safer way to achieve that. You can use the CaseIterable (Swift 4.2) and pick the desired case in the allCases collection.
enum Foo: CaseIterable {
case bar
case baz
init?(withIndex index: Int) {
guard Foo.allCases.indices ~= index else { return nil }
self = Foo.allCases[index]
}
}
Foo(withIndex: 0) // bar
Foo(withIndex: 1) // baz
Foo(withIndex: 2) // nil
Note: I'm leaving this little trick here, because playing with unsafe pointer is fun, but please, do not use this method to create a case with an index.
It relies on Swift memory representation which might change without notice, and is really unsafe because using a wrong index produce a runtime error.
That being said, in Swift, a case is represented using an Int in raw memory. So you can use this to build a case using unsafe pointers.
enum Foo {
case bar
case baz
init(withIndex index: UInt8) {
var temp: Foo = .bar
withUnsafeMutablePointer(to: &temp) { pointer in
let ptr = UnsafeMutableRawPointer(pointer).bindMemory(to: UInt8.self, capacity: 1)
ptr.pointee = index
}
self = temp
}
}
Foo(withIndex: 0) // bar
Foo(withIndex: 1) // baz
Foo(withIndex: 2) // runtime error !