Generic where clause on property support / syntax

Hi everyone,

does anyone know if Swift supports generic where clauses on properties - and if so, what is the correct syntax?

WORKS: I wish to convert this working function to a property:

    func lowerL() -> Point<T> where T : ULO
    {
        return Point<T>( self.x0, self.y1 )
    }

WORKS: Without a contraint, this property compiles fine:

    var lowerL : Point<T>
    {
        return Point<T>( self.x0, self.y1 )
    }

FAILS: However with a constraint, the compiler reports: "Consecutive declarations on a line must be separated by ';'"

    var lowerL : Point<T> where T : ULO
    {
        return Point<T>( self.x0, self.y1 )
    }

Thanks.

Swift does not support generic variables.

However, if T happens to make more sense as a generic of the type instead of of the function, then perhaps that is what you are really looking for:

struct Something<T> where T: ULO {
  // ...
  var lowerL: Point<T> {
    return Point<T>(self.x0, self.y1)
  }
}

Thanks & damn.

Although arguably var lowerL: Point<T> is a generic variable.

You can convert function without arguments into a property, but in your case, lowerL() still has an argument - T. It is a type argument, not a value argument, but still it is something that needs to be specified from the outside. From this point of view, it does not really make sense to think about this as a property.

Also, it is a common pattern in Swift to be let caller to be explicit about type-as-argument in such scenarios:

func lowerL<T>(of type: T.Type) -> Point<T> where T: UL0 { ... }

// Usage with explicit type
lowerL(of: Int.self)

If solution by @SDGGiesbrecht does work for you, and you really want to express that lowerL is a "property that gives a point of element type of your choosing", you can return a wrapper type that delays specification of the element type, kinda like closure delays specification of the argument value:

// We can transform function into property returning a closure:
func foo(x: Int) -> Int
var foo: (Int) -> Int

// We can try do do something similar with type arguments:
func lowerL<T>() -> Point<T> where T: UL0
var lowerL: PointProvider

struct PointProvider {
    ...
    func get<T>() -> Point<T> where T: UL0 { ... }
}

But that's probably not what you were asking for.

1 Like

Thanks, your insights are interesting.

I wasn't aware of the common pattern of introducing a value type argument. It looks tautologous to the generic without a value argument, with the cost of new a stack parameter. Does it have more purpose that just improving expressiveness?

func lowerL() -> Point<T> where T : ULO
func lowerL<T>(of type: T.Type) -> Point<T> where T: UL0

You noted that lowerL() has argument T - surely that's only meaningful within an AST to verify typing, and the label T does not participate on the stack at runtime? That's why I'm still confused as to why only one of these cases is accepted by the compiler.

var lowerL : Point<T>
var lowerL : Point<T> where T : ULO

Swift doesn't support properties with where clauses, regardless of whether you've used a generic type.