https://github.com/idapgroup/IDPCastable
i like the idea of Castable. but i don't like to have too much public functions without an "Namespace" aka Class flying around like cast
, castable
, match
.
i prefer it more encapsulated in one class and also to prefix the first closure also with match
to get it uniform with the other match
es
i rewrite the class like this:
/**
Chainable type representing the value matching different types
*/
public enum Castable<Wrapped> {
case value(Wrapped)
/**
Wraps a value in Castable.
- Parameter x: Value to wrap.
- Returns: Value wrapped by Castable
*/
init(_ data: Wrapped){
self = .value(data)
}
/**
Casts a value from Type to Result?
- Parameter value: Value to be casted
- Returns: *.some(value: Result)* if the value could be casted, *.none* otherwise
*/
private func cast<Type, Result>(_ value: Type) -> Result? {
return value as? Result
}
/**
Casts a value to function argument type and calls a function, if the cast was successfull.
- Parameter f: Function to call, if the *.value* in can be be casted to function argument
- Returns: Castable wrapping the same value
*/
@discardableResult
public func match<Subject>(f: (Subject) -> ()) -> Castable<Wrapped> {
switch self {
case let .value(x):
cast(x).map { f($0) }
return .value(x)
}
}
/**
Extracts a value from Castable
- Returns: Value wrapped by Castable
*/
public func extract() -> Wrapped {
switch self {
case let .value(x):
return x
}
}
}
to test it in Playground
class RedCell{}
class GreenCell{}
class ColorCell{}
class RedColorCell: ColorCell{}
class GreenColorCell: ColorCell{}
class LightRedColorCell: RedColorCell{}
[ RedCell(), GreenCell(), ColorCell(),
RedColorCell(),GreenColorCell(),
LightRedColorCell()].map{
print("\nTest for : \($0)")
let u = Castable($0)
.match{ (x:RedCell) in
print("Tested : RedCell")
}
.match{ (x:GreenCell) in
print("Tested : GreenCell")
}
.match{ (x:ColorCell) in
print("Tested : ColorCell")
}
.match{ (x:RedColorCell) in
print("Tested : RedColorCell")
}
.match{ (x:GreenColorCell) in
print("Tested : GreenColorCell")
}
.match{ (x:LightRedColorCell) in
print("Tested : LightRedColorCell")
}
.extract()
print("Extracted: \(u)")
}
Output:
Test for : RedCell
Tested : RedCell
Extracted: RedCell
Test for : GreenCell
Tested : GreenCell
Extracted: GreenCell
Test for : ColorCell
Tested : ColorCell
Extracted: ColorCell
Test for : RedColorCell
Tested : ColorCell
Tested : RedColorCell
Extracted: RedColorCell
Test for : GreenColorCell
Tested : ColorCell
Tested : GreenColorCell
Extracted: GreenColorCell
Test for : LightRedColorCell
Tested : ColorCell
Tested : RedColorCell
Tested : LightRedColorCell
Extracted: LightRedColorCell