this is my code
public enum Key {
enum A: String {
case x
}
enum B: String {
case y
}
enum C: String {
case z
}
}
Now I need to compare to which nesting enum the argument belongs,
it is possible something like this?
func readString(key: Key) {
switch key {
case .A:
//do smth
default:
break
}
}
I have found the solution to specifically my problem:
enum Key {
case a(A)
case b(B)
case c(C)
enum A: String {
case x
}
enum B: String {
case y
}
enum C: String {
case z
}
}
After this we can use switch-case.
But it will be better to do in the following way:
Creating protocol
Subscribe
Call this in generic
Something like this
protocol CKey: RawRepresentable where RawValue == String {
var nestingEnum: String { get }
}
enum Key {
enum A: String, CKey {
case x
var nestingEnum: String {
return "X"
}
}
enum B: String, CKey {
case y
var nestingEnum: String {
return "Y"
}
}
enum C: String, CKey {
case z
var nestingEnum: String {
return "Z"
}
}
}
And call this
func read<Item: CKey>(for key: Item) -> String {
//now we can read key.nestingEnum
}
Related
I want to access to value of my enum in case, I made a switch for getting access to value, but as you can see I am reaping my codes, how can i do this in better way?
enum TestEnum {
case a(value: Int)
case b(value: Int)
case c(value: Int)
var value: Int {
switch self {
case .a(let value):
return value
case .b(let value):
return value
case .c(let value):
return value
}
}
}
Maybe you could change the way your data is modeled
struct MyStruct {
enum Kind {
case one, two, three
}
let kind: Kind
let value: Int
}
var value: Int {
switch self {
case .a(let value),
.b(let value),
.c(let value):
return value
}
}
I have a generic binary search tree based on Comparable:
public class BSTree<T: Comparable> {
public func insert(_ val: T, _ n: Int) {
// ...
}
#discardableResult
public func delete(_ val: T, _ n: Int) -> Int {
// ...
}
}
I want to add the ability to provide the sum of the values, if T is an arithmetic type. I tried the following:
public class BSTree<T: Comparable> {
private var sumStorage: T?
public func insert(_ val: T, _ n: Int) {
if let arithVal = val as? AdditiveArithmetic {
for _ in 0 ..< n { sumStorage += arithVal }
}
// ...
}
#discardableResult
public func delete(_ val: T, _ n: Int) -> Int {
// ...
numDeleted = ...
if let arithVal = val as? AdditiveArithmetic {
for _ in 0 ..< numDeleted { sumStorage -= arithVal }
}
}
}
extension BSTree where T: AdditiveArithmetic {
public var sum: T {
sumStorage as? T ?? T.zero
}
}
Of course, when I try to cast val as AdditiveArithmetic I get “Protocol 'AdditiveArithmetic' can only be used as a generic constraint because it has Self or associated type requirements”. Plus sumStorage isn’t AdditiveArithmetic, so I can’t add to it, and I can’t make it a stored property of the extension, because ... you just can’t.
What I finally came up with was to use inheritance:
class SummedBSTree<T>: BSTree<T> where T: AdditiveArithmetic & Comparable {
public var sum = T.zero
override public func insert(_ val: T, _ n: Int) {
super.insert(val, n)
for _ in 0 ..< n { sum += val }
}
#discardableResult
override public func delete(_ val: T, _ n: Int) -> Int {
let numDeleted = super.delete(val, n)
for _ in 0 ..< numDeleted { sum -= val }
return numDeleted
}
}
This works, but it seems like it’s a case of using a sledgehammer where a jeweler’s screwdriver should be able to do the trick. It’s frustrating that something that would be so easy to do in Objective-C (and other less strongly typed languages) is so difficult in Swift. Can someone come up with a way of adding the summing capability without subclassing?
import UIKit
//https://stackoverflow.com/questions/61784548/swift-extended-capability-for-a-more-restrictive-generic
protocol ON1Speedable {
associatedtype Item: Comparable
var sumStorage: Item? { get set }
}
public class BSTree<T: Comparable> {
var sumStorage: T?
init(sumStorage: T? = nil) {
self.sumStorage = sumStorage
}
}
extension ON1Speedable where Item: AdditiveArithmetic, Item: Strideable, Item.Stride: SignedInteger {
mutating func insert(_ val: Item, _ n: Int) {
sumStorage = sumStorage ?? Item.zero
for _ in 0..<n { sumStorage! += val }
}
#discardableResult
mutating func delete(_ val: Item, _ n: Int) -> Item? {
sumStorage = sumStorage ?? Item.zero
for _ in Item.zero..<val { sumStorage! -= val }
return sumStorage
}
}
extension BSTree: ON1Speedable { }
var g2 = BSTree<Int>(sumStorage: 0)
g2.sumStorage
g2.insert(5, 5)
g2.sumStorage // 25
g2.delete(5, 5) // 0
var g3 = BSTree<String>()
g3.sumStorage // nil
//g3.insert("foo", 5) // Error: Referencing instance method 'insert' on 'ON1Speedable' requires that 'String.Stride' conform to 'SignedInteger'
g3.sumStorage // nil
//g3.delete("bar", 5) // Error: Referencing instance method 'delete' on 'ON1Speedable' requires that 'String.Stride' conform to 'SignedInteger'
I have enum Foo with associated value. Enum Foo serves as an associated value of another enum, Car. I would like to know how to access the 'nested' associated value of Foo, as shown in the example below:
enum Foo: Equatable {
case moo
case zoo(String)
}
enum Car {
case mar
case dar(Foo)
case gar(Foo)
}
func request(with type: Car) -> String {
switch type {
case .mar:
return "mar"
case .dar(let foo) where foo == .moo:
return "darmoo"
case .dar(let foo) where foo == .zoo(let value):
// how can I access the associated value of foo?
// This where syntax results in an error - Consecutive statements on a line must be separated by ';'
}
}
You can use pattern matching:
switch type {
case .mar:
return "mar"
case .dar(let foo) where foo == .moo:
return "darmoo"
case .dar(.moo):
return "dar: moo"
case let .dar(.zoo(value)):
return "dar: \(value)"
case .gar:
return "gar"
}
Or, if you want to handle Foo in the same manner for dar and gar, you can bind foo in one case:
switch type {
case .mar:
return "mar"
case .dar(let foo) where foo == .moo:
return "darmoo"
case let .dar(foo), let .gar(foo):
switch foo {
case .moo:
return "moo"
case let .zoo(value):
return value
}
}
As you rightly say, it's nested. So nest! Use a switch within the switch. This compiles:
func request(with type: Car) -> String {
switch type {
case .mar:
return "mar"
case .dar(let foo):
switch foo {
case .moo: return "darmoo"
case .zoo(let s): return s
}
case .gar:
return "gar"
}
}
I have the following Swift enum that ensures only pure json types are used.
public enum JSONValue {
case string(String)
case integer(Int)
case double(Double)
case bool(Bool)
public init(_ value: String) {
self = .string(value)
}
public init(_ value: Int) {
self = .integer(value)
}
public init(_ value: Double) {
self = .double(value)
}
public init(_ value: Bool) {
self = .bool(value)
}
}
To initialise a JSON value, one has to do
let json = JSONValue.string("my value")
or in a case of a dictionary
let params: [String: JSONValue] = [
"my string": JSONValue.string("my value"),
"my int": JSONValue.init(10)
]
Isn't there a way to infer the initialiser from the primitive value to facilitate the usage like this:
let json: JSONValue = "my value"
let params: [String: JSONValue] = [
"my string": "my value",
"my int": 10
]
(off topic but if you wonder why I need this JSONValue enum, this is the reason
I think you need to conform to the following protocols:
ExpressibleByBooleanLiteral
ExpressibleByIntegerLiteral
ExpressibleByFloatLiteral
ExpressibleByStringLiteral
Like this
public enum JSONValue: ExpressibleByBooleanLiteral, ExpressibleByIntegerLiteral, ExpressibleByFloatLiteral, ExpressibleByStringLiteral {
public typealias BooleanLiteralType = Bool
public typealias IntegerLiteralType = Int
public typealias FloatLiteralType = Double
public typealias StringLiteralType = String
case string(String)
case integer(Int)
case double(Double)
case bool(Bool)
public init(stringLiteral value: String) {
self = .string(value)
}
public init(integerLiteral value: Int) {
self = .integer(value)
}
public init(floatLiteral value: Double) {
self = .double(value)
}
public init(booleanLiteral value: Bool) {
self = .bool(value)
}
}
This will allow the compiler to perform some magic:
let jsonValue: JSONValue = "Hello World"
I have a switch case statement over an enum type with associated values in Swift:
enum Foo {
case Something(let s: Any)
// …
}
I would like to use a cast in the pattern match, a bit like this:
let foo: Foo = // …
switch foo {
case .Something(let a as? SpecificType):
// …
}
In other words, I would like the case pattern to succeed only if the cast succeeds. Is that possible?
Your example basically works as is:
enum Foo {
case Something(s: Any)
}
let foo = Foo.Something(s: "Success")
switch foo {
case .Something(let a as String):
print(a)
default:
print("Fail")
}
If you replace "Success" with e.g. the number 1 it will print "Fail" instead. Is that what you want?
You can use where clause:
enum Foo {
case Something(s: Any)
}
let foo: Foo = Foo.Something(s: "test")
switch foo {
case .Something(let a) where a is String:
print("Success")
default:
print("Failed")
}