> Le 28 avr. 2016 à 03:34, Pyry Jahkola via swift-evolution
> <[email protected]> a écrit :
>
> 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.
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
>
>> 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
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution