> On May 28, 2016, at 9:29 PM, Brent Royal-Gordon <br...@architechies.com> 
> wrote:
> 
>>> You are trying to call `mutating` methods on an *immutable* value, the 
>>> return value of `withCopy`. Normally, the compiler would reject that.
>> 
>> You are right, there would need to be an exception for method cascades.  
>> That might be a reasonable exception to make because we already know the 
>> temporary is not just the subject of mutation but also the result of the 
>> expression.  The method cascade just operates on the temporary in-place 
>> before being used in the surrounding expression or statement .
>> 
>>> Perhaps you could say that method cascades operate on a copy if the 
>>> receiver is immutable
>> 
>> This isn’t necessary with the previously mentioned exception for allowing 
>> mutating method cascades on temporaries.
> 
> I don't understand what you mean by "temporary”.

I mean a return value.

> Are you saying that Swift should distinguish between things which could be 
> mutable but don't happen to be (variables and subscripts), and things which 
> cannot ever be mutable (functions and methods)?

No.  I’m saying that whether the return value temporary is immutable or mutable 
is something the language defines (not something the user declares anywhere).  
The language rules for method cascades could be defined such that they create a 
contextual type environment that allows the return value temporary to be 
mutable to allow the method cascade to operate on the temporary in place before 
it is used in the surrounding expression.  This makes sense for method cascades 
because by definition they return the original value.  It does not make sense 
for arbitrary operations because they will not return the original value.

Applying mutating method cascades to temporary value could be very handy.  You 
have an expression that returns a value and mutate the result before storing it 
in a binding or returning it from your function.  You can do this by binding 
the result to an explicit temporary and giving it a name.  Allowing you to do 
it with method cascades on the implicit temporary is great syntactic sugar and 
a big argument for making them work well with value types, not just reference 
types IMO.


> Will this distinction hold up when we get `inout`-returning functions?

What I describe above would mean return values behave like a `var` argument 
used to (before they were removed) when the return value has a method cascade 
attached to it.  `inout` return values would work differently, writing back to 
the source storage.

> 
> Basically, what principled rule makes Swift treat this:
> 
>       immutableVariable..mutatingMethod()
> 
> And this:
> 
>       functionCall()..mutatingMethod()
> 
> Differently?

The rule is that it is safe to mutate a return value temporary copy in place 
without impacting the semantics of any code that relies on immutability.  The 
mutation happens prior to any code getting a chance to do anything with the 
value.  The mutation is really part of the expression itself and the method 
cascade provides a safe syntactic and semantic environment for allowing this 
mutation.

> 
> Or is the distinction between this:
> 
>       immutableVariable..mutatingMethod()
> 
> And this:
> 
>       mutableVariable..mutatingMethod()
> 
> And if so, how is that not going to lead to bugs when people move code around?

That distinction is absolutely critical.  The former is not allowed.  I am not 
suggesting allowing calling mutating methods on any `let` constants.  What I am 
saying is that the semantics of method cascades allow them to be safely used 
with return value temporaries even when they mutate the temporary.

-Matthew

> 
> -- 
> Brent Royal-Gordon
> Architechies
> 

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

Reply via email to