<html><head><style>
body {
        font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
        padding:1em;
        margin:auto;
        background:#fefefe;
}

h1, h2, h3, h4, h5, h6 {
        font-weight: bold;
}

h1 {
        color: #000000;
        font-size: 28pt;
}

h2 {
        border-bottom: 1px solid #CCCCCC;
        color: #000000;
        font-size: 24px;
}

h3 {
        font-size: 18px;
}

h4 {
        font-size: 16px;
}

h5 {
        font-size: 14px;
}

h6 {
        color: #777777;
        background-color: inherit;
        font-size: 14px;
}

hr {
        height: 0.2em;
        border: 0;
        color: #CCCCCC;
        background-color: #CCCCCC;
    display: inherit;
}

p, blockquote, ul, ol, dl, li, table, pre {
        margin: 15px 0;
}

a, a:visited {
        color: #4183C4;
        background-color: inherit;
        text-decoration: none;
}

#message {
        border-radius: 6px;
        border: 1px solid #ccc;
        display:block;
        width:100%;
        height:60px;
        margin:6px 0px;
}

button, #ws {
        font-size: 12 pt;
        padding: 4px 6px;
        border-radius: 5px;
        border: 1px solid #bbb;
        background-color: #eee;
}

code, pre, #ws, #message {
        font-family: Monaco;
        font-size: 10pt;
        border-radius: 3px;
        background-color: #F8F8F8;
        color: inherit;
}

code {
        border: 1px solid #EAEAEA;
        margin: 0 2px;
        padding: 0 5px;
}

pre {
        border: 1px solid #CCCCCC;
        overflow: auto;
        padding: 4px 8px;
}

pre > code {
        border: 0;
        margin: 0;
        padding: 0;
}

#ws { background-color: #f8f8f8; }


.bloop_markdown table {
border-collapse: collapse;  
font-family: Helvetica, arial, freesans, clean, sans-serif;  
color: rgb(51, 51, 51);  
font-size: 15px; line-height: 25px;
padding: 0; }

.bloop_markdown table tr {
border-top: 1px solid #cccccc;
background-color: white;
margin: 0;
padding: 0; }
     
.bloop_markdown table tr:nth-child(2n) {
background-color: #f8f8f8; }

.bloop_markdown table tr th {
font-weight: bold;
border: 1px solid #cccccc;
margin: 0;
padding: 6px 13px; }

.bloop_markdown table tr td {
border: 1px solid #cccccc;
margin: 0;
padding: 6px 13px; }

.bloop_markdown table tr th :first-child, table tr td :first-child {
margin-top: 0; }

.bloop_markdown table tr th :last-child, table tr td :last-child {
margin-bottom: 0; }

.bloop_markdown blockquote{
  border-left: 4px solid #dddddd;
  padding: 0 15px;
  color: #777777; }
  blockquote > :first-child {
    margin-top: 0; }
  blockquote > :last-child {
    margin-bottom: 0; }

code, pre, #ws, #message {
    word-break: normal;
    word-wrap: normal;
}

hr {
    display: inherit;
}

.bloop_markdown :first-child {
    -webkit-margin-before: 0;
}

code, pre, #ws, #message {
    font-family: Menlo, Consolas, Liberation Mono, Courier, monospace;
}


.send { color:#77bb77; }
.server { color:#7799bb; }
.error { color:#AA0000; }</style></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="bloop_markdown"><p>Hello folks,</p>

<p>I’d like to revive the discussion about the <a href="https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#variadic-generics"><strong>Variadic generics</strong></a> feature from the generics manifesto.</p>

<p>There exist an older draft proposal from <a href="https://github.com/austinzheng/swift-evolution/blob/az-variadic-generics/proposals/XXXX-variadic-generics.md">Douglas Gregor and Austin Zheng</a>.</p>

<p>As part of this discussion I also would like to talk about the possibly of a new enum type <code>Wrapped</code> (some of you might be familiar with <code>Result</code> or <code>Either</code> type). To be clear about this, I do not want to introduce a <em>union type</em> here, because if you might not know:</p>

<blockquote>
<p><a href="https://lists.swift.org/pipermail/swift-evolution-announce/2016-June/000182.html">Disjunctions (logical ORs) in type constraints:</a> These include anonymous union-like types (e.g. (Int | String) for a type that can be inhabited by either an integer or a string). “[This type of constraint is] something that the type system cannot and should not support.”</p>

<p>Source: <a href="https://github.com/apple/swift-evolution/blob/master/commonly_proposed.md#miscellaneous">Commonly Rejected Changes</a></p>
</blockquote>

<p>But I still have hope for the infix <code>|</code> type operator as part of the <code>Wrapped</code> enum.</p>

<p>To beginn with, I’d like to thank to Douglas and Austin for their work back then and putting this draft together. To be honest while reading the proposal I found it hard to keep track of where the prefix <code>…</code> and where the postfix <code>…</code> was used. Especially it was really confusing to understand the behavior of each <code>…</code> operator.</p>

<p>Let’s look at the following 3 examples from the proposal:</p>

<pre><code class="swift">struct Foo&lt;...C : Collection&gt; {
    // Indices and C are bound to be the same length.
    typealias ...Indices = C.Index...

    // A value vector of indices
    var (...startIndices): (Indices...)

    init(...x: C...) {
        startIndices... = x.startIndex...
    }
}

struct Foo&lt;...T : CustomStringConvertible&gt; {

    var (...descriptions): (String...)

    init(...x: T) {
        // .description goes from Tn -&gt; String
        // Because of this, descriptions' length is identical to that of T.
        descriptions... = x.description...
    }
}

// NOT ALLOWED!!!
struct Foo&lt;...T : CustomStringConvertible&gt; {

    var (...descriptions): (String...)

    mutating func doSomething() {
        descriptions... = ("foo", "bar", "baz")
    }
}
</code></pre>

<p>The first problem I realize here, is that the <code>...</code> prefix has no ability to describe its own boundary and therefore the last example is not possible.</p>

<p>As contrast to this I’d like to pitch a new keyword <code>vector</code> and <code>vector(Boundary_Size)</code> (we could also use <code>params</code> instead, like in C#). Without the explicit <code>Boundary_Size</code>, which could be from 1 to (positive) n, the vector is unbound and acts exactly like the proposed <code>...</code> prefix.</p>

<p>Let’s rewrite and reposition a few things from above with the new keyword:</p>

<pre><code class="swift">struct Foo&lt;vector C : Collection&gt; {

    // Indices vector is bound to be the same length as its parent scope C vector, because we're using its `Index` here.
    typealias vector Indices = vector C.Index

    // A value vector of indices
    // Note: We *might* omit `vector` here for the value, because its type
    // already is a vector, or we want to be explicit everywhere?!
    vector var startIndices: Indices
     
    // Alternative 1 (preferred):
    var startIndices: Indices
     
    // Alternative 2 (still okay):
    var startIndices: vector Indices
     
    // Alternative 3 (really strange):
    vector var startIndices: vector Indices

    // Same here, `C` is a vector, so we could omit `vector` keyword before x
    init(vector x: C) {
     
        // Since the vectors `startIndices` and `x` are bound by a  
        // unbound *parent scope vector* we don't need the postfix `...`
        self.startIndices = x.startIndex
    }
     
    // Alternative 1:
    init(x: C) {
        self.startIndices = x.startIndex
    }
     
    // Alternative 2:
    init(x: vector C) {
        self.startIndices = x.startIndex
    }
}

struct Foo&lt;vector T : CustomStringConvertible&gt; {

    // When there is no other context than the unbound parent scope vector,
    // the following vector will have the same length, otherwise it will be unbound.
    var descriptions: vector String

    init(x: T) {
        // .description goes from Tn -&gt; String
        // Because of this, descriptions' length is identical to that of T.
        self.descriptions = x.description
    }
}

// Allowed now
struct Foo&lt;vector T : CustomStringConvertible&gt; {

    // This vector has an explicit boundary size and therefore not bound  
    // to vector T
    vector(3) var descriptions: String
     
    // Alternative:
    var descriptions: vector(3) String

    mutating func doSomething() {
     
        // Assigning can be made with tuples
        self.descriptions = ("foo", "bar", "baz")
    }
}
</code></pre>

<p>From my personal point of view this new approach is way easier to read. A really good thing about it, is that it eliminates the ugly pre-/postfix <code>...</code> confusion.</p>

<hr>

<p>Now let’s scratch the surface of the mentioned <code>Wrapped</code> enum.</p>

<p>Recently I bumped into an issue where no Swift feature could nicely solve it for me, not even conditional conformances with it’s full power. The only possible solution would be such a <code>Wrapped</code> enum (the only one in the whole language) or the ability to implicitly wrap any instances into enum cases when it’s possible.</p>

<pre><code class="swift">// Implicitly wrapping

enum MyEnum {
    case string(String)
    case integer(Int)
}

let int = 42

// Matched against the cases and wrapped if possible, otherwise it'll be an error
let e1: MyEnum = int

// There is no `ExpressibleByStringLiteral` here, so the literal fallback to  
// its default type `String`, than matched against all the cases and wraps into `.string(String)`
let e2: MyEnum = "Swift"    

// Wrapped enum, with the same functionality as above.
enum Wrapped&lt;vector T&gt; {

    // How about the ability of extracting the vector index?
    vector case vector.index(T)
     
    // Alternative
    vector case #(T)
}

let e3: Wrapped&lt;String, Int&gt; = 0 // implicitly wrapped into `.1(Int)`

switch e3 {

case .0(let stringValue):
    print(stringValue)
     
case .1(let intValue)
    print(intValue)
}

// Yes, this is not a typo but a possible useless artifact.
// For the Wrapped enum we could check for same types (probably very complex to achieve), or just leave it as is.
let e4: Wrapped&lt;String, String&gt; = "test"

switch e3 {

case .0(let stringValue):
    print(stringValue)
     
case .1(let stringValue)
    // Will never print
    print(stringValue)
}
</code></pre>

<p>As mentioned above I’d like to use the infix <code>|</code> type operator for the <code>Wrapped</code> enum as a shortcut.</p>

<pre><code class="swift">let x: Wrapped&lt;A, B, C&gt; = ...
let x: A | B | C = ...

// x.0(A)
// x.1(B)
// x.2(C)
</code></pre>

<hr>

<p>Any feedback is much appreciated. :)</p>

<p></p></div><div class="bloop_original_html"><style>body{font-family:Helvetica,Arial;font-size:13px}</style><div id="bloop_customfont" style="font-family:Helvetica,Arial;font-size:13px; color: rgba(0,0,0,1.0); margin: 0px; line-height: auto;"><br></div><br><div id="bloop_sign_1479801817699141120" class="bloop_sign"><div style="font-family:helvetica,arial;font-size:13px">--&nbsp;<br>Adrian Zubarev<br>Sent with Airmail</div></div></div><div class="bloop_markdown"><p></p></div></body></html>