[swift-evolution] Idea for Restricted "Pseudo-Dynamic" Typing

davesweeris at mac.com davesweeris at mac.com
Tue Jan 12 17:40:09 CST 2016


(Disclaimer: This might actually just be a slightly disguised subset of the “allow non-type generic parameters” idea, depending on whether that includes stuff like this:
> var foo = 2
> var bar = Vector<foo>()
or if it only addresses this:
> var bar = Vector<2>()
)

Building on “pure" from: https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151214/003684.html <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151214/003684.html>

Consider this function:
> func @pure foo<T,U,V>(_: T.Type, _: U.Type) -> V.Type {…}


Since @pure prevents foo from accessing global/static variables, since it can only call other @pure functions, and since its only parameters are themselves other types, then the return type of V must solely depend on the *types* T and U (and what can be gotten from T & U using @pure functions). While this is not the same thing as “known at compile time”, it does (I think) guarantee that V can be deduced only using what is known about T and U *at compile time*. If the return value of such a function could used as a “proper” type (i.e., it could be used like “var bar: foo(Int.self, String.self)”, for instance), it wouldn’t so much remove the “types must be known at compile time” restriction, as it would give the programmer a powerful way to tell the compiler *how* to figure out what the type is.

The use case I’m thinking of is admittedly pretty narrow… I  personally want this feature to help with a work-around I’m using for Swift not having non-type generic parameters:
> protocol IVAT { //Integer Value As Type
> 	static var integerValue:Int {get} 
> }
> struct _0 : IVAT { static let integerValue = 0 }
> struct _1 : IVAT { static let integerValue = 1 }
> struct _2 : IVAT { static let integerValue = 2 }
> //…etc
>  
> struct Matrix<M:IVAT, N:IVAT> {
> 	private var backing = [[Double]](count: M.integerValue, repeatedValue: [Double](count: N.integerValue, repeatedValue: 0.0))
> 	subscript(row: Int, col: Int) -> Double {}
> }


If we allowed pure functions to return “usable” types, then Matrices could be joined like this:
> func @pure + <T: IVAT, U: IVAT, V: IVAT> (_: T.Type, _: U.Type) -> V.Type {
> 	switch (T, U) {
> 	case (_0, _0): return _0.self
> 	case (_0, _1): return _1.self
>> 	default: return _0.self
> }
> // joins two matrices… join([[1,2],[3,4]], [[5],[6]]) would return [[1,2,5],[3,4,6]] 
> func join <M:IVAT, N1:IVAT, N2:IVAT> (lhs: Matrix<M,N1>, rhs: Matrix<M, N2>) -> Matrix<M, N1.self + N2.self> {…}

Again, I realize the use case I’ve presented is pretty narrow (and one that’ll hopefully become a moot point later), but it seems like this would be a *very* expressive way to expand the power of generic types.

Anyway… Yay? Nay? Implementation-wise, my first thought is to embed the REPL in the generic specialization system then use the function in question as its input to extend the generic specialization system, but I don’t know if that’s the right place to handle it, let alone if that’s a feasible idea.

-Dave
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160112/7a1ab1fd/attachment.html>


More information about the swift-evolution mailing list