[swift-evolution] [Pitch] Self's nominal restriction denies significant feature patterns

Gwendal Roué gwendal.roue at gmail.com
Fri Jun 2 04:39:55 CDT 2017


Hello Zaid,

I don't know what prevents you from implementing your DAOs.

For an example of a library that uses them extensively, see http://github.com/groue/GRDB.swift:

    struct PointOfInterest {
        var id: Int64?
        var title: String?
        var favorite: Bool
        var coordinate: CLLocationCoordinate2D
    }

    // (snip) adopt protocols that turn PointOfInterest in a "record"

    // Fetch from SQL
    let pois = try PointOfInterest.fetchAll(db, "SELECT * FROM pointOfInterests") // [PointOfInterest]
    
    // Fetch without SQL
    let title = Column("title")
    let favorite = Column("favorite")
    let poi1 = try PointOfInterest.fetchOne(db, key: 1)                   // PointOfInterest?
    let pois = try PointOfInterest.fetchOne(db, keys: [1, 2, 3])          // [PointOfInterest]
    let paris = try PointOfInterest.filter(title == "Paris").fetchOne(db) // PointOfInterest?
    let favoritePois = try PointOfInterest                                // [PointOfInterest]
        .filter(favorite)
        .order(title)
        .fetchAll(db)
    
    // Insert, update, delete
    var berlin = PointOfInterest(
        id: nil,
        title: "Berlin",
        favorite: false,
        coordinate: CLLocationCoordinate2DMake(52.52437, 13.41053))
    try berlin.insert(db)
    berlin.id // some value
    berlin.favorite = true
    try berlin.update(db)
    try berlin.delete(db)

GRDB "records" work pretty well with structs, but also class hierarchies, without any caveat.

Can you explain a little more your issue ?

Gwendal Roué


> Le 2 juin 2017 à 11:18, Zaid Daghestani via swift-evolution <swift-evolution at swift.org> a écrit :
> 
> Greetings Swift Community,
> 
> Today I’m throwing out a pitch on freeing the shackles on Self. Self is a potentially significant tool that I am itching to implement in my patterns to make my code more concise, clear and intuitive.
> 
> Self, by far, is cherished by Data Models and ORM's, and particularly DAO <https://en.wikipedia.org/wiki/DAO> s (Ref. 1 for examples). There are a significant amount of patterns in which a base class’s methods are Self relevant and not generic relevant. Self being non-referrable in non-nominal types denies significant feature and pattern delivery such as DAO. And to deny implementation of a pattern as significant as DAO’s seems like a shot in the foot. Adding Self to non-nominal types brings Collections and Async to our class/protocol methods. A single query method returning a sync or likely async collection on my DataModel class will be used in about 80% of my app screens and 80% of my eerver API’s, almost all of the time. Hell this even applies to struct patterns as well.
> 
> Now, DAO’s can actually already currently be achieved via generics, see Ref. 2. This actually still a pretty good implementation, but Self is a significantly more true implementation of these patterns. Issues with the current generic pattern of Self relevancy in Swift is:
> 1- Generic methods in the base class are a workaround to the lack of Self. The base class is not a class that implements generic patterns. It a base class that implements Self patterns. Self is more concise and intuitive in implementing a DAO or any other Self relevant base class.
> 2- Self relevant patterns are distinct and not the same as Generic patterns. 
> 3- In usage of a DAO, the generic pattern requires that the Left Hand Side be typed to collapse the generic. In the case of Self relevance, the particular class name is enough. Swift, being an inference language, would be truer with the Self system, and not the repetitive type declaration style of ObjC/Java that generics provide.
> let friends = User.where("id IN %@", friendIds) // truer to Swift type inference
> // vs.
> let friends:[User] = User.where("id IN %@", friendIds) // Java/Objective-C style repetitive type declarations
> 
> Let’s break the chains on Self! It is extremely intuitive, and we are all going to use it
> 
> Peace!
> 
> Z
> 
> 
> 
> 
> Ref 1: DAO patterns::
> 
> class DataModelObject  {
>     
>     /* One of the most significant use cases
>      * Retrieving a queried on collection asynchronusly
>      */
>     class func `where`(_ predicate:String, _ args:CVarArg...) -> Promise<[Self]> {
>         // querie
>         return Promise(value: [[])
>     }
>     
>     // some more examples
> 
>     // optional async get
>     class func get(id:String) -> Promise<Self?> {
>         return Promise(value:self.init(id:id))
>     }
>     
>     // sync all collection
>     class func all() -> [Self] {
>         return []
>     }
>     // asynnchronous fetch
>     class func allAsync() -> Promise<[Self]> {
>         return Promise(value: [])
>     }
>     
>     // in the case of RealmDB we have returns of Results<Self>, a lazy collection
>     class func `where`(_ predication:NSPredicate) -> Results<Self> {
>         return Results<self>()
>     }
> }
> 
> class User : DataMadelObject {
>     dynamic var id:String = ""
>     dynamic var name:String = ""
> }
> 
> let friendIds = [1, 2, 3]
> let friends = User.where("id IN %@", friendIds)
> 
> Ref 2: Currently implementable DAO
> 
> class DataModelObject  {
>     
>     /* One of the most significant use cases
>      * Retrieving a queried on collection asynchronusly
>      */
>     class func `where`<T: DataModelObject>(_ predicate:String, _ args:CVarArg...) -> Promise<[T]> {
>         // querie
>         return Promise(value: [])
>     }
>     
>     // some more examples
>     // optional async get
>     class func <T: DataModelObject>get(id:String) -> Promise<T?> {
>         return Promise(value:self.init(id:id))
>     }
>     
>     
>     // sync all collection
>     class func all<T: DataModelObject>() -> [T] {
>         return []
>     }
>     // asynnchronous fetch
>     class func allAsync<T: DataModelObject>() -> Promise<[T]> {
>         return Promise(value: [])
>     }
>     
>     // in the case of RealmDB we have returns of Results<Self>, a lazy collection
>     class func `where`<T: DataModelObject>(_ predication:NSPredicate) -> Results<T> {
>         return Results<T>()
>     }
> }
> 
> class User : DataMadelObject {
>     dynamic var id:String = ""
>     dynamic var name:String = ""
> }
> 
> let friendIds = [1, 2, 3]
> let friends:[User] = User.where("id IN %@", friendIds)
> 
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170602/b0360b2f/attachment.html>


More information about the swift-evolution mailing list