What about renaming Optional.map to Optional.mapMe ?


(Jay Zhao) #1

Hi there,

Code explains everything:

/// Maybe a bad API naming in Swift? See below:

        /// array1 can be array of any object that have a `count` method
        let array1 = [[String]]()
        let array2 :[String]? = nil
        
        // I believe the confusion between `array.map` and `optionalArray.map` is really bad.
        // Because when you read code like this, you can not tell which is which:
        _ = array1.map({$0.count})
        _ = array2.map({$0.count})
        
        // It can be clearer:
        // 1, we pass `self.element` into the closure
        _ = array1.map({$0.count})
        // 2, we pass self directly into the closure
        _ = array2.mapMe({$0.count})

The mapFlat method is also problematic.

Yours,
Jay Zhao


(David Sweeris) #2

It might be possible to convince me to support renaming map for optionals, but not to mapMe. As it is, you’ll have the same problem with anything having a map function where the element(s) also have a map function. Sets of arrays, arrays of dictionaries, etc.

- Dave Sweeris

···

On Dec 5, 2016, at 7:46 PM, Jay Zhao via swift-evolution <swift-evolution@swift.org> wrote:

Hi there,

Code explains everything:

/// Maybe a bad API naming in Swift? See below:

        /// array1 can be array of any object that have a `count` method
        let array1 = [[String]]()
        let array2 :[String]? = nil
        
        // I believe the confusion between `array.map` and `optionalArray.map` is really bad.
        // Because when you read code like this, you can not tell which is which:
        _ = array1.map({$0.count})
        _ = array2.map({$0.count})
        
        // It can be clearer:
        // 1, we pass `self.element` into the closure
        _ = array1.map({$0.count})
        // 2, we pass self directly into the closure
        _ = array2.mapMe({$0.count})

The mapFlat method is also problematic.


(David Sweeris) #3

If the name is anything other than “map”, you already have to think of the “special” word. At that point, why not just unwrap it manually?
_ = array2?.count
vs
_ = array2?.map {$0.count}

I think this topic was discussed on the list a while ago… I’d have to go back, find the thread and reread it, since the same arguments would just come up again.

- Dave Sweeris

···

On Dec 5, 2016, at 8:54 PM, Jay Zhao <zhaojianyin@icloud.com> wrote:

What about mapUnwrapped ?


(David Sweeris) #4

Oops, there shouldn’t be a “?" on the last line

···

On Dec 5, 2016, at 9:17 PM, David Sweeris via swift-evolution <swift-evolution@swift.org> wrote:

On Dec 5, 2016, at 8:54 PM, Jay Zhao <zhaojianyin@icloud.com <mailto:zhaojianyin@icloud.com>> wrote:

What about mapUnwrapped ?

If the name is anything other than “map”, you already have to think of the “special” word. At that point, why not just unwrap it manually?
_ = array2?.count
vs
_ = array2?.map {$0.count}


(Alexis) #5

This same issue applies to an Array of Arrays, wherein there is no renaming solution. That is, you've built a Collection of Collection, and have mixed up the inner and outer collections. I expect in most cases you'll run into a type error when you try to use the result.

This is an unfortunate bug to have, but I don't think a change to a core type is worth making over it. The name has been discussed in the past, and it was deemed sufficiently desirable as to defy standard naming conventions (it should be called mapped by standard conventions).

···

On Dec 5, 2016, at 11:48 PM, David Sweeris via swift-evolution <swift-evolution@swift.org> wrote:

On Dec 5, 2016, at 7:46 PM, Jay Zhao via swift-evolution <swift-evolution@swift.org> wrote:

Hi there,

Code explains everything:

/// Maybe a bad API naming in Swift? See below:

        /// array1 can be array of any object that have a `count` method
        let array1 = [[String]]()
        let array2 :[String]? = nil
        
        // I believe the confusion between `array.map` and `optionalArray.map` is really bad.
        // Because when you read code like this, you can not tell which is which:
        _ = array1.map({$0.count})
        _ = array2.map({$0.count})
        
        // It can be clearer:
        // 1, we pass `self.element` into the closure
        _ = array1.map({$0.count})
        // 2, we pass self directly into the closure
        _ = array2.mapMe({$0.count})

The mapFlat method is also problematic.

It might be possible to convince me to support renaming map for optionals, but not to mapMe. As it is, you’ll have the same problem with anything having a map function where the element(s) also have a map function. Sets of arrays, arrays of dictionaries, etc.

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


(Jay Zhao) #6

Or maybe just: mapUnwrapped

···

On 6 Dec 2016, at 11:46, Jay Zhao <zhaojianyin@icloud.com> wrote:

Hi there,

Code explains everything:

/// Maybe a bad API naming in Swift? See below:

        /// array1 can be array of any object that have a `count` method
        let array1 = [[String]]()
        let array2 :[String]? = nil
        
        // I believe the confusion between `array.map` and `optionalArray.map` is really bad.
        // Because when you read code like this, you can not tell which is which:
        _ = array1.map({$0.count})
        _ = array2.map({$0.count})
        
        // It can be clearer:
        // 1, we pass `self.element` into the closure
        _ = array1.map({$0.count})
        // 2, we pass self directly into the closure
        _ = array2.mapMe({$0.count})

The mapFlat method is also problematic.

Yours,
Jay Zhao


(Jay Zhao) #7

What about mapUnwrapped ?

- Jay Zhao

···

On 6 Dec 2016, at 12:48, David Sweeris <davesweeris@mac.com> wrote:

On Dec 5, 2016, at 7:46 PM, Jay Zhao via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hi there,

Code explains everything:

/// Maybe a bad API naming in Swift? See below:

        /// array1 can be array of any object that have a `count` method
        let array1 = [[String]]()
        let array2 :[String]? = nil
        
        // I believe the confusion between `array.map` and `optionalArray.map` is really bad.
        // Because when you read code like this, you can not tell which is which:
        _ = array1.map({$0.count})
        _ = array2.map({$0.count})
        
        // It can be clearer:
        // 1, we pass `self.element` into the closure
        _ = array1.map({$0.count})
        // 2, we pass self directly into the closure
        _ = array2.mapMe({$0.count})

The mapFlat method is also problematic.

It might be possible to convince me to support renaming map for optionals, but not to mapMe. As it is, you’ll have the same problem with anything having a map function where the element(s) also have a map function. Sets of arrays, arrays of dictionaries, etc.

- Dave Sweeris


(Jay Zhao) #8

We can make the code condense when the optional is used as a parameter:

  /// Long version
        if let doubleValue = json["taken_at"].double {
            self.createTime = Date(timeIntervalSince1970:doubleValue)
        }
        
        /// Shourt version
        self.createTime = json["taken_at"].double.mapUnwrapped{ Date(timeIntervalSince1970:$0) }

···

On 6 Dec 2016, at 13:18, David Sweeris <davesweeris@mac.com> wrote:

On Dec 5, 2016, at 9:17 PM, David Sweeris via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Dec 5, 2016, at 8:54 PM, Jay Zhao <zhaojianyin@icloud.com <mailto:zhaojianyin@icloud.com>> wrote:

What about mapUnwrapped ?

If the name is anything other than “map”, you already have to think of the “special” word. At that point, why not just unwrap it manually?
_ = array2?.count
vs
_ = array2?.map {$0.count}

Oops, there shouldn’t be a “?" on the last line


(Robert Widmann) #9

If you think of Optional as a zero-or-one element collection there's really no reason this operation should be named any differently. It still lifts a function over values to one over Optionals. It still extracts the contents of the structure and applies the function (propagating failure if necessary). The operation is no different from the one required of a plain Sequence conformance, why should it have a new name if it is not a new operation?

~Robert Widmann

2016/12/05 22:46、Jay Zhao via swift-evolution <swift-evolution@swift.org> のメッセージ:

···

Hi there,

Code explains everything:

/// Maybe a bad API naming in Swift? See below:

        /// array1 can be array of any object that have a `count` method
        let array1 = [[String]]()
        let array2 :[String]? = nil
        
        // I believe the confusion between `array.map` and `optionalArray.map` is really bad.
        // Because when you read code like this, you can not tell which is which:
        _ = array1.map({$0.count})
        _ = array2.map({$0.count})
        
        // It can be clearer:
        // 1, we pass `self.element` into the closure
        _ = array1.map({$0.count})
        // 2, we pass self directly into the closure
        _ = array2.mapMe({$0.count})

The mapFlat method is also problematic.

Yours,
Jay Zhao
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(David Waite) #10

This might be a bit of a side question, but do you use optional arrays in your code? If so, what is the distinction between no array and an empty array?

I believe I haven’t had this confusion in practice because I assume “cars” is a collection, not an optional.

-DW

···

On Dec 5, 2016, at 8:46 PM, Jay Zhao via swift-evolution <swift-evolution@swift.org> wrote:

Hi there,

Code explains everything:

/// Maybe a bad API naming in Swift? See below:

        /// array1 can be array of any object that have a `count` method
        let array1 = [[String]]()
        let array2 :[String]? = nil
        
        // I believe the confusion between `array.map` and `optionalArray.map` is really bad.
        // Because when you read code like this, you can not tell which is which:
        _ = array1.map({$0.count})
        _ = array2.map({$0.count})
        
        // It can be clearer:
        // 1, we pass `self.element` into the closure
        _ = array1.map({$0.count})
        // 2, we pass self directly into the closure
        _ = array2.mapMe({$0.count})

The mapFlat method is also problematic.

Yours,
Jay Zhao
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Guillaume Lessard) #11

No.

I would like to point out that, as used in functional programming, “map” matches the following dictionary definitions:

Map (verb):
• associate (a group of elements or qualities) with an equivalent group, according to a particular formula or model: the transformational rules map deep structures into surface structures.
• (Mathematics) associate each element of (a set) with an element of another set.

So, there are *two* dictionary definitions that match the “map” method name. They’re both somewhat technical, but the protesting should stop.

(I am not a functional programming guy; I simply agree that the language is appropriate.)

Cheers,
Guillaume Lessard


(Xiaodi Wu) #12

Here's a good explanation of map and some other functional idioms in Swift:
http://www.mokacoding.com/blog/functor-applicative-monads-in-pictures/

I hope it adequately explains to you why Optional, like Array, has a method
called map. Unwrapping and rewrapping is inherent to the meaning of the
term "map." Likewise, this article explains flatMap and what it does. These
are terms of art that have specific meanings. The idea of renaming them was
considered during Swift 3 evolution and the decision was made to keep them
as they are.

···

On Mon, Dec 5, 2016 at 23:35 Jay Zhao via swift-evolution < swift-evolution@swift.org> wrote:

We can make the code condense when the optional is used *as a parameter*:

/// Long version
        if let doubleValue = json["taken_at"].double {
            self.createTime = Date(timeIntervalSince1970:doubleValue)
        }

        /// Shourt version
        self.createTime = json["taken_at"].double.mapUnwrapped{ Date(timeIntervalSince1970:$0)
}

On 6 Dec 2016, at 13:18, David Sweeris <davesweeris@mac.com> wrote:

On Dec 5, 2016, at 9:17 PM, David Sweeris via swift-evolution < > swift-evolution@swift.org> wrote:

On Dec 5, 2016, at 8:54 PM, Jay Zhao <zhaojianyin@icloud.com> wrote:

What about mapUnwrapped ?

If the name is anything other than “map”, you already have to think of the
“special” word. At that point, why not just unwrap it manually?
_ = array2?.count
vs
_ = array2?.map {$0.count}

Oops, there shouldn’t be a “?" on the last line

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


(Jay Zhao) #13

It applies in theory to think Optional as a collect of one and for that reason map is a perfect name.

But in practice, we often use the same variable name for array and array? . So when you see :
    cars.map({...$0...})
You can not tell which map and even worse which $0 it is.

According to Swift API Design Guidelines #1, Clarity at the point of use.
And to combine theory and practice, I propose mapUnwrapped to remove the confusion.

Actually this is what’s been adopted in my company:

public extension Optional {
    /// Pass the `Optional` into the closure that returns `Non-Optional`
    public func mapUnwrapped<U>(_ transform: (Wrapped) throws -> U) rethrows -> U? {
        return try map(transform)
    }
}

To summary my idea:
This is the situation where usability > design purity for a language(a tool).

···

On 7 Dec 2016, at 08:05, Robert Widmann <devteam.codafi@gmail.com> wrote:

If you think of Optional as a zero-or-one element collection there's really no reason this operation should be named any differently. It still lifts a function over values to one over Optionals. It still extracts the contents of the structure and applies the function (propagating failure if necessary). The operation is no different from the one required of a plain Sequence conformance, why should it have a new name if it is not a new operation?

~Robert Widmann

2016/12/05 22:46、Jay Zhao via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> のメッセージ:

Hi there,

Code explains everything:

/// Maybe a bad API naming in Swift? See below:

        /// array1 can be array of any object that have a `count` method
        let array1 = [[String]]()
        let array2 :[String]? = nil
        
        // I believe the confusion between `array.map` and `optionalArray.map` is really bad.
        // Because when you read code like this, you can not tell which is which:
        _ = array1.map({$0.count})
        _ = array2.map({$0.count})
        
        // It can be clearer:
        // 1, we pass `self.element` into the closure
        _ = array1.map({$0.count})
        // 2, we pass self directly into the closure
        _ = array2.mapMe({$0.count})

The mapFlat method is also problematic.

Yours,
Jay Zhao
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Robert Widmann) #14

I don't think this is a case where that rule applies, rather it seems like we're sliding back into Objective-C's approach of "stick a sentence into a selector". `map` for Arrays is not called `mapIterateApply`, map for Sets is not called `mapUnorderedIterateApply`, map for Dictionaries is not called `mapUnorderedIterateKeyValuePairsApply`. In every case, you are performing the same essential operation, so why not give them the same name? There is incredible power in being able to pin down a singular common concept and factor it out as Sequence has done. Moreso than not omitting needless words here in my opinion.

A certain, shall we say, controversial overload of `flatMap` is a different kettle of fish, though.

~Robert Widmann

2016/12/06 21:46、Jay Zhao <zhaojianyin@icloud.com> のメッセージ:

···

It applies in theory to think Optional as a collect of one and for that reason map is a perfect name.

But in practice, we often use the same variable name for array and array? . So when you see :
    cars.map({...$0...})
You can not tell which map and even worse which $0 it is.

According to Swift API Design Guidelines #1, Clarity at the point of use.
And to combine theory and practice, I propose mapUnwrapped to remove the confusion.

Actually this is what’s been adopted in my company:

public extension Optional {
    /// Pass the `Optional` into the closure that returns `Non-Optional`
    public func mapUnwrapped<U>(_ transform: (Wrapped) throws -> U) rethrows -> U? {
        return try map(transform)
    }
}

To summary my idea:
This is the situation where usability > design purity for a language(a tool).

On 7 Dec 2016, at 08:05, Robert Widmann <devteam.codafi@gmail.com> wrote:

If you think of Optional as a zero-or-one element collection there's really no reason this operation should be named any differently. It still lifts a function over values to one over Optionals. It still extracts the contents of the structure and applies the function (propagating failure if necessary). The operation is no different from the one required of a plain Sequence conformance, why should it have a new name if it is not a new operation?

~Robert Widmann

2016/12/05 22:46、Jay Zhao via swift-evolution <swift-evolution@swift.org> のメッセージ:

Hi there,

Code explains everything:

/// Maybe a bad API naming in Swift? See below:

        /// array1 can be array of any object that have a `count` method
        let array1 = [[String]]()
        let array2 :[String]? = nil
        
        // I believe the confusion between `array.map` and `optionalArray.map` is really bad.
        // Because when you read code like this, you can not tell which is which:
        _ = array1.map({$0.count})
        _ = array2.map({$0.count})
        
        // It can be clearer:
        // 1, we pass `self.element` into the closure
        _ = array1.map({$0.count})
        // 2, we pass self directly into the closure
        _ = array2.mapMe({$0.count})

The mapFlat method is also problematic.

Yours,
Jay Zhao
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Derrick Ho) #15

Jay, I fail to see the point you are trying to make. Can you clarify why we
need a new map method for an optional array of elements?

···

On Tue, Dec 6, 2016 at 9:46 PM Jay Zhao via swift-evolution < swift-evolution@swift.org> wrote:

It applies in theory to think Optional as a collect of one and for that
reason map is a perfect name.

But in practice, we often use the same variable name for *array* and
*array?* . So when you see :
cars.*map*({...$0...})
You can not tell which map and even worse which $0 it is.

According to Swift API Design Guidelines *#1*, *Clarity at the point of use*
.
And to combine theory and practice, I propose *mapUnwrapped* to remove the
confusion.

Actually this is what’s been adopted in my company:

public extension Optional {

    /// Pass the `Optional` into the closure that returns `Non-Optional`

    public func mapUnwrapped<U>(_ transform: (Wrapped) throws -> U) rethrows
-> U? {

        return try map(transform)

    }

}

To summary my idea:
This is the situation where usability > design purity for a language(a
tool).

On 7 Dec 2016, at 08:05, Robert Widmann <devteam.codafi@gmail.com> wrote:

If you think of Optional as a zero-or-one element collection there's really
no reason this operation should be named any differently. It still lifts a
function over values to one over Optionals. It still extracts the contents
of the structure and applies the function (propagating failure if
necessary). The operation is no different from the one required of a plain
Sequence conformance, why should it have a new name if it is not a new
operation?

~Robert Widmann

2016/12/05 22:46、Jay Zhao via swift-evolution <swift-evolution@swift.org>
のメッセージ:

Hi there,

Code explains everything:

/// Maybe a bad API naming in Swift? See below:

        /// array1 can be array of any object that have a `count` method
        let array1 = [[String]]()
        let array2 :[String]? = nil

        // I believe the confusion between `array.map` and
`optionalArray.map` is really bad.
        // Because when you read code like this, you can not tell which is
which:
        _ = array1.map({$0.count})
        _ = array2.map({$0.count})

        // It can be clearer:
        // 1, we pass `self.element` into the closure
        _ = array1.map({$0.count})
        // 2, we pass self directly into the closure
        _ = array2.mapMe({$0.count})

The mapFlat method is also problematic.

Yours,
Jay Zhao

_______________________________________________
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


(Daniel Leping) #16

Totally against renaming. Keeping the syntax consistent is a good practice.
If you have to use Monade inside a Monade - handle it your way. Otherwise
think of flattening to single Monade layer.

I strongly feel we should keep standard naming for functional approach.

···

On Wed, 7 Dec 2016 at 7:43 Robert Widmann via swift-evolution < swift-evolution@swift.org> wrote:

I don't think this is a case where that rule applies, rather it seems like
we're sliding back into Objective-C's approach of "stick a sentence into a
selector". `map` for Arrays is not called `mapIterateApply`, map for Sets
is not called `mapUnorderedIterateApply`, map for Dictionaries is not
called `mapUnorderedIterateKeyValuePairsApply`. In every case, you are
performing the same essential operation, so why not give them the same
name? There is incredible power in being able to pin down a singular
common concept and factor it out as Sequence has done. Moreso than not
omitting needless words here in my opinion.

A certain, shall we say, controversial overload of `flatMap` is a
different kettle of fish, though.

~Robert Widmann

2016/12/06 21:46、Jay Zhao <zhaojianyin@icloud.com> のメッセージ:

It applies in theory to think Optional as a collect of one and for that
reason map is a perfect name.

But in practice, we often use the same variable name for *array* and
*array?* . So when you see :
cars.*map*({...$0...})
You can not tell which map and even worse which $0 it is.

According to Swift API Design Guidelines *#1*, *Clarity at the point of
use*.
And to combine theory and practice, I propose *mapUnwrapped* to remove
the confusion.

Actually this is what’s been adopted in my company:

public extension Optional {

    /// Pass the `Optional` into the closure that returns `Non-Optional`

    public func mapUnwrapped<U>(_ transform: (Wrapped) throws -> U)
rethrows -> U? {

        return try map(transform)

    }

}

To summary my idea:
This is the situation where usability > design purity for a language(a
tool).

On 7 Dec 2016, at 08:05, Robert Widmann <devteam.codafi@gmail.com> wrote:

If you think of Optional as a zero-or-one element collection there's
really no reason this operation should be named any differently. It still
lifts a function over values to one over Optionals. It still extracts the
contents of the structure and applies the function (propagating failure if
necessary). The operation is no different from the one required of a plain
Sequence conformance, why should it have a new name if it is not a new
operation?

~Robert Widmann

2016/12/05 22:46、Jay Zhao via swift-evolution <swift-evolution@swift.org>
のメッセージ:

Hi there,

Code explains everything:

/// Maybe a bad API naming in Swift? See below:

        /// array1 can be array of any object that have a `count` method
        let array1 = [[String]]()
        let array2 :[String]? = nil

        // I believe the confusion between `array.map` and
`optionalArray.map` is really bad.
        // Because when you read code like this, you can not tell which
is which:
        _ = array1.map({$0.count})
        _ = array2.map({$0.count})

        // It can be clearer:
        // 1, we pass `self.element` into the closure
        _ = array1.map({$0.count})
        // 2, we pass self directly into the closure
        _ = array2.mapMe({$0.count})

The mapFlat method is also problematic.

Yours,
Jay Zhao

_______________________________________________
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


(Jay Zhao) #17

Hi Derrick,

Not just for optional array, but for all optional types. Optional.map has a deep confusion for we’re not sure what is $0 inside. And it is so commonly used compared to the collection of collection scenario mentioned by Alexis Beingessner.

- Jay Zhao

···

On 7 Dec 2016, at 10:58, Derrick Ho <wh1pch81n@gmail.com> wrote:

Jay, I fail to see the point you are trying to make. Can you clarify why we need a new map method for an optional array of elements?

On Tue, Dec 6, 2016 at 9:46 PM Jay Zhao via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
It applies in theory to think Optional as a collect of one and for that reason map is a perfect name.

But in practice, we often use the same variable name for array and array? . So when you see :
    cars.map({...$0...})
You can not tell which map and even worse which $0 it is.

According to Swift API Design Guidelines #1, Clarity at the point of use.
And to combine theory and practice, I propose mapUnwrapped to remove the confusion.

Actually this is what’s been adopted in my company:

public extension Optional {
    /// Pass the `Optional` into the closure that returns `Non-Optional`
    public func mapUnwrapped<U>(_ transform: (Wrapped) throws -> U) rethrows -> U? {
        return try map(transform)
    }
}

To summary my idea:
This is the situation where usability > design purity for a language(a tool).

On 7 Dec 2016, at 08:05, Robert Widmann <devteam.codafi@gmail.com <mailto:devteam.codafi@gmail.com>> wrote:

If you think of Optional as a zero-or-one element collection there's really no reason this operation should be named any differently. It still lifts a function over values to one over Optionals. It still extracts the contents of the structure and applies the function (propagating failure if necessary). The operation is no different from the one required of a plain Sequence conformance, why should it have a new name if it is not a new operation?

~Robert Widmann

2016/12/05 22:46、Jay Zhao via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> のメッセージ:

Hi there,

Code explains everything:

/// Maybe a bad API naming in Swift? See below:

        /// array1 can be array of any object that have a `count` method
        let array1 = [[String]]()
        let array2 :[String]? = nil
        
        // I believe the confusion between `array.map` and `optionalArray.map` is really bad.
        // Because when you read code like this, you can not tell which is which:
        _ = array1.map({$0.count})
        _ = array2.map({$0.count})
        
        // It can be clearer:
        // 1, we pass `self.element` into the closure
        _ = array1.map({$0.count})
        // 2, we pass self directly into the closure
        _ = array2.mapMe({$0.count})

The mapFlat method is also problematic.

Yours,
Jay Zhao
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

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


(Xiaodi Wu) #18

I don't understand why there is confusion. $0 refers to the same thing
whether you're invoking `map` on Optional or a type that conforms to
Collection. That is why the method is named `map`.

···

On Tue, Dec 6, 2016 at 9:16 PM, Jay Zhao via swift-evolution < swift-evolution@swift.org> wrote:

Hi Derrick,

Not just for optional array, but for all optional types. Optional.map has
a deep confusion for we’re not sure what is $0 inside. And it is so
commonly used compared to the collection of collection scenario mentioned
by Alexis Beingessner.

- Jay Zhao

On 7 Dec 2016, at 10:58, Derrick Ho <wh1pch81n@gmail.com> wrote:

Jay, I fail to see the point you are trying to make. Can you clarify why
we need a new map method for an optional array of elements?

On Tue, Dec 6, 2016 at 9:46 PM Jay Zhao via swift-evolution < > swift-evolution@swift.org> wrote:

It applies in theory to think Optional as a collect of one and for that
reason map is a perfect name.

But in practice, we often use the same variable name for *array* and
*array?* . So when you see :
cars.*map*({...$0...})
You can not tell which map and even worse which $0 it is.

According to Swift API Design Guidelines *#1*, *Clarity at the point of
use*.
And to combine theory and practice, I propose *mapUnwrapped* to remove
the confusion.

Actually this is what’s been adopted in my company:

public extension Optional {

    /// Pass the `Optional` into the closure that returns `Non-Optional`

    public func mapUnwrapped<U>(_ transform: (Wrapped) throws -> U)
rethrows -> U? {

        return try map(transform)

    }

}

To summary my idea:
This is the situation where usability > design purity for a language(a
tool).

On 7 Dec 2016, at 08:05, Robert Widmann <devteam.codafi@gmail.com> wrote:

If you think of Optional as a zero-or-one element collection there's
really no reason this operation should be named any differently. It still
lifts a function over values to one over Optionals. It still extracts the
contents of the structure and applies the function (propagating failure if
necessary). The operation is no different from the one required of a plain
Sequence conformance, why should it have a new name if it is not a new
operation?

~Robert Widmann

2016/12/05 22:46、Jay Zhao via swift-evolution <swift-evolution@swift.org>
のメッセージ:

Hi there,

Code explains everything:

/// Maybe a bad API naming in Swift? See below:

        /// array1 can be array of any object that have a `count` method
        let array1 = [[String]]()
        let array2 :[String]? = nil

        // I believe the confusion between `array.map` and
`optionalArray.map` is really bad.
        // Because when you read code like this, you can not tell which
is which:
        _ = array1.map({$0.count})
        _ = array2.map({$0.count})

        // It can be clearer:
        // 1, we pass `self.element` into the closure
        _ = array1.map({$0.count})
        // 2, we pass self directly into the closure
        _ = array2.mapMe({$0.count})

The mapFlat method is also problematic.

Yours,
Jay Zhao

_______________________________________________
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

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


(Derrick Ho) #19

If you are confused by what $0 represents then your shouldn't use the short
hand version of writing a block. The long version includes the type which
will remove all mysteries

// What is $0
array.map {
$0.method()
}

// No mystery of $0. It is clearly a String?
array.map { (name: String?) -> String?
return name?.uppercased()
}

···

On Tue, Dec 6, 2016 at 10:16 PM Jay Zhao <zhaojianyin@icloud.com> wrote:

Hi Derrick,

Not just for optional array, but for all optional types. Optional.map has
a deep confusion for we’re not sure what is $0 inside. And it is so
commonly used compared to the collection of collection scenario mentioned
by Alexis Beingessner.

- Jay Zhao

On 7 Dec 2016, at 10:58, Derrick Ho <wh1pch81n@gmail.com> wrote:

Jay, I fail to see the point you are trying to make. Can you clarify why
we need a new map method for an optional array of elements?

On Tue, Dec 6, 2016 at 9:46 PM Jay Zhao via swift-evolution < > swift-evolution@swift.org> wrote:

It applies in theory to think Optional as a collect of one and for that
reason map is a perfect name.

But in practice, we often use the same variable name for *array* and
*array?* . So when you see :
cars.*map*({...$0...})
You can not tell which map and even worse which $0 it is.

According to Swift API Design Guidelines *#1*, *Clarity at the point of
use*.
And to combine theory and practice, I propose *mapUnwrapped* to remove
the confusion.

Actually this is what’s been adopted in my company:

public extension Optional {

    /// Pass the `Optional` into the closure that returns `Non-Optional`

    public func mapUnwrapped<U>(_ transform: (Wrapped) throws -> U)
rethrows -> U? {

        return try map(transform)

    }

}

To summary my idea:
This is the situation where usability > design purity for a language(a
tool).

On 7 Dec 2016, at 08:05, Robert Widmann <devteam.codafi@gmail.com> wrote:

If you think of Optional as a zero-or-one element collection there's
really no reason this operation should be named any differently. It still
lifts a function over values to one over Optionals. It still extracts the
contents of the structure and applies the function (propagating failure if
necessary). The operation is no different from the one required of a plain
Sequence conformance, why should it have a new name if it is not a new
operation?

~Robert Widmann

2016/12/05 22:46、Jay Zhao via swift-evolution <swift-evolution@swift.org>
のメッセージ:

Hi there,

Code explains everything:

/// Maybe a bad API naming in Swift? See below:

        /// array1 can be array of any object that have a `count` method
        let array1 = [[String]]()
        let array2 :[String]? = nil

        // I believe the confusion between `array.map` and
`optionalArray.map` is really bad.
        // Because when you read code like this, you can not tell which
is which:
        _ = array1.map({$0.count})
        _ = array2.map({$0.count})

        // It can be clearer:
        // 1, we pass `self.element` into the closure
        _ = array1.map({$0.count})
        // 2, we pass self directly into the closure
        _ = array2.mapMe({$0.count})

The mapFlat method is also problematic.

Yours,
Jay Zhao

_______________________________________________
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