Coder Social home page Coder Social logo

Use Generics when parsing about argo HOT 12 CLOSED

piercifani avatar piercifani commented on May 24, 2024
Use Generics when parsing

from argo.

Comments (12)

gfontenot avatar gfontenot commented on May 24, 2024

There's really no way for Argo to know how to parse an object of the type T without also knowing that T is JSONDecodable. The long compile times resulting in failures make sense to me, given that the compiler has no idea what to do with that type in this context.

tl;dr: if you want Argo to decode contained types, they need to conform to JSONDecodable. There's really no way around that.

from argo.

piercifani avatar piercifani commented on May 24, 2024

I've pushed a repo with my findings: https://github.com/piercifani/ArgoGenericParse. Please look at Model.swift and Parse.swift

I think that noting that noting that T is a JSONDecodable in the decode and create methods should be enough for the compiler to know that when calling Page<T>.decode it should error when T doesn't comply with JSONDecodable but still let you do stuff like Page<U> when you're not calling either decode or create.

I don't think this is an Argo bug, but instead a compiler bug. Shall we create a radar with this behaviour?

PS: It still won't compile if I declare <T:JSONDecodable> in the original struct Page declaration

from argo.

tonyd256 avatar tonyd256 commented on May 24, 2024

Because of the way we've implemented Argo, you would need to make T like so: <T: JSONDecodable where T.DecodedType == T>. You could try that and see if it helps with Page.

from argo.

tonyd256 avatar tonyd256 commented on May 24, 2024

You also can't have a generic class/struct that conforms to a protocol in only some cases. For example, Page<T>. Page: JSONDecodable for only when T: JSONDecodable wouldn't work. The declairation of Page<T> would have to say that T is such.

from argo.

piercifani avatar piercifani commented on May 24, 2024

You are right, declaring:

public struct Page<T: JSONDecodable where T.DecodedType == T> {
    public let count : Int
    public let next : String?
    public let previous : String?
    public let results : [T]
}

Compiles and works as expected. However, it is a shame that this limitation exists, since now my model classes are tightly coupled to Argo, that means that now my ViewControllers must know what JSONDecodable is and what classes/structs comply to it.

I still don't understand why the compiler can't figure out when it's correct to call Page<T>.decode and when not to, since it knows which <T>s comply to the protocol and which don't.

I have updated the repository including the correct code.

Thanks for your help!

from argo.

gfontenot avatar gfontenot commented on May 24, 2024

However, it is a shame that this limitation exists, since now my model classes are tightly coupled to Argo

This isn't a limitation, there's really no other way for Argo to work. Argo is designed to be tightly coupled to your model objects.

that means that now my ViewControllers must know what JSONDecodable is and what classes/structs comply to it.

Your view controllers might know that your object is JSONDecodable, but they really shouldn't need to care about JSONDecodable. I'd be interested in why you think they do.

I still don't understand why the compiler can't figure out when it's correct to call Page<T>.decode and when not to

The issue isn't calling Page<T>.decode, the issue is calling T.decode when it tries to decode your results property.

since it knows which <T>s comply to the protocol and which don't.

That's simply not true. The compiler has no idea what T is. So how can it know if it's JSONDecodable? The larger issue that there's literally no way that the compiler can know that Page is JSONDecodable if it doesn't know that all of the properties on Page are also JSONDecodable.

from argo.

piercifani avatar piercifani commented on May 24, 2024

Argo is designed to be tightly coupled to your model objects.

Well, I can conform to JSONDecodable in an extension and in a different file, just like I did in the attached repo using Parse.swift. This is one of the nicest things of Argo, because in case you want to change the JSON->Model Objects serialization, you just edit that one file.

Your view controllers might know that your object is JSONDecodable, but they really shouldn't need to care about JSONDecodable

Well, now they have to import Argo in order to understand what a struct Page<T: JSONDecodable where T.DecodedType == T> means, before I only had to import my App's internal framework and that was it.

The issue isn't calling Page.decode, the issue is calling T.decode when it tries to decode your results property.

Exactly: I thought that if I declared

extension Page : JSONDecodable {

    static func create<T: JSONDecodable where T.DecodedType == T> () -> Page<T>  {

    }

    public static func decode<T: JSONDecodable where T.DecodedType == T>(j: JSONValue) -> Page<T>? {

    }
}

That would be enough, but the compiler SEGFAULTs if I do this. Do you see why I think that that should be enough for the compiler to know when Page<T>.decode is legal and when it isn't?

Because I feel like I'm not explaining myself good enough, if you think it'll help I can change the code back to how I think it should work and you can see the compiler SEGFAULTing :) always fun when that happens!

from argo.

gfontenot avatar gfontenot commented on May 24, 2024

Well, now they have to import Argo in order to understand what a struct Page<T: JSONDecodable where T.DecodedType == T> means, before I only had to import my App's internal framework and that was it.

That doesn't sound right at all. Doing a quick check, the only reason you would need to import Argo in a file that uses one of your models is accessing the decode function (or the DecodedType typealias) defined on JSONDecodable itself. Where are you seeing this behavior?

I'll need to think more about your decode type constraints. That's an interesting point.

from argo.

piercifani avatar piercifani commented on May 24, 2024

Sorry for the long time between answers, I'm using Argo on a side project, so I don't check this thread out everyday :(

I withdraw what I said: the ViewControllers importing the model objects from a framework don't need to import Argo, since Swift collapses all the necessary imports at the beginning of the generated module header.

So to recap, it's not ideal to have that coupled there, but I can live with this.

I'm still intellectually curious on why the compiler can't figure it out without making all the Page's Ts comply to JSONDecodable, but rather only the ones that I'm calling decode onto. But hell, maybe it's time to ask someone who works on the language

from argo.

gfontenot avatar gfontenot commented on May 24, 2024

I think the answer is probably as simple as the fact that these two function definitions aren't the same:

static func decode<T: JSONDecodable where T.DecodedType == T>(j: JSONValue) -> Page<T>?
static func decode(j: JSONValue) -> DecodedType?

DecodedType is typealiased to Self, so you can't make constraints on it.

from argo.

piercifani avatar piercifani commented on May 24, 2024

Mmmmm that makes a lot of sense

from argo.

mendesbarreto avatar mendesbarreto commented on May 24, 2024

Hello Guys, how it's going?

Some one could post here the solutions file, because I am having the same trouble and can't figure out how fix.

Thx

from argo.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.