I'm trying to implement either function, which accepts two generic container and return either of them:
func either<A,B>(a: Container<A>, b: Container<B>) -> ?either Container<A> or Container<B>? {
// choose any of container
return chosen
}
Looks like I need a protocol, that Container must conforms to, so that my either's return type should be of this protocol.
Is this right solution?
protocol ContainerProtocol
struct Container<T>: ContainerProtocol
func either<A: ContainerProtocol, B:ContainerProtocol, C:ContainerProtocol>(a: A, b: B) -> C {
// choose any of container
return chosen
}
UPDATE
ok so I've implemented the EitherContainer enum and the final code is following:
struct Container<T>: Unique {
typealias UnderlyingObject = T
var object: UnderlyingObject
var uniqueId: String
}
enum EitherContainer<A,B> {
case a(container: Container<A>)
case b(container: Container<B>)
}
func wrappedInput<A,B>(wra: Container<A>, wrb: Container<B>, paramClosure: (Container<A>, Container<B>) -> EitherContainer<A,B>) -> EitherContainer<A,B> {
//do some work here
return paramClosure(wra, wrb)
}
func rawInput<A, B>(a: A, b: B) -> Any {
let wrappedA = Container(object: a, uniqueId: "a")
let wrappedB = Container(object: b, uniqueId: "b")
let wrappedRes = wrappedInput(wrappedA, wrb: wrappedB) {
(a1: Container, a2: Container) -> EitherContainer<A,B> in
// do some work here
return EitherContainer.a(container: a1)
}
var rawRes: Any
switch wrappedRes {
case .a(let container):
rawRes = container.object
case .b(let container):
rawRes = container.object
}
return rawRes
}
what bothers me now, is Any type, which shuts the compiler up, but for me looks like a weak crutch. Again same problem rawInput<A, B>(a: A, b: B) -> Any . rawInput should return either A or B, but I'm forced to use Any instead. Should I add another enum for raw options? Any thoughts?
The traditional Either type looks like this:
enum Either<A, B>
{
case Left(A)
case Right(B)
}
and is more useful, as it's not limited to your Container type.
(Either is the "canonical" sum type.)
It would be used like this:
func wrappedInput<A, B> (
a : Container<A>,
b: Container<B>,
paramClosure: (Container<A>, Container<B>) -> Either<Container<A>,Container<B>>
) -> Either<Container<A>, Container<B>>
{
return Either.Left(a) // Dummy
}
func rawInput<A, B>(a: A, b: B) -> Either<A,B> {
let wrappedA = Container(object: a, uniqueId: "a")
let wrappedB = Container(object: b, uniqueId: "b")
let wrappedRes = wrappedInput(wrappedA, b: wrappedB) {
(a1: Container, a2: Container) -> Either<Container<A>, Container<B>> in
// do some work here
return Either.Left(a1)
}
switch wrappedRes {
case .Left(let container):
return Either.Left(container.object)
case .Right(let container):
return Either.Right(container.object)
}
}
Related
Imagine I have a simple linked list:
class Node {
var parent: Node?
}
// Create the chain: a <- b <- c
let a = Node()
let b = Node(parent: a)
let c = Node(parent: b)
Now I want to convert c into an array ([c, b, a]) so I can use other high-order functions like map.
What is a method that produces an array from a linked list typically called?
Is there a way to use other high-order functions to implement this and not use a loop?
The only implementation I could think of falls back to using a loop:
func chain<T>(_ initial: T, _ next: (T) -> T?) -> [T] {
var result = [initial]
while let n = next(result.last!) {
result.append(n)
}
return result
}
chain(c) { $0.parent } // == [c, b, a]
I'm wondering if there is a built-in way to use functions like map/reduce/etc. to get the same results.
You can use sequence(first:next:) to make a Sequence and then Array() to turn that sequence into an array:
let result = Array(sequence(first: c, next: { $0.parent }))
or equivalently:
let result = Array(sequence(first: c, next: \.parent))
You could use it to implement chain:
func chain<T>(_ initial: T, _ next: #escaping (T) -> T?) -> [T] {
Array(sequence(first: initial, next: next))
}
But I'd just use it directly.
Note: If you just want to call map, you don't need to turn the sequence into an Array. You can just apply .map to the sequence.
For example, here is a useless map that represents each node in the linked list with a 1:
let result = sequence(first: c, next: \.parent).map { _ in 1 }
You could make Node be a "denaturated" sequence, this will automatically bring all high-order functions: map, filter, reduce, flatMap, etc.
class Node {
var parent: Node?
var value: String
init(parent: Node? = nil, value: String = "") {
self.parent = parent
self.value = value
}
}
extension Node: Sequence {
struct NodeIterator: IteratorProtocol {
var node: Node?
mutating func next() -> Node? {
let result = node
node = node?.parent
return result
}
}
func makeIterator() -> NodeIterator {
NodeIterator(node: self)
}
}
// Create the chain: a <- b <- c
let a = Node(value: "a")
let b = Node(parent: a, value: "b")
let c = Node(parent: b, value: "c")
// each node behaves like its own sequence
print(c.map { $0.value }) // ["c", "b", "a"]
print(b.map { $0.value }) // ["b", "a"]
Let's say that I want to generate a data set that requires multiple promises to resolve, how would I store each result down the promise chain so I can create my final data set in one shot?
struct CompleteData {
let a: String
let b: String
}
func getData() -> Promise<CompleteData> {
getA().then { a -> Promise<String> in
return a.getB()
}.then { b -> CompleteData in
return CompleteData(a: ???, b: b)
}
}
The solutions that I'm coming up with don't feel elegant enough:
Temporary IUOs
Use implicitly-unwrapped optionals to store temporary values. This can break if I forget to assign to a.
func getData() -> Promise<CompleteData> {
var a: String!
getA().then { _a -> Promise<String> in
_a = a
return _a.getB()
}.then { b -> CompleteData in
return CompleteData(a: a, b: b)
}
}
Nested promises
Nest promises and access values from the outer scopes. This defeats the purpose of promises by getting into a nesting hell.
func getData() -> Promise<CompleteData> {
getA().then { a -> Promise<CompleteData> in
return a.getB().then { b -> CompleteData in
return CompleteData(a: a, b: b)
}
}
}
Other solutions on top of my head: use optional fields in CompleteData, use var fields in CompleteData and assign as the chain resolves, none of those are good to me.
Can someone think of a more elegant way to do this?
You could use tuples to pass data down the promise chain. You just need to specify tuple and "a" return promise. Use .map to return tuple. Here is the code on your example:
struct CompleteData {
let a: String
let b: String
}
func getData() -> Promise<CompleteData> {
getA().then { a -> Promise<(String, a)> in
return a.getB().map{ ($0, a) }
}.then { (b, a) -> CompleteData in
return CompleteData(a: a, b: b)
}
}
PromiseKit documentation
Hope it will help you. Cheers :)
I have the following class with a generic factory method:
final class Something<T> {
let value: T
init(initial: T) {
value = initial
}
}
extension Something {
class func zip<A, B>(_ a: A, _ b: B) -> Something<(A, B)> {
let initial = (a, b)
return Something<(A, B)>(initial: initial)
}
}
How come I can’t call zip without explicitly specifying the return type?
// ERROR: Cannot invoke `zip` with an argument list of type `(Int, Int)`
let y = Something.zip(1, 2)
// OK: Works but it’s unacceptable to require this on caller's side
let x = Something<(Int, Int)>.zip(1, 2)
Thank you for your time!
The reason you're seeing this is that there's nothing in this call:
let y = Something.zip(1, 2)
That tells Swift what T should be.
Your call implicitly specifies what A and B should be, and specifies the method should return Something<A, B>. But that Something<A, B> is not connected to Something<T>.
In fact, nothing at all in your call is connected to T; T is left unspecified, so it could be anything. I mean that literally—you can actually put (nearly) any random type in the angle brackets after Something and it'll work exactly the same:
let y = Something<UICollectionViewDelegateFlowLayout>.zip(1, 2)
What you would really like to do is somehow specify that T has to be a tuple and the two parameters are of the same types as the tuple's elements. Unfortunately, Swift doesn't currently have the features needed to properly do that. If the language were more sophisticated, you could say something like this:
extension<A, B> Something where T == (A, B) {
class func zip(a: A, _ b: B) -> Something {
let initial = (a, b)
return Something(initial: initial)
}
}
But for now, you'll have to make do with this horrible hack, which works by meaninglessly reusing the T type parameter so that it's no longer at loose ends:
extension Something {
class func zip<B>(a: T, _ b: B) -> Something<(T, B)> {
let initial = (a, b)
return Something<(T, B)>(initial: initial)
}
}
In short explanation, you use generics not correct. It's not realtime feature, it's precompile thing. If you need to make abstract class from generic input values, see and do like this:
class Abstract<T> {
init(value: T) {
print("inputed value: \(value)")
}
}
class Something {
class func zip<A, B>(value: A, value2: B) -> Abstract<(A, B)> {
print("Something.zip", value, value2)
return Abstract<(A, B)>(value: (value, value2))
}
}
Something.zip(5, value2: 40) // "inputed value: (5, 40)"
T simply isn't related to A and B in that way and so can't be inferred.
Eg.
let z = Something<(String, String)>.zip(1, 2)
let z2 = Something<AnyObject>.zip(1, 2)
work just fine to return a Something<(Int, Int)>
You can introduce type inference for your case like this:
final class Something<T> {
let value: T
init(initial: T) {
value = initial
}
class func zip<A, B>(_ a: A, _ b: B) -> Something<T> where T == (A, B) {
let initial = (a, b)
return Something<(A, B)>(initial: initial)
}
}
let y = Something.zip(1, 2) //works
Instead of using multiple optional bindings, we can define a function to tear down optional pyramid of doom.
func if_let<T, U, V> (a: T?, _ b: U?, _ c: V?, fn:(T, U, V) -> () ){
if let a = a {
if let b = b {
if let c = c {
fn(a, b, c)
}
}
}
}
Then I can write like this:
var s1: String? = "s11"
var s2: String? = "s22"
var s3: String? = "s33"
if_let(s1, s2, s3) { s1, s2, s3 in
print(("\(s1) - \(s2) - \(s3)"))
}
However, the problem is how to make this if_let function more generic so that it can accept any number of arguments. My implementation is like this:
func if_let<T> (values: T?..., fn:(params: [T]) -> ()) {
for value in values {
guard value != nil else { return }
}
let unwrappedArray = values.map{ $0! }
fn(params: unwrappedArray)
}
I tried to map the array and get a new one with all elements unwrapped and then call the fn. But when I ran the test again, I got a compile error:
Cannot convert value of type String? to expected argument type '_?'
Can anyone explain and fix this error?
The problem is that your second implementation of if_let no longer takes as a final parameter a function of type (T,U,V)->(). It now needs a function of type ([T])->(). If you call it with one, it compiles:
if_let(s1, s2, s3) { args in // or: (args: [String])->() in
print("\(args[0]) - \(args[1]) - \(args[2])")
}
A relevant note, rather than an answer to the specific question: with Swift 2, you needn't enter the pyramid of doom no more
let a: String? = nil
let b: Int? = nil
let c: Double? = nil
// possible mutate...
if let a = a, b = b, c = c {
// do something with shadow vars
}
This question already has answers here:
Using multiple let-as within a if-statement in Swift
(3 answers)
Closed 6 years ago.
In Swift I used if let declarations to check if my object is not nil
if let obj = optionalObj
{
}
But sometimes, I have to face with consecutive if let declarations
if let obj = optionalObj
{
if let a = obj.a
{
if let b = a.b
{
// do stuff
}
}
}
I'm looking for a way to avoid consecutive if let declarations.
I would try something like :
if let obj = optionalObj && if let a = obj.a && if let b = a.b
{
// do stuff
}
But the swift compiler do not allow this.
Any suggestion ?
Update
In swift 1.2 you can do
if let a = optA, let b = optB {
doStuff(a, b)
}
Original answer
In your specific case, you can use optional chaining:
if let b = optionaObj?.a?.b {
// do stuff
}
Now, if you instead need to do something like
if let a = optA {
if let b = optB {
doStuff(a, b)
}
}
you're out of luck, since you can't use optional chaining.
tl; dr
Would you prefer a cool one-liner instead?
doStuff <^> optA <*> optB
Keep reading. For how scaring it might look, this is really powerful and not so crazy to use as it seems.
Fortunately, this is a problem easily solved using a functional programming approach. You can use the Applicative abstraction and provide an apply method for composing multiple options together.
Here's an example, taken from http://robots.thoughtbot.com/functional-swift-for-dealing-with-optional-values
First we need a function to apply a function to an optional value only only when it contains something
// this function is usually called fmap, and it's represented by a <$> operator
// in many functional languages, but <$> is not allowed by swift syntax, so we'll
// use <^> instead
infix operator <^> { associativity left }
func <^><A, B>(f: A -> B, a: A?) -> B? {
switch a {
case .Some(let x): return f(x)
case .None: return .None
}
}
Then we can compose multiple options together using apply, which we'll call <*> because we're cool (and we know some Haskell)
// <*> is the commonly-accepted symbol for apply
infix operator <*> { associativity left }
func <*><A, B>(f: (A -> B)?, a: A?) -> B? {
switch f {
case .Some(let value): return value <^> a
case .None: return .None
}
}
Now we can rewrite our example
doStuff <^> optA <*> optB
This will work, provided that doStuff is in curried form (see below), i.e.
func doStuff(a: A)(b: B) -> C { ... }
The result of the whole thing is an optional value, either nil or the result of doStuff
Here's a complete example that you can try in the playground
func sum(a: Int)(b: Int) -> Int { return a + b }
let optA: Int? = 1
let optB: Int? = nil
let optC: Int? = 2
sum <^> optA <*> optB // nil
sum <^> optA <*> optC // Some 3
As a final note, it's really straightforward to convert a function to its curried form. For instance if you have a function taking two parameters:
func curry<A, B, C>(f: (A, B) -> C) -> A -> B -> C {
return { a in { b in f(a,b) } }
}
Now you can curry any two-parameter function, like + for example
curry(+) <^> optA <*> optC // Some 3
I wrote a little essay on the alternatives some time ago: https://gist.github.com/pyrtsa/77978129090f6114e9fb
One approach not yet mentioned in the other answers, which I kinda like, is to add a bunch of overloaded every functions:
func every<A, B>(a: A?, b: B?) -> (A, B)? {
switch (a, b) {
case let (.Some(a), .Some(b)): return .Some((a, b))
default: return .None
}
}
func every<A, B, C>(a: A?, b: B?, c: C?) -> (A, B, C)? {
switch (a, b, c) {
case let (.Some(a), .Some(b), .Some(c)): return .Some((a, b, c))
default: return .None
}
}
// and so on...
These can be used in if let statements, case expressions, as well as optional.map(...) chains:
// 1.
var foo: Foo?
if let (name, phone) = every(parsedName, parsedPhone) {
foo = ...
}
// 2.
switch every(parsedName, parsedPhone) {
case let (name, phone): foo = ...
default: foo = nil
}
// 3.
foo = every(parsedName, parsedPhone).map{name, phone in ...}
Having to add the overloads for every is boilerplate'y but only has to be done in a library once. Similarly, with the Applicative Functor approach (i.e. using the <^> and <*> operators), you'd need to create the curried functions somehow, which causes a bit of boilerplate somewhere too.
In some cases you can use optional chaining. For your simple example:
if let b = optionalObj?.a?.b {
// do stuff
}
To keep your nesting down and to give yourself the same variable assignments, you could also do this:
if optionalObj?.a?.b != nil {
let obj = optionalObj!
let a = obj.a!
let b = a.b!
}
After some lecture thanks to Martin R, I found an interesting workaround: https://stackoverflow.com/a/26012746/2754218
func unwrap<T, U>(a:T?, b:U?, handler:((T, U) -> ())?) -> Bool {
switch (a, b) {
case let (.Some(a), .Some(b)):
if handler != nil {
handler!(a, b)
}
return true
default:
return false
}
}
The solution is interesting, but it would be better if the method uses variadic parameters.
I naively started to create such a method:
extension Array
{
func find(includedElement: T -> Bool) -> Int?
{
for (idx, element) in enumerate(self)
{
if includedElement(element)
{
return idx
}
}
return nil
}
}
func unwrap<T>(handler:((T...) -> Void)?, a:T?...) -> Bool
{
let b : [T!] = a.map { $0 ?? nil}
if b.find({ $0 == nil }) == nil
{
handler(b)
}
}
But I've this error with the compiler: Cannot convert the expression's type '[T!]' to type '((T...) -> Void)?'
Any suggestion for a workaround ?