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 <[email protected]> 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>,
 it's unusual to use `self` here.
            mutate halve()      // Where would you put the `&` prefix in this?
        }
    }

— Pyry

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to