I tried to create enum, which elements will be copied of another enum, like this:
enum Modes {
case mode1
case mode2
case additionalMode1
case additionalMode2
}
enum GeneralModes {
case mode1
case mode2
}
I have no idea how to do this. Need some backup.
Thanks for all answers and ideas.
You can't make an enum inherit from another enum and there is no built-in way to make your enum implement all cases that another enum implemented.
One possible workaround would be to give Modes a case with an associated value, which will be of type GeneralModes.
enum Modes {
case general(GeneralModes)
case additionalMode1
case additionalMode2
}
enum GeneralModes {
case mode1
case mode2
}
Then you can create a variable of type Modes with a value of mode1 like
let mode1 = Modes.general(.mode1)
Related
Optional in Swift allows for magic where switch-ing over an optional enum flattens the cases into a single switch statement.
Given:
enum Foo {
case bar, baz
}
You can:
let foo: Foo? = .bar
switch foo {
case .bar:
break
case .baz:
break
case nil:
break
Here, Optional is an enum and Foo is an enum, but just one single statement is enough to cover all cases of both.
Question: can I declare my own enum inside another enum so that the cases can be handled in a flat way too?
So that I could:
enum Foo<Bar> {
case nope
case dope(Bar)
}
enum Baz {
case yep
}
let b: Foo<Baz> = .dope(.yep)
switch b {
case .nope:
break
case .yep:
break
}
Maybe if I call the case Foo.dope as Foo.some? Maybe there is an annotation that I can use?
You could do this with …
switch b {
case .nope: // stuff
case .dope(.yep): // other stuff
case .dope(.someOtherCase): // more stuff
}
Responding to your comment…
Imagine you could flatten it like you said. How would you deal with…
enum Foo {
case a
case b(Bar)
case c(Bar)
}
If you are allowed to exclude the .b from the switch then there is no way to differentiate between .b and .c.
I want to define an enum case which is recursively defined by a particular instance of the same enum
enum Menu {
case item(String)
case submenu([.item]) // i want a submenu to be defined by an array of items
}
the submenu case isn't correct:
case submenu([.item])
how can I confine it?
All cases of an enum are of the same enum type, so you cannot declare an Array that can only hold a specific case of an enum.
However, you can achieve your goals by creating 2 enums instead of one and making the Menu.submenu enum case take the other enum as its associated value.
enum Menu {
case item(MenuItem)
case submenu([MenuItem])
}
enum MenuItem {
case item(String)
}
Then you can use it like
let menu = Menu.item(.item("main"))
let submenu = Menu.submenu([.item("a"), .item("b")])
Background
I have an enum which, simplified, goes like this:
enum Container<T> {
case a(T)
case b(T)
case c
}
I want to be able to instantiate this with a few different types for the generic and use typealias for that:
typealias IntContainer = Container<Int>
typealias FloatContainer = Container<Float>
Problem
So far, this is all fine. However, I also want to create a recursive instance of this:
typealias CyclicContainer = Container<CyclicContainer>
Swift reports this with a compile error:
Type alias 'CyclicContainer' references itself
… This error is still reported when I change the Container declaration to:
indirect enum Container<T>
This is a bit annoying, because this would be wholesome and compiling Swift:
indirect enum CyclicContainer {
case a(CyclicContainer)
case b(CyclicContainer)
case c
}
Workaround 1
There is a work around for this. I can declare, for example:
indirect enum CyclicContainer {
case container(Container<CyclicContainer>)
}
… However, this becomes awkward for concise descriptions of a CyclicContainer instance:
let cyclicContainer: CyclicContainer = .container(.a(.container(.b(.container(.c)))))
Instead of just:
let cyclicContainer: CyclicContainer = .a(.b(.c))
Workaround 2
I could also simply create a separate enum for the recursive case, as shown earlier:
indirect enum CyclicContainer {
case a(CyclicContainer)
case b(CyclicContainer)
case c
}
However, I'll need to: create functions to convert between CyclicContainer and Container; re-implement various member functions that exist on Container<T>; and keep the two types in sync in future if I add a new case or change a case name.
This isn't terribly arduous and it's the approach I'm leaning towards. But it seems a shame to have to do this when Swift can handle an indirect enum completely happily, but not when its induced by instantiation of a generic argument on the enum.
Question
Is there a better way?
The Apple documentation says
Every switch statement must be exhaustive. That is, every possible
value of the type being considered must be matched by one of the
switch cases.
So in new Xcode I have placed a code like this
println(UInt16.min); // Output : '0'
println(UInt16.max); // Output : '65535'
var quantity : UInt16 = 10;
switch quantity {
case 0...65535: //OR case UInt16.min...UInt16.max:
println();
default:
println();
}
Now if i remove the default section I get a compiler error:
Switch must be exhaustive
Do you want to add missing cases? Fix
So my question is for a case that I have mentioned as case 0...65535: have I not mentioned all the case values for an UInt16 ?? But still I am getting an error ?? Why am I getting this error, Did i miss something ??
Swift only truly verifies that a switch block is exhaustive when working with enum types. Even a switching on Bool requires a default block in addition to true and false:
var b = true
switch b {
case true: println("true")
case false: println("false")
}
// error: switch must be exhaustive, consider adding a default clause
With an enum, however, the compiler is happy to only look at the two cases:
enum MyBool {
case True
case False
}
var b = MyBool.True
switch b {
case .True: println("true")
case .False: println("false")
}
If you need to include a default block for the compiler's sake but don't have anything for it to do, the break keyword comes in handy:
var b = true
switch b {
case true: println("true")
case false: println("false")
default: break
}
Part of why you see that error because the compiler can't verify that switch is exhaustive without running code. The expression 0...65535 creates a ClosedInterval struct, and when the switch statement executes it has to ask that struct if the value quantity is in the interval. There's room for that to change at run time, so the compiler can't check it at compile time. (See the Halting Problem.)
More generally, the compiler can't detect an exhaustive switch for integer values — even if you add specific cases for every integer value (case 0: ... case 1: ... ... case 65535:), it doesn't know your switch is exhaustive. (Theoretically it could, though: consider filing a feature request about this if it's something you'd like to see.)
As it stands, there are two scenarios where Swift can detect completeness and allow you to omit the default clause: enums and value binding in tuples. #NateCook's answer covers enums — if you switch on an enum value and have a case in your switch for every case in the enum, you don't need a default. You also don't need a default label if you switch on a tuple and bind every possible combination of values, as seen in the Swift book:
switch anotherPoint {
case (let x, 0):
println("on the x-axis with an x value of \(x)")
case (0, let y):
println("on the y-axis with a y value of \(y)")
case let (x, y):
println("somewhere else at (\(x), \(y))")
}
You might generalize this rule as "if the type system knows about the possible values of your type, it can detect switch completeness", but the fact that there's a level on which the type system doesn't know the range of possible (e.g.) UInt32 values is sort of splitting hairs...
Swift 4.1. Either you need to specify all cases or Just include default block inside switch statement.
(As of Swift 4.2, and probably earlier): I have a helper function that converts a Bool? into the selectedSegmentIndex for a UISegmentedControl with 2 segments. If the value is nil then neither segment should be selected. My function uses a switch, which returns the appropriate segment index for true or false values, and uses this to explicitly test for the nil and satisfy the compiler's need for it to be exhaustive:
case nil: // only remaining possible value
fallthrough
default:
return UISegmentedControl.noSegment
Technically, the case nil: fallthrough isn't required because the default: will suffice, but this syntax may be useful if you want to explicitly test a value to make the code more self-documenting, or perhaps in another situation.
Check if your enum was initialised as an optional which could be either case or nil
Is it possible in Swift to pattern match and extract the initial value (now cast) at the same time?
For example, if I had these enums:
enum Inner {
case a(Int)
case b(Int)
}
enum Outer {
case one
case two(Inner)
}
and I wanted to match Outer.two(Inner.a(1)) and have have a variable cast to that at the same time
let value: Any // Could be anything :|
switch value {
case let a as Outer.two(Inner.a(1)):
// Do something which needs `a`
default"
// Do some other things
}
Obviously, that doesn't work because as only casts to types.
I've also tried
case Outer.two(let a) where a == Inner.a(1):
case let Outer.two(.a(1)) = a: // i.e. the syntax in "guard case let ..."
which don't work. (NB The first would work, but implementing == isn't an option for me, annoyingly)
FYI: Scala lets you do it with the # operator, something like this:
case a # Outer.two(Inner.a(1)):
Is there a syntax which can do this, or do I need to rethink how I'm solving my problem?
I don't think there is an equivalent pattern to
case a # Outer.two(Inner.a(1)): in Swift. Here is a possible
workaround:
switch value {
case Outer.two(Inner.a(1)):
let a = Inner.a(1)
// Do something which needs `a`
default:
// Do some other things
}