thoughtbot/Argo

Unable to compile the decode function

dalu93 opened this issue · 3 comments

Hi, I'm currently unable to compile the decode function for an object. Everything works, but, when I add a new json key, I get an error regarding some mismatch with the types expected by the compiler.

Error Messages

Cannot convert value of type (ALL THE TYPES HERE) -> Object to expected argument type (_) -> (_) ...

Models

The model is quite huge and, before you think it's a problem of length, I tried all the possible solutions you wrote here and it ends with the same error.

extension Object: Decodable {
    
    static func decode(_ json: JSON) -> Decoded<Object> {
        let d = curry(Object.init)
        return d
            <^> (json <|    "id") as Decoded<String>
            ... other 19 properties
            <*> (json <|?    "objectDescription") as Decoded<String?>
    }
}

Well, if I remove the last row and I remove it from the initializer too, it works. I'm quite sure the type in the initializer is the same I'm using in the decode function (String?).
Here is the init

init(objectId: String, ..., objectDescription: String?) { ... }

Argo Version

4.1.0

Dependency Manager

Cocoapods

I took a look at the curry function and it seems it accepts a maximum of 20 parameters (where U is the return type). Is there a workaround for this issue (I cannot split the model in more objects because it will mean a lot of refactoring)?

So I created the curry function for this purpose.

public func curry<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V>(_ function: @escaping (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) -> V) -> (A) -> (B) -> (C) -> (D) -> (E) -> (F) -> (G) -> (H) -> (I) -> (J) -> (K) -> (L) -> (M) -> (N) -> (O) -> (P) -> (Q) -> (R) -> (S) -> (T) -> (U) -> V {
    return { (a: A) -> (B) -> (C) -> (D) -> (E) -> (F) -> (G) -> (H) -> (I) -> (J) -> (K) -> (L) -> (M) -> (N) -> (O) -> (P) -> (Q) -> (R) -> (S) -> (T) -> (U) -> V in { (b: B) -> (C) -> (D) -> (E) -> (F) -> (G) -> (H) -> (I) -> (J) -> (K) -> (L) -> (M) -> (N) -> (O) -> (P) -> (Q) -> (R) -> (S) -> (T) -> (U) -> V in { (c: C) -> (D) -> (E) -> (F) -> (G) -> (H) -> (I) -> (J) -> (K) -> (L) -> (M) -> (N) -> (O) -> (P) -> (Q) -> (R) -> (S) -> (T) -> (U) -> V in { (d: D) -> (E) -> (F) -> (G) -> (H) -> (I) -> (J) -> (K) -> (L) -> (M) -> (N) -> (O) -> (P) -> (Q) -> (R) -> (S) -> (T) -> (U) -> V in { (e: E) -> (F) -> (G) -> (H) -> (I) -> (J) -> (K) -> (L) -> (M) -> (N) -> (O) -> (P) -> (Q) -> (R) -> (S) -> (T) -> (U) -> V in { (f: F) -> (G) -> (H) -> (I) -> (J) -> (K) -> (L) -> (M) -> (N) -> (O) -> (P) -> (Q) -> (R) -> (S) -> (T) -> (U) -> V in { (g: G) -> (H) -> (I) -> (J) -> (K) -> (L) -> (M) -> (N) -> (O) -> (P) -> (Q) -> (R) -> (S) -> (T) -> (U) -> V in { (h: H) -> (I) -> (J) -> (K) -> (L) -> (M) -> (N) -> (O) -> (P) -> (Q) -> (R) -> (S) -> (T) -> (U) -> V in { (i: I) -> (J) -> (K) -> (L) -> (M) -> (N) -> (O) -> (P) -> (Q) -> (R) -> (S) -> (T) -> (U) -> V in { (j: J) -> (K) -> (L) -> (M) -> (N) -> (O) -> (P) -> (Q) -> (R) -> (S) -> (T) -> (U) -> V in { (k: K) -> (L) -> (M) -> (N) -> (O) -> (P) -> (Q) -> (R) -> (S) -> (T) -> (U) -> V in { (l: L) -> (M) -> (N) -> (O) -> (P) -> (Q) -> (R) -> (S) -> (T) -> (U) -> V in { (m: M) -> (N) -> (O) -> (P) -> (Q) -> (R) -> (S) -> (T) -> (U) -> V in { (n: N) -> (O) -> (P) -> (Q) -> (R) -> (S) -> (T) -> (U) -> V in { (o: O) -> (P) -> (Q) -> (R) -> (S) -> (T) -> (U) -> V in { (p: P) -> (Q) -> (R) -> (S) -> (T) -> (U) -> V in { (q: Q) -> (R) -> (S) -> (T) -> (U) -> V in { (r: R) -> (S) -> (T) -> (U) -> V in { (s: S) -> (T) -> (U) -> V in { (t: T) -> (U) -> V in { (u: U) -> V in function(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) } } } } } } } } } } } } } } } } } } } } }
}

@dalu93 FYI, the reason Curry doesn't go past 20 arguments is due to the polynomial time complexity of the Swift type checker, which means that the functions take longer and longer the more parameters they have. Creating your own implementation of the 21 argument version is fine, just be aware of it's high compile time.