mutating/non-mutating suggestion from a Rubyist

Hello Dave,

That makes these people suspicious of language features that could
threaten to make classes “second-class citizens.”

...and that is unfortunate when emotions and resistance to positive change worsen the discussion, but if you take a look at discussion related to abstract classes and methods, there is not a lack of "POP is the new way, why dedicate time on this at all, let's invest in protocols alone..." kind of comments fearing that protocols did not receive deserved preferential treatment.

[[iOS messageWithData:ideas] broadcast]

···

On 25 Apr 2016, at 19:48, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:

That makes these people suspicious of language features that could
threaten to make classes “second-class citizens.”

We've already discussed this whole question length, specifically
considered the direction of an almost-identical language feature, and
ended up settling on the “form/ed/ing” naming conventions. If there is
some new information since then, it would be possible to handle
something like this via a new evolution proposal. However, anything
like that is way out of scope for Swift 3, and in the absence of new
information, it isn’t a productive use of time to rehash it at all.

···

on Tue Apr 26 2016, Thorsten Seitz <tseitz42-AT-icloud.com> wrote:

Am 23.04.2016 um 10:27 schrieb Pyry Jahkola via swift-evolution > <swift-evolution@swift.org>:

    I'd like to second James Campbell's suggestion of a `mutate` keyword.
    Clarifying comments inline below:

        On 23 Apr 2016, at 00:24, Dave Abrahams via swift-evolution > <swift-evolution@swift.org> wrote:

        This is not a new idea. Something almost identical to this has been
        explored and discussed quite thoroughly already:
        <https://github.com/apple/swift/blob/master/docs/proposals/Inplace.rst&gt;\.
        In fact, it was implmented and later reverted because it raised
        language-design questions for which we had no good answers.

    I don't know if the following are particularly good answers, but I'll try
    anyway:

        I don't believe the choice of glyph (& vs =) affects any of the

        fundamental issues:

        * Should the x.=f() syntax be required for *every* mutating method
        invocation?

    Allow me to ask it differently: Should some specific syntax be required for
    every mutating method? — Yes.

I think I like that idea.

    Should the syntax be `x.=f()`? — Not necessarily. I kinda like James
    Campbell's idea of a `mutate` keyword. Consider the following:

    var numbers = [5, 12, 6, 2]
    mutate numbers.append(10)
    mutate numbers.sort()
    if let biggest = mutate numbers.popLast() {
    print("The biggest number was:", biggest)
    }

    So `mutate` would work much like `try` but—unlike `try` which can move
    further to the left—`mutate` would have to always prefix the mutating
    receiver.

That doesn't look so bad (we might shorten 'mutate' to 'mut', though I don't
think that would be really necessary).

--
Dave

If we do go ahead with this then put me in the “mutate” camp, as I’d actually prefer to see & on inout variables be replaced by the inout keyword at the call-site for consistency. That said, the reason I want that is because inout variables are fairly uncommon (though with indexing changes that will change), but it also looks fairly ugly IMO.

Still, for the feature itself I’m of two minds; the naming convention was just changed to enable clear distinctions between mutating and non-mutating methods, but if we had this feature that distinction wouldn’t actually be necessary, we can just call all forms of sorting .sort() and the mutate keyword (or lack of) would distinguish which one is meant, and failure to use a return value would pick up on mistakes. I’d hate to go through the whole naming debate again, but at the same time that would be simpler in a way.

So I’m a +1 if we can also use it to roll mutating and non-mutating methods under the same name, even though I don’t want to go through the naming transition all over again ;)

···

On 26 Apr 2016, at 14:48, Thorsten Seitz via swift-evolution <swift-evolution@swift.org> wrote:

Should the syntax be `x.=f()`? — Not necessarily. I kinda like James Campbell's idea of a `mutate` keyword. Consider the following:

    var numbers = [5, 12, 6, 2]
    mutate numbers.append(10)
    mutate numbers.sort()
    if let biggest = mutate numbers.popLast() {
        print("The biggest number was:", biggest)
    }

So `mutate` would work much like `try` but—unlike `try` which can move further to the left—`mutate` would have to always prefix the mutating receiver.

That doesn't look so bad (we might shorten 'mutate' to 'mut', though I don't think that would be really necessary).
I'm wondering how to deal with fluent interfaces which do mutate the receiver and return 'self', i.e. the builder pattern. I think we can simply require that such a chained expression is required to consist of only mutating calls (or only non-mutating calls), so that one 'mutate' for the whole expression would be sufficient.
Expressions combining mutating calls to different receivers which have return values would simply be prohibited. This would probably be bad style anyway (contrary to the fluent example), or does anyone have a good counter example?

I like this idea very much. I believe '&' should belong to instance variable, as it will be mutated, just like for inout parameter, so

c&.frobnicate(i)
let k = c&.frobnicate(&i)

very clear and explicit. Don't like the 'mutation' or even 'mut' as we'll have heavy code, as it is a word just like functions/methods/variable names and IMO harder to parse visually. '&' is a 'marker', that clearly parsed.

···

On 26.04.2016 16:48, Thorsten Seitz via swift-evolution wrote:

As an alternative to the mutate keyword I rather like using '&' because it
already means 'inout'. Using '&.' as mutating method call would therefore
be quite understandable.

c&.frobnicate(i)
let k = c&.frobnicate(&i)

Or marking the method like suggested elsewhere:

c.frobnicate&(i)
let k = c.frobnicate&(&i)

-Thorsten

Good that you brought the topic of "fluent" interfaces up. I don't see any problem with explicit value type mutation and method chaining because fluent interfaces are constrained to reference types by the language. Details below:

How would this chain if I wanted to do something like:

let median = foo.calculateBigHugeArray().sort().medianValue()

and I want the sort to be done in place.

I think I can guess what you wanted the above to mean but, mind you, the in-place sort returns `()` so you wouldn't chain its result like that. On the other hand, the above code already works using the non-mutating `.sort()` (to be known as `.sorted()` in Swift 3), and—correct me if I'm wrong—the compiler probably optimises the copy away using copy-on-write anyway.

Or will this type of thing just be disallowed in favor of.

let array = foo.calculateBigHugeArray()
mutate array.sort()
let median = array.medianValue()

Yes, I think mutating code should be written in many statements rather than squeezing everything into one long expression.

Indeed, no currently working method chaining would be disallowed in my proposal. Let's consider the example of "fluent API" for value types, i.e. one where you'd extensively `return self` in `mutating` methods. Firstly, the stdlib doesn't practice that at all. And I failed to find any popular Swift libraries that would do so on Github either. The reason is simple: fluent mutating APIs on value types don't work.

Consider the following silly example that shortens an array in half (but demonstrates the use of `return self` in a `mutating` method):

    extension Array {
        mutating func halve() -> Array {
            self = self[0 ..< count / 2]
            return self
        }
    }

Suppose I want to get the result of halving an array twice. What happens?

    var xs = [1,2,3,4,5,6,7,8]
    xs.halve().halve()
    // error: cannot use mutating member on immutable value: function call returns immutable value

So no, fluent APIs on value types are not a thing in Swift. Not now at least. Making mutation explicit along this proposal has nothing to do with fluent APIs.

Alternately you could replace the method invocation operator with &

let median = foo.calculateBigHugeArray()&sort().medianValue()

Don't you think that's too prone to getting mixed up with the binary `&` operator?

Also, if you wanted to stick with consistent & syntax, you could do:

&c.frobnicate(i)
and
let k = &c.frobnicate(&i)

Yeah, probably. However, one place where that notation falls short compared to a prefixing keyword like `mutate` is when mutating `self`:

    extension Array {
        // Apologies for not having the time to think of a less contrived example than this!
        mutating func quarter() {
            mutate self.halve() // Ever since SE-0009 <https://github.com/apple/swift-evolution/blob/master/proposals/0009-require-self-for-accessing-instance-members.md&gt;, it's unusual to use `self` here.
            mutate halve() // Where would you put the `&` prefix in this?
        }
    }

— Pyry

···

On 28 Apr 2016, at 03:44, Tyler Cloutier <cloutiertyler@aol.com> wrote:

@Tyler,

Excellent summary of concerns which has made me revise my preferences!

I would suggest a few differences from your suggestions (primarily based on
the interpretation of `mutating <name>` as the name of the method, i.e. the
method name includes `mutating`). The couple of areas I suggest are:

    1. Use `mutating` after `func` in declarations: `func mutating
sort(...)`.
    2. Use mutating after `.` in calls: `array.mutating sort(<)`
    3. Allow mutating for classes:

        protocol P { func mutating p() }
        class AP: P { func mutating p() { ... }
        let aP = AP()
        aP.mutating p() // Mutates what `aP` points to

    2. Treat mutating as part of name when chaining:

        let median = foo.calculateBigHugeArray().mutating
sort().medianValue()

  -- Howard.

···

On 28 April 2016 at 10:44, Tyler Cloutier via swift-evolution < swift-evolution@swift.org> wrote:

On Apr 23, 2016, at 1:27 AM, Pyry Jahkola via swift-evolution < > swift-evolution@swift.org> wrote:

I'd like to second James Campbell's suggestion of a `mutate` keyword.
Clarifying comments inline below:

On 23 Apr 2016, at 00:24, Dave Abrahams via swift-evolution < > swift-evolution@swift.org> wrote:

This is not a new idea. Something almost identical to this has been
explored and discussed quite thoroughly already:
<https://github.com/apple/swift/blob/master/docs/proposals/Inplace.rst&gt;\.
In fact, it was implmented and later reverted because it raised
language-design questions for which we had no good answers.

I don't know if the following are particularly good answers, but I'll try
anyway:

I don't believe the choice of glyph (& vs =) affects any of the

fundamental issues:

* Should the x.=f() syntax be required for *every* mutating method
invocation?

Allow me to ask it differently: Should *some* specific syntax be required
for every mutating method? — Yes.

Should the syntax be `x.=f()`? — Not necessarily. I kinda like James
Campbell's idea of a `mutate` keyword. Consider the following:

    *var* numbers = [5, 12, 6, 2]
    *mutate* numbers.append(10)
    *mutate* numbers.sort()
    *if let* biggest = *mutate* numbers.popLast() {
        print("The biggest number was:", biggest)
    }

So `mutate` would work much like `try` but—unlike `try` which can move
further to the left—`mutate` would have to always prefix the mutating
receiver. Here's a contrived example of a corner case:

    *enum* Error : ErrorType { *case* BadNumber }

    *func* demo() *throws* -> Int {

    }

* Are assignment methods a redundant way to spell mutating methods?
Should we really have both mechanisms?

(I had to look up the definition of an *assignment method*. For the
uninitiated, Dave is talking about what's written here:
https://github.com/apple/swift/blob/master/docs/proposals/Inplace.rst#use-one-simple-name
.)

— Yes they are redundant, and no, we should not have both.

With `mutate` required at the call site, we could simply allow both
overloads `*func* sort()` and `*mutating func* sort()` to coexist,
because the call sites become unambiguous:

    *let* originals = [2, 1, 3, 0, 4, 2]
    *var* copies = originals

    originals.sort() // *warning:* result of call to 'sort()'
is unused
    *mutate* originals.sort() // *compiler error*
    *let* xs = originals.sort() // ok

    copies.sort() // *warning:* result of call to
'sort()' is unused
    *mutate* copies.sort() // ok
    *let* ys = copies.sort() // ok
    *let* zs = mutate copies.sort() // *warning:* constant 'x' inferred
to have type '()', which may be unexpected

The language could also allow the use of

* mutate* x.next()

as shorthand for

    x = x.next()

when only the non-mutating variant `*func* next() -> *Self*` exists with
compatible return type.

* Can we really introduce this feature without having a way to apply it
to class types?

Yes we can. Why complicate the naming of value type members with the
complexities of reference semantics? The current API naming conventions are
*good* for reference types which sometimes come with unobvious to obscure
behaviour (i.e. anything from bumping an internal counter to firing
missiles and wiping hard drives).

But value types ought to have no side effects (besides memory allocation
and logging maybe), and so we don't necessarily need that strong a naming
convention to limit their collateral damage.

If the `mutate` keyword became required for calling `mutating` methods,
then operators would remain the only place where naming convention were
needed to distinguish mutation:

   - Mutating assignment is *explicit*: `xs = [1, 2] + xs + [2, 1]` (i.e.
   `=` without `let` or `var` means mutation)
   - Mutating method call becomes *explicit*: `*mutate* xs.sort()` and `
   *let* x = *mutate* xs.removeAtIndex(2)`
   - Mutating function arguments are *explicit* with the `&` prefix: `swap(&xs,
   &ys)`
   - Mutating operators are *implicit* and *by convention,* should end
   with the `=` symbol: `xs += [8, 9]`
   - Reference types have no notion of `mutating` members (and probably
   ought to remain that way) so they mutate *implicitly*.

I should also point out that under the assignment method paradigm one
would probably need to re-evalutate rules for naming. Under the current
API guidelines' approach, we'd write:

   x.=sorted() // sort x in-place

and I am not sure how easy that would be for people to swallow
considering how much more straightforward

   x.sort() // current way to sort x in-place

is, and because the language now contains explicit notation for
mutation, it becomes harder to argue against theis pair:

   y = x.sort()
   x.=sort() // sort x in place

I agree that the current API guidelines wouldn't work for value types
anymore. Both `sort` and `sorted` would be called `sort`.

Lastly, I should point out that the proposal does nothing to solve the
problem of `c.formSuccessor(&i)`, since that doesn't mutate the
receiver.

This proposal does address the problem of `c.formSuccessor(&i)`. Given
that it's value types at play here, what mutates in the following is
unambiguous even to non-native English speakers:

    c.frobnicate(&i) // cannot possibly mutate c but
mutates i
    *let* j = c.frobnicate(i) // cannot possibly mutate either
    *mutate* c.frobnicate(i) // mutates c
    *let* k = *mutate* c.frobnicate(&i) // mutates both

How would this chain if I wanted to do something like:

let median = foo.calculateBigHugeArray().sort().medianValue()

and I want the sort to be done in place. Or will this type of thing just
be disallowed in favor of.

let array = foo.calculateBigHugeArray()
mutate array.sort()
let median = array.medianValue()

Alternately you could replace the method invocation operator with &

let median = foo.calculateBigHugeArray()&sort().medianValue()

Or depending how sacrilegious you’re feeling you could use the only
character on the keyboard that isn’t currently used and doesn’t require the
shift key and is easily distinguished from a ‘.’

let median = foo.calculateBigHugeArray()'sort().medianValue()

This is definitely more confusing than the & and mutate, since & is used
to indicate mutation elsewhere.

Also, if you wanted to stick with consistent & syntax, you could do:

&c.frobnicate(i)
and
let k = &c.frobnicate(&i)

Dave, to your point about classes, there is currently already special
syntax for value types with the & as parameters. Reference semantics is the
wild west there anyway.

I still like the proposal's basic approach and would love to see it used
to address these naming problems, but I want to be clear that it's by no
means a panacea and there are real obstacles between here and actually
being able to apply it. If you want to move forward with something like
this, you need to solve the problems described above.

I think this proposal would simplify all code handling value types. Yes,
it adds one keyword of boilerplate but wins clarity in return. I think
reference types should stay separate from this discussion, as their
mutation has always been implicit anyway. The API guidelines set a good
convention for them.

— Pyry

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

You are very correct. Yup, that pretty much addresses all of my concerns. So count me amongst the fans.

I had something like popLast in mind, but as you point out, return values are immutable in Swift.

struct Foo {
    var y = [5, 6]
    func foo() -> [Int] {
        return y
    }
}
var x = Foo()
x.foo().popLast()?.advanced(by: 1) // error: Cannot use mutating member on immutable value: function call returns immutable value

Thanks!

···

On Apr 28, 2016, at 12:34 AM, Pyry Jahkola <pyry.jahkola@iki.fi> wrote:

Good that you brought the topic of "fluent" interfaces up. I don't see any problem with explicit value type mutation and method chaining because fluent interfaces are constrained to reference types by the language. Details below:

On 28 Apr 2016, at 03:44, Tyler Cloutier <cloutiertyler@aol.com <mailto:cloutiertyler@aol.com>> wrote:

How would this chain if I wanted to do something like:

let median = foo.calculateBigHugeArray().sort().medianValue()

and I want the sort to be done in place.

I think I can guess what you wanted the above to mean but, mind you, the in-place sort returns `()` so you wouldn't chain its result like that. On the other hand, the above code already works using the non-mutating `.sort()` (to be known as `.sorted()` in Swift 3), and—correct me if I'm wrong—the compiler probably optimises the copy away using copy-on-write anyway.

Or will this type of thing just be disallowed in favor of.

let array = foo.calculateBigHugeArray()
mutate array.sort()
let median = array.medianValue()

Yes, I think mutating code should be written in many statements rather than squeezing everything into one long expression.

Indeed, no currently working method chaining would be disallowed in my proposal. Let's consider the example of "fluent API" for value types, i.e. one where you'd extensively `return self` in `mutating` methods. Firstly, the stdlib doesn't practice that at all. And I failed to find any popular Swift libraries that would do so on Github either. The reason is simple: fluent mutating APIs on value types don't work.

Consider the following silly example that shortens an array in half (but demonstrates the use of `return self` in a `mutating` method):

    extension Array {
        mutating func halve() -> Array {
            self = self[0 ..< count / 2]
            return self
        }
    }

Suppose I want to get the result of halving an array twice. What happens?

    var xs = [1,2,3,4,5,6,7,8]
    xs.halve().halve()
    // error: cannot use mutating member on immutable value: function call returns immutable value

So no, fluent APIs on value types are not a thing in Swift. Not now at least. Making mutation explicit along this proposal has nothing to do with fluent APIs.

Alternately you could replace the method invocation operator with &

let median = foo.calculateBigHugeArray()&sort().medianValue()

Don't you think that's too prone to getting mixed up with the binary `&` operator?

Also, if you wanted to stick with consistent & syntax, you could do:

&c.frobnicate(i)
and
let k = &c.frobnicate(&i)

Yeah, probably. However, one place where that notation falls short compared to a prefixing keyword like `mutate` is when mutating `self`:

    extension Array {
        // Apologies for not having the time to think of a less contrived example than this!
        mutating func quarter() {
            mutate self.halve() // Ever since SE-0009 <https://github.com/apple/swift-evolution/blob/master/proposals/0009-require-self-for-accessing-instance-members.md&gt;, it's unusual to use `self` here.
            mutate halve() // Where would you put the `&` prefix in this?
        }
    }

— Pyry

By the way,

I can be counted as +1 on reusing the keyword `mutating` here.

However, for the reasons stated in my previous email, I maintain that the keyword should go before the value being mutated rather than next to the function's name.

— Pyry

···

On 28 Apr 2016, at 10:59, Tyler Fleming Cloutier <cloutiertyler@aol.com> wrote:

Yup, that pretty much addresses all of my concerns. So count me amongst the fans.

No, the compiler can't automatically turn non-mutating operations into
in-place operations.

···

on Thu Apr 28 2016, Pyry Jahkola <swift-evolution@swift.org> wrote:

Good that you brought the topic of "fluent" interfaces up. I don't see any
problem with explicit value type mutation and method chaining because fluent
interfaces are constrained to reference types by the language. Details below:

    On 28 Apr 2016, at 03:44, Tyler Cloutier > <cloutiertyler@aol.com> wrote:

    How would this chain if I wanted to do something like:

    let median = foo.calculateBigHugeArray().sort().medianValue()

    and I want the sort to be done in place.

I think I can guess what you wanted the above to mean but, mind you, the
in-place sort returns `()` so you wouldn't chain its result like that. On the
other hand, the above code already works using the non-mutating `.sort()` (to be
known as `.sorted()` in Swift 3), and—correct me if I'm wrong—the compiler
probably optimises the copy away using copy-on-write anyway.

--
Dave

How about '&' as allowed prefix/suffix for method name as a marker of mutating method? I.e.

self.&halve()
&halve()

or

self.halve&()
halve&()

Actually, IMO &halve() is not a variant as it probably could be used in function like

something( &halve ) - confused

so, the suggestion is to have '&' suffix as marker of mutating methid:

self.halve&()
halve&()

···

On 28.04.2016 10:34, Pyry Jahkola via swift-evolution wrote:

* extension* Array {
        // Apologies for not having the time to think of a less contrived
example than this!
        *mutating* *func* quarter() {
            *mutate* *self*.halve() // Ever since SE-0009
<https://github.com/apple/swift-evolution/blob/master/proposals/0009-require-self-for-accessing-instance-members.md&gt;,
it's unusual to use `self` here.
            *mutate*halve() // Where would you put the `&` prefix in this?
        }
    }

Good that you brought the topic of "fluent" interfaces up. I don't see any problem with explicit value type mutation and method chaining because fluent interfaces are constrained to reference types by the language. Details below:

How would this chain if I wanted to do something like:

let median = foo.calculateBigHugeArray().sort().medianValue()

and I want the sort to be done in place.

I think I can guess what you wanted the above to mean but, mind you, the in-place sort returns `()` so you wouldn't chain its result like that. On the other hand, the above code already works using the non-mutating `.sort()` (to be known as `.sorted()` in Swift 3), and—correct me if I'm wrong—the compiler probably optimises the copy away using copy-on-write anyway.

Or will this type of thing just be disallowed in favor of.

let array = foo.calculateBigHugeArray()
mutate array.sort()
let median = array.medianValue()

Yes, I think mutating code should be written in many statements rather than squeezing everything into one long expression.

Indeed, no currently working method chaining would be disallowed in my proposal. Let's consider the example of "fluent API" for value types, i.e. one where you'd extensively `return self` in `mutating` methods. Firstly, the stdlib doesn't practice that at all. And I failed to find any popular Swift libraries that would do so on Github either. The reason is simple: fluent mutating APIs on value types don't work.

Consider the following silly example that shortens an array in half (but demonstrates the use of `return self` in a `mutating` method):

    extension Array {
        mutating func halve() -> Array {
            self = self[0 ..< count / 2]
            return self
        }
    }

Suppose I want to get the result of halving an array twice. What happens?

    var xs = [1,2,3,4,5,6,7,8]
    xs.halve().halve()
    // error: cannot use mutating member on immutable value: function call returns immutable value

So no, fluent APIs on value types are not a thing in Swift. Not now at least. Making mutation explicit along this proposal has nothing to do with fluent APIs.

But is this limitation as per design, or just something that no one reported as a bug yet? When acting on large piece of data and simple operations one might want to chain mutable version (to avoid large allocation) of the operations as a single stream (à la functional programming) instead of having to use multiple line of:
  mutate largeData.operation()

On a side note, this "long" explicit 'mutate' keyword could be seen by some as a way to impose the use immutability by making it harder (more to type) to use mutability.

Also, this 'mutate' could maybe help to differentiate between sort() 2.2-style and sort() 3.0-style, and avoid endless discussion on InPlace/form/ed/ing. But for language uniformity, would this new 'mutate' keyword be required on nearly every single standard OOP methods?

mutate graph.pencil.changeColor(Red) // the color properties of pencil is mutated
mutate graph.pencil.changeWidth(wide)
mutate graph.drawFrame() // the graphic is altered/mutated

Not proposing, just asking.

Dany

···

Le 28 avr. 2016 à 03:34, Pyry Jahkola via swift-evolution <swift-evolution@swift.org> a écrit :

On 28 Apr 2016, at 03:44, Tyler Cloutier <cloutiertyler@aol.com> wrote:

Alternately you could replace the method invocation operator with &

let median = foo.calculateBigHugeArray()&sort().medianValue()

Don't you think that's too prone to getting mixed up with the binary `&` operator?

Also, if you wanted to stick with consistent & syntax, you could do:

&c.frobnicate(i)
and
let k = &c.frobnicate(&i)

Yeah, probably. However, one place where that notation falls short compared to a prefixing keyword like `mutate` is when mutating `self`:

    extension Array {
        // Apologies for not having the time to think of a less contrived example than this!
        mutating func quarter() {
            mutate self.halve() // Ever since SE-0009, it's unusual to use `self` here.
            mutate halve() // Where would you put the `&` prefix in this?
        }
    }

— Pyry

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I'm talking about `.sorted()` in particular. Its implementation <https://github.com/apple/swift/blob/master/stdlib/public/core/CollectionAlgorithms.swift.gyb#L329-L335&gt; is essentially this:

    var result = ContiguousArray(self) // What if `self` is not used after this line?
    result.sort()
    return Array(result)

Depending on what `self ` is and how copy-on-write works, if `foo().sorted()` was called on a temporary (unique) Array returned by `foo()`, I believe the initialisation `ContiguousArray(self)` could be able to reuse `self._buffer` instead of making a copy. Whether it indeed does that, remains unclear to me, probably not <https://github.com/apple/swift/blob/master/stdlib/public/core/Arrays.swift.gyb#L925-L930&gt;\.

— Pyry

···

On 28 Apr 2016, Dave Abrahams wrote:

I think I can guess what you wanted the above to mean but, mind you, the
in-place sort returns `()` so you wouldn't chain its result like that. On the
other hand, the above code already works using the non-mutating `.sort()` (to be
known as `.sorted()` in Swift 3), and—correct me if I'm wrong—the compiler
probably optimises the copy away using copy-on-write anyway.

No, the compiler can't automatically turn non-mutating operations into
in-place operations.

        I think I can guess what you wanted the above to mean but, mind you, the
        in-place sort returns `()` so you wouldn't chain its result like that.
        On the
        other hand, the above code already works using the non-mutating `.sort()
        ` (to be
        known as `.sorted()` in Swift 3), and—correct me if I'm wrong—the
        compiler
        probably optimises the copy away using copy-on-write anyway.

    No, the compiler can't automatically turn non-mutating operations into
    in-place operations.

I'm talking about `.sorted()` in particular. Its implementation is essentially
this:

var result = ContiguousArray(self) // What if `self` is not used after this
line?
result.sort()
return Array(result)

Depending on what `self ` is and how copy-on-write works, if `foo().sorted()`
was called on a temporary (unique) Array returned by `foo()`, I believe the
initialisation `ContiguousArray(self)` could be able to reuse `self._buffer`
instead of making a copy.

Yes, *if* `self` was a contiguous array, there will be no copy in that
line, and *if* ARC can determine that `self` is not used after `result`
is constructed, then `result` will have a unique reference to the same
buffer and `result.sort()` can avoid doing a copy before mutating the
result.

Whether it indeed does that, remains unclear to me, probably not.

It's worth doing an experiment; it might well work. And if it doesn't,
someone should file a bug report :-)

···

on Thu Apr 28 2016, "pyry.jahkola--- via swift-evolution" <swift-evolution@swift.org> wrote:

    On 28 Apr 2016, Dave Abrahams wrote:

--
Dave