Pitching The Start of Variadic Generics

I agree with you. If specific index or indices like T[5] (6th type parameter) have special meaning and it should be String, it means you should split them into different parameters, like <T0, T1, T2, T3, T4, Rest...>. Constraints like where 2 <= n have similar problem. It would mean, certain two type parameters have special meaning. Therefore, perhaps you should use perameter-split strategy like <First, Second, Rest...>, <First, Middle..., Last> or other corresponding signature for your intention.

Nevertheless, I think some type of constraints cannot be expressed without subscript-like syntax. (using @Jumhyn's forEach like syntax).

// declare fixed-length version of chain
static func buildBlock<A, B, C, D>(_ f: (A) -> B, _ g: (B) -> C, _ h: (C) -> D) -> A -> D {
    let f0 = { (value: A) in value }        // f0: (A) -> A
    let f1 = { (value: A) in f(f0(value)) } // f1: (A) -> B
    let f2 = { (value: A) in g(f1(value)) } // f2: (A) -> C
    let f3 = { (value: A) in h(f2(value)) } // f3: (A) -> D
    return f3
}

// variadic version
static func buildBlock<type(n) Input, types(n) Output>(
//                     ~~~~~^~~~~~     ~~~~~^~~~~~   
//              specify exact number of type parameters
    _ closures: ((Input) -> Output)...
) -> (Input[0]) -> Output[n-1] where 1 <= n, forEach(i, i+1 in 0 ..< n) Input[i+1] == Output[i]
//                                                   ~~~~~~~~^~~~~~~~~
//                                             ensure i and i+1 in valid range 

I tried but couldn't write this function without <= and subscript access. When I add FirstInput and LastOutput to remove <= and(Input[0]) -> Output[n-1], I couldn't write the signature of closures. I think subscript like range access would also have such usage in some rare conditions.

By the way, it also means that further discussion is required about how to treat variadic values. The pitch describes map , but reduce like operation would be also required. Chain would not be able to be expressed with only map and for .

static func buildBlock<type(n) Input, types(n) Output>(
    _ closures: ((Input) -> Output)...
) -> (Input[0]) -> Output[n-1] where 1 <= n,  forEach(i, i+1 in 0 ..< n) Input[i+1] == Output[i] {
    // how to chain closures here...?
}

(EDIT) I was replying to the wrong address. This is not a reply to @nonsensery, I'm sorry :bowing_man:
This is a reply to @maustinstar.

1 Like