Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shorter Version #4

Open
muescha opened this issue Jan 13, 2017 · 3 comments
Open

Shorter Version #4

muescha opened this issue Jan 13, 2017 · 3 comments

Comments

@muescha
Copy link

muescha commented Jan 13, 2017

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 matches

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
@trimmurrti
Copy link
Contributor

Well, the thing is, that I prefer using public short functions.

Secondly, cast specifically is used for type inference, I use to avoid as? operators with types, inferring types instead.. See my articles for more details: Type Inference, Chainable Casting

And the last, but not the least, you see, the thing is, that cutting down the functionality is overall worse, then expanding. That's breaking changes inside my own projects and projects other people rely on.

@trimmurrti
Copy link
Contributor

Closing the issue, as I don't want to cut the functionality down. If you would like to extend it, however, I will gladly reopen the issue.

@muescha
Copy link
Author

muescha commented Jan 24, 2017

my issue was not about cutting the functionality. it was just to inform you how i use the library with a smaller footprint of global functions :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants