[Pitch] Improve `init(repeating:count)`

What people are doing is taking a real set of values (1, 2, 3, 4, 5, for example), then discarding them via `_ in`, which is different from `Void -> T` or `f(x) = 0 * x`. The domain could just as easily be (Foo(), "b", :poop:, UIColor.red, { x: Int in x^x }). There are too many semantic shifts away from "I would like to collect the execution of this closure n times" for it to sit comfortably.

What arguments might help to alleviate this discomfort? Clearly, functions exist that can map this delightfully heterogeneous domain to some sort of range that the user wants. Would you feel better if we wrote instead the following?

repeatElement((), count: 5).map { UIView() }

My favorite solution is the array initializer. Something along the lines of `Array<T>(count n: Int, generator: () -> T)`. I'm not sure it _quite_ reaches standard library but I think it is a solid way to say "produce a collection with a generator run n times". It's a common task. I was asking around about this, and found that a lot of us who work with both macOS and iOS and want to stress test interfaces do this very often. Other use cases include "give me n random numbers", "give me n records from this database", etc. along similar lines.

The difference between this and the current `Array(repeating:count:)` initializer is switching the arguments and using a trailing closure (or an autoclosure) rather than a set value. That API was designed without the possibility that you might want to repeat a generator, so there's a bit of linguistic turbulence.

-- E

···

On Aug 17, 2017, at 6:56 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:
On Thu, Aug 17, 2017 at 7:51 PM, Erica Sadun <erica@ericasadun.com <mailto:erica@ericasadun.com>> wrote:

On Aug 17, 2017, at 3:53 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

This is, I would argue, much too limiting in the way of semantics and not at all required by “map”. It’s unclear to me how _any_ result with reference semantics or any function with side effects could be used in a way that comports with that definition.

On the other hand, just as y = 0x is a function, { _ in Foo() } is a closure that very much does project from a domain to a range. I’m not sure I understand what wins are to be had by having “collect {}” as a synonym for “map { _ in }”.

On Thu, Aug 17, 2017 at 16:01 Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Aug 17, 2017, at 12:04 PM, Max Moiseev <moiseev@apple.com <mailto:moiseev@apple.com>> wrote:

On Aug 17, 2017, at 10:05 AM, Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Also, for those of you here who haven't heard my previous rant on the subject, I dislike using map for generating values that don't depend on transforming a domain to a range. (It has been argued that `_ in` is mapping from `Void`, but I still dislike it immensely)

Can you please elaborate why (or maybe point me at the rant)?

Summary:

. Since this application is a generator and not a transformative function, `map` is a misfit to usage semantics. It breaks the contract that map means to project from a domain to a range via a function. More languages conventionally use `collect` than `map` to collect n applications of a generator closure

-- E

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

`repeatElement((), count: 5)` is better than `1 ... 5`, but `Count(3).map({ UIView() })` is far more elegant. I'd still probably go with an array initializer or `5.elements(of: UIView())`. I don't think I'm overstating how common this pattern is, and `Array(repeating:count:)` feels _close_ but not close enough.

-- E

···

On Aug 17, 2017, at 7:13 PM, Robert Bennett <rltbennett@icloud.com> wrote:

Xiaodi, you pretty much took the words out of my mouth. I was going to suggest a Count collection whose Element was Void and with the sole initializer init(_ count: Int). The type would just contain its count and pretty much fake its collection interface, in the sense that no elements are actually stored. Then you could do Count(3).map { UIView() }

On Aug 17, 2017, at 9:06 PM, Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Aug 17, 2017, at 6:56 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Thu, Aug 17, 2017 at 7:51 PM, Erica Sadun <erica@ericasadun.com <mailto:erica@ericasadun.com>> wrote:
What people are doing is taking a real set of values (1, 2, 3, 4, 5, for example), then discarding them via `_ in`, which is different from `Void -> T` or `f(x) = 0 * x`. The domain could just as easily be (Foo(), "b", :poop:, UIColor.red, { x: Int in x^x }). There are too many semantic shifts away from "I would like to collect the execution of this closure n times" for it to sit comfortably.

What arguments might help to alleviate this discomfort? Clearly, functions exist that can map this delightfully heterogeneous domain to some sort of range that the user wants. Would you feel better if we wrote instead the following?

repeatElement((), count: 5).map { UIView() }

My favorite solution is the array initializer. Something along the lines of `Array<T>(count n: Int, generator: () -> T)`. I'm not sure it _quite_ reaches standard library but I think it is a solid way to say "produce a collection with a generator run n times". It's a common task. I was asking around about this, and found that a lot of us who work with both macOS and iOS and want to stress test interfaces do this very often. Other use cases include "give me n random numbers", "give me n records from this database", etc. along similar lines.

The difference between this and the current `Array(repeating:count:)` initializer is switching the arguments and using a trailing closure (or an autoclosure) rather than a set value. That API was designed without the possibility that you might want to repeat a generator, so there's a bit of linguistic turbulence.

-- E

On Aug 17, 2017, at 3:53 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

This is, I would argue, much too limiting in the way of semantics and not at all required by “map”. It’s unclear to me how _any_ result with reference semantics or any function with side effects could be used in a way that comports with that definition.

On the other hand, just as y = 0x is a function, { _ in Foo() } is a closure that very much does project from a domain to a range. I’m not sure I understand what wins are to be had by having “collect {}” as a synonym for “map { _ in }”.

On Thu, Aug 17, 2017 at 16:01 Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Aug 17, 2017, at 12:04 PM, Max Moiseev <moiseev@apple.com <mailto:moiseev@apple.com>> wrote:

On Aug 17, 2017, at 10:05 AM, Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Also, for those of you here who haven't heard my previous rant on the subject, I dislike using map for generating values that don't depend on transforming a domain to a range. (It has been argued that `_ in` is mapping from `Void`, but I still dislike it immensely)

Can you please elaborate why (or maybe point me at the rant)?

Summary:

. Since this application is a generator and not a transformative function, `map` is a misfit to usage semantics. It breaks the contract that map means to project from a domain to a range via a function. More languages conventionally use `collect` than `map` to collect n applications of a generator closure

-- E

_______________________________________________
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

What people are doing is taking a real set of values (1, 2, 3, 4, 5, for
example), then discarding them via `_ in`, which is different from `Void ->
T` or `f(x) = 0 * x`. The domain could just as easily be (Foo(), "b", :poop:,
UIColor.red, { x: Int in x^x }). There are too many semantic shifts away
from "I would like to collect the execution of this closure n times" for it
to sit comfortably.

What arguments might help to alleviate this discomfort? Clearly, functions
exist that can map this delightfully heterogeneous domain to some sort of
range that the user wants. Would you feel better if we wrote instead the
following?

repeatElement((), count: 5).map { UIView() }

-- E

···

On Thu, Aug 17, 2017 at 7:51 PM, Erica Sadun <erica@ericasadun.com> wrote:

On Aug 17, 2017, at 3:53 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

This is, I would argue, much too limiting in the way of semantics and not
at all required by “map”. It’s unclear to me how _any_ result with
reference semantics or any function with side effects could be used in a
way that comports with that definition.

On the other hand, just as y = 0x is a function, { _ in Foo() } is a
closure that very much does project from a domain to a range. I’m not sure
I understand what wins are to be had by having “collect {}” as a synonym
for “map { _ in }”.

On Thu, Aug 17, 2017 at 16:01 Erica Sadun via swift-evolution < > swift-evolution@swift.org> wrote:

On Aug 17, 2017, at 12:04 PM, Max Moiseev <moiseev@apple.com> wrote:

On Aug 17, 2017, at 10:05 AM, Erica Sadun via swift-evolution < >> swift-evolution@swift.org> wrote:

Also, for those of you here who haven't heard my previous rant on the
subject, I dislike using map for generating values that don't depend on
transforming a domain to a range. (It has been argued that `_ in` is
mapping from `Void`, but I still dislike it immensely)

Can you please elaborate why (or maybe point me at the rant)?

Summary:

. Since this application is a generator and not a transformative
function, `map` is a misfit to usage semantics. It breaks the contract that
map means to project from a domain to a range via a function. More
languages conventionally use `collect` than `map` to collect n applications
of a generator closure

-- E

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

...but, again, why would such an API be superior to `map`, which is already
widely used and clear? My point above was that, if your problem with using
`(0..<5).map { _ in UIView() }` is the discarding of a set of values (which
I argue is semantically unproblematic in the first place, since it's still
mapping from a domain to a range), then `repeatElement((), count: 5).map {
UIView() }` produces the same result without violating your stipulated
semantics.

···

On Thu, Aug 17, 2017 at 8:06 PM, Erica Sadun <erica@ericasadun.com> wrote:

On Aug 17, 2017, at 6:56 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Thu, Aug 17, 2017 at 7:51 PM, Erica Sadun <erica@ericasadun.com> wrote:

What people are doing is taking a real set of values (1, 2, 3, 4, 5, for
example), then discarding them via `_ in`, which is different from `Void ->
T` or `f(x) = 0 * x`. The domain could just as easily be (Foo(), "b", :poop:,
UIColor.red, { x: Int in x^x }). There are too many semantic shifts away
from "I would like to collect the execution of this closure n times" for it
to sit comfortably.

What arguments might help to alleviate this discomfort? Clearly, functions
exist that can map this delightfully heterogeneous domain to some sort of
range that the user wants. Would you feel better if we wrote instead the
following?

repeatElement((), count: 5).map { UIView() }

My favorite solution is the array initializer. Something along the lines
of `Array<T>(count n: Int, generator: () -> T)`. I'm not sure it _quite_
reaches standard library but I think it is a solid way to say "produce a
collection with a generator run n times". It's a common task. I was asking
around about this, and found that a lot of us who work with both macOS and
iOS and want to stress test interfaces do this very often. Other use cases
include "give me n random numbers", "give me n records from this database",
etc. along similar lines.

The difference between this and the current `Array(repeating:count:)`
initializer is switching the arguments and using a trailing closure (or an
autoclosure) rather than a set value. That API was designed without the
possibility that you might want to repeat a generator, so there's a bit of
linguistic turbulence.

`repeatElement((), count: 5)` is better than `1 ... 5`, but `Count(3).map({ UIView() })` is far more elegant. I'd still probably go with an array initializer or `5.elements(of: UIView())`. I don't think I'm overstating how common this pattern is, and `Array(repeating:count:)` feels _close_ but not close enough.

The first two have the benefit of being currently existing APIs;

I'm pretty sure Count isn't an existing API. And as I said before, while I don't think this rises to stdlib inclusion, it's been a common problem domain for people both inside and outside Apple so it deserves a full discussion.

That said, `Count` is neat. It encapsulates an idea in a way that I haven't seen in Swift.

-- E

···

On Aug 17, 2017, at 7:38 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:
On Thu, Aug 17, 2017 at 8:25 PM, Erica Sadun <erica@ericasadun.com <mailto:erica@ericasadun.com>> wrote:

they capture the semantics perfectly, as I've argued, and I simply don't see how they are impaired in elegance in any way--certainly not enough to justify a standard library addition to create a third way of spelling the same thing. Ultimately, any user is free to define something like:

func * <T>(lhs: Int, rhs: @autoclosure () throws -> T) rethrows -> [T] {
  return try repeatElement((), count: lhs).map { try rhs() }
}

5 * UIView()

The first two have the benefit of being currently existing APIs; they
capture the semantics perfectly, as I've argued, and I simply don't see how
they are impaired in elegance in any way--certainly not enough to justify a
standard library addition to create a third way of spelling the same thing.
Ultimately, any user is free to define something like:

func * <T>(lhs: Int, rhs: @autoclosure () throws -> T) rethrows -> [T] {
  return try repeatElement((), count: lhs).map { try rhs() }
}

5 * UIView()
···

On Thu, Aug 17, 2017 at 8:25 PM, Erica Sadun <erica@ericasadun.com> wrote:

`repeatElement((), count: 5)` is better than `1 ... 5`, but
`Count(3).map({ UIView() })` is far more elegant. I'd still probably go
with an array initializer or `5.elements(of: UIView())`. I don't think I'm
overstating how common this pattern is, and `Array(repeating:count:)` feels
_close_ but not close enough.

Xiaodi, you pretty much took the words out of my mouth. I was going to suggest a Count collection whose Element was Void and with the sole initializer init(_ count: Int). The type would just contain its count and pretty much fake its collection interface, in the sense that no elements are actually stored. Then you could do Count(3).map { UIView() }

···

On Aug 17, 2017, at 9:06 PM, Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

On Aug 17, 2017, at 6:56 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Thu, Aug 17, 2017 at 7:51 PM, Erica Sadun <erica@ericasadun.com> wrote:
What people are doing is taking a real set of values (1, 2, 3, 4, 5, for example), then discarding them via `_ in`, which is different from `Void -> T` or `f(x) = 0 * x`. The domain could just as easily be (Foo(), "b", :poop:, UIColor.red, { x: Int in x^x }). There are too many semantic shifts away from "I would like to collect the execution of this closure n times" for it to sit comfortably.

What arguments might help to alleviate this discomfort? Clearly, functions exist that can map this delightfully heterogeneous domain to some sort of range that the user wants. Would you feel better if we wrote instead the following?

repeatElement((), count: 5).map { UIView() }

My favorite solution is the array initializer. Something along the lines of `Array<T>(count n: Int, generator: () -> T)`. I'm not sure it _quite_ reaches standard library but I think it is a solid way to say "produce a collection with a generator run n times". It's a common task. I was asking around about this, and found that a lot of us who work with both macOS and iOS and want to stress test interfaces do this very often. Other use cases include "give me n random numbers", "give me n records from this database", etc. along similar lines.

The difference between this and the current `Array(repeating:count:)` initializer is switching the arguments and using a trailing closure (or an autoclosure) rather than a set value. That API was designed without the possibility that you might want to repeat a generator, so there's a bit of linguistic turbulence.

-- E

On Aug 17, 2017, at 3:53 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

This is, I would argue, much too limiting in the way of semantics and not at all required by “map”. It’s unclear to me how _any_ result with reference semantics or any function with side effects could be used in a way that comports with that definition.

On the other hand, just as y = 0x is a function, { _ in Foo() } is a closure that very much does project from a domain to a range. I’m not sure I understand what wins are to be had by having “collect {}” as a synonym for “map { _ in }”.

On Thu, Aug 17, 2017 at 16:01 Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

On Aug 17, 2017, at 12:04 PM, Max Moiseev <moiseev@apple.com> wrote:

On Aug 17, 2017, at 10:05 AM, Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

Also, for those of you here who haven't heard my previous rant on the subject, I dislike using map for generating values that don't depend on transforming a domain to a range. (It has been argued that `_ in` is mapping from `Void`, but I still dislike it immensely)

Can you please elaborate why (or maybe point me at the rant)?

Summary:

. Since this application is a generator and not a transformative function, `map` is a misfit to usage semantics. It breaks the contract that map means to project from a domain to a range via a function. More languages conventionally use `collect` than `map` to collect n applications of a generator closure

-- E

_______________________________________________
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

To me at least, this is a very i-Centric complaint, since I can barely
remember the last time I needed something like this for anything that
didn’t involve UIKit. What you’re asking for is API sugar for generating
reference types with less typing. The problem is it’s hugely disruptive to
user’s mental model of how Swift operates, to say the least. When I read a
function signature like Array.init(count:object:) or whatever, I expect
that if a referency type is passed to the object parameter, the *pointer*
gets copied `count` times, and the reference count incremented accordingly.
I don’t expect the object itself to get deepcopied. That’s why the use of
@autoclosure is strongly recommended against
<https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=5&cad=rja&uact=8&ved=0ahUKEwjar8qe6d_VAhUC4YMKHcIIC5MQygQIRDAE&url=https%3A%2F%2Fdeveloper.apple.com%2Flibrary%2Fcontent%2Fdocumentation%2FSwift%2FConceptual%2FSwift_Programming_Language%2FClosures.html%23%2F%2Fapple_ref%2Fdoc%2Fuid%2FTP40014097-CH11-ID543&usg=AFQjCNHnH4tzGagCKcjU5jRzK-GSDCB6qA>,
and why it only appears in things relating to debugging like
assert(condition:message:file:line:), which are mentally separated from the
rest of Swift.

Doing this with a function is less disruptive, but if you ask me, it
expands API surface area without offering any real benefit. As people have
pointed out, we already have a perfectly good idiom in (0 ..< n).map{ _ in
UIView() }. I never understood why certain people complain about
“discarding the domain”, but have no problem writing things like this:

for _ in 0 ..< n
{
    //
}

If you’re truly allergic to map{ _ in UIView() }, might I suggest the
following:

var array:[UIView] = []
    array.reserveCapacity(n)
for _ in 0 ..< n
{
    { array.append(UIView()) }()
}

That’s really all an array initializer that takes a block is really doing.
Or just use map.

···

On Thu, Aug 17, 2017 at 9:06 PM, Erica Sadun via swift-evolution < swift-evolution@swift.org> wrote:

On Aug 17, 2017, at 6:56 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Thu, Aug 17, 2017 at 7:51 PM, Erica Sadun <erica@ericasadun.com> wrote:

What people are doing is taking a real set of values (1, 2, 3, 4, 5, for
example), then discarding them via `_ in`, which is different from `Void ->
T` or `f(x) = 0 * x`. The domain could just as easily be (Foo(), "b", :poop:,
UIColor.red, { x: Int in x^x }). There are too many semantic shifts away
from "I would like to collect the execution of this closure n times" for it
to sit comfortably.

What arguments might help to alleviate this discomfort? Clearly, functions
exist that can map this delightfully heterogeneous domain to some sort of
range that the user wants. Would you feel better if we wrote instead the
following?

repeatElement((), count: 5).map { UIView() }

My favorite solution is the array initializer. Something along the lines
of `Array<T>(count n: Int, generator: () -> T)`. I'm not sure it _quite_
reaches standard library but I think it is a solid way to say "produce a
collection with a generator run n times". It's a common task. I was asking
around about this, and found that a lot of us who work with both macOS and
iOS and want to stress test interfaces do this very often. Other use cases
include "give me n random numbers", "give me n records from this database",
etc. along similar lines.

The difference between this and the current `Array(repeating:count:)`
initializer is switching the arguments and using a trailing closure (or an
autoclosure) rather than a set value. That API was designed without the
possibility that you might want to repeat a generator, so there's a bit of
linguistic turbulence.

-- E

No, that's what the original thread poster wanted.

I want to avoid breaking math. For any x passed to a function, I expect f(x) to produce the same result. To map is to create a relation so that for every x in a domain, there is a single y that it produces. You can hand-wave and say the map is "producing" the closure, but it's not. It's executing it and recovering a value.

How we get past the `(n ... m).map({ _ in ... })` pattern may be through language guidance or through language evolution. Either way, it doesn't make this pattern not problematic and worthy of discussion.

Finally, I don't think Swift Evolution _can_ be considered entirely outside the auspices of the Apple halo. Look at SE-0005, SE-0006, and SE-0023 for example. i-Centricity is inescapable given the core team and the hosting domain for this project.

-- E

···

On Aug 17, 2017, at 9:29 PM, Taylor Swift <kelvin13ma@gmail.com> wrote:
On Thu, Aug 17, 2017 at 9:06 PM, Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Aug 17, 2017, at 6:56 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Thu, Aug 17, 2017 at 7:51 PM, Erica Sadun <erica@ericasadun.com <mailto:erica@ericasadun.com>> wrote:
What people are doing is taking a real set of values (1, 2, 3, 4, 5, for example), then discarding them via `_ in`, which is different from `Void -> T` or `f(x) = 0 * x`. The domain could just as easily be (Foo(), "b", :poop:, UIColor.red, { x: Int in x^x }). There are too many semantic shifts away from "I would like to collect the execution of this closure n times" for it to sit comfortably.

What arguments might help to alleviate this discomfort? Clearly, functions exist that can map this delightfully heterogeneous domain to some sort of range that the user wants. Would you feel better if we wrote instead the following?

repeatElement((), count: 5).map { UIView() }

My favorite solution is the array initializer. Something along the lines of `Array<T>(count n: Int, generator: () -> T)`. I'm not sure it _quite_ reaches standard library but I think it is a solid way to say "produce a collection with a generator run n times". It's a common task. I was asking around about this, and found that a lot of us who work with both macOS and iOS and want to stress test interfaces do this very often. Other use cases include "give me n random numbers", "give me n records from this database", etc. along similar lines.

The difference between this and the current `Array(repeating:count:)` initializer is switching the arguments and using a trailing closure (or an autoclosure) rather than a set value. That API was designed without the possibility that you might want to repeat a generator, so there's a bit of linguistic turbulence.

-- E

To me at least, this is a very i-Centric complaint, since I can barely remember the last time I needed something like this for anything that didn’t involve UIKit. What you’re asking for is API sugar for generating reference types with less typing.

1 Like

it’s not that deep, the `for _ in 0 …< n` loop is exactly the same thing
except more verbose. In fact, that’s how your proposed `
Array.init(count:generator:)` would be implemented. But I don’t see anyone
saying we should get rid of the underscore pattern or `@discardableResult`,
so…

···

On Fri, Aug 18, 2017 at 1:23 PM, Erica Sadun <erica@ericasadun.com> wrote:

I want to avoid breaking math.

I know it's late to chime in here, but IMO (mutable) reference types and the exposure of === “break math,” and I think that's the real effect you're seeing here.

···

on Fri Aug 18 2017, Erica Sadun <swift-evolution@swift.org> wrote:

On Aug 17, 2017, at 9:29 PM, Taylor Swift >> <kelvin13ma@gmail.com> > wrote: On Thu, Aug 17, 2017 at 9:06 PM, Erica Sadun via >> swift-evolution >> <swift-evolution@swift.org >> <mailto:swift-evolution@swift.org>> >> wrote:

On Aug 17, 2017, at 6:56 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote: On Thu, Aug 17, 2017 at 7:51 PM, Erica Sadun <erica@ericasadun.com <mailto:erica@ericasadun.com>> wrote: What people are doing is taking a real set of values (1, 2, 3, 4, 5, for example), then discarding them via `_ in`, which is different from `Void -> T` or `f(x) = 0 * x`. The domain could just as easily be (Foo(), "b", :poop:, UIColor.red, { x: Int in x^x }). There are too many semantic shifts away from "I would like to collect the execution of this closure n times" for it to sit comfortably. What arguments might help to alleviate this discomfort? Clearly, functions exist that can map this delightfully heterogeneous domain to some sort of range that the user wants. Would you feel better if we wrote instead the following? ``` repeatElement((), count: 5).map { UIView() } ```

My favorite solution is the array initializer. Something along the lines of `Array<T>(count n: Int, generator: () -> T)`. I'm not sure it _quite_ reaches standard library but I think it is a solid way to say "produce a collection with a generator run n times". It's a common task. I was asking around about this, and found that a lot of us who work with both macOS and iOS and want to stress test interfaces do this very often. Other use cases include "give me n random numbers", "give me n records from this database", etc. along similar lines. The difference between this and the current `Array(repeating:count:)` initializer is switching the arguments and using a trailing closure (or an autoclosure) rather than a set value. That API was designed without the possibility that you might want to repeat a generator, so there's a bit of linguistic turbulence. -- E To me at least, this is a very i-Centric complaint, since I can barely remember the last time I needed something like this for anything that didn’t involve UIKit. What you’re asking for is API sugar for generating reference types with less typing.

No, that's what the original thread poster wanted.

I want to avoid breaking math.

--
-Dave

I don’t quite understand your objections to using a closure { _ in ... } with map. By your own admission, the semantics of map are

project from a domain to a range via a function

Well that’s exactly what happening. It’s a function, just like any other function, whose domain is the universal set (Any, in Swift) to a codomain of one value.

There’s no contract of map that says “the funciton can’t be surjective”. If that were the case, we also shouldn’t use Array(-2...2).map{ $0 * $0 }.

To your definition of the semantics of map, I would add that it’s probably best to avoid side effects in the function. Lucky for us, { _ in UIView() } is pure and also idempotent.

There’s nothing about the formal definition of a function or map that disqualifies surjective functions with a codomain of size 1 as being functions or being allowed within map.

I think your objection is fruitless. As @taylorswift said (emphasis mine):