[Review] SE-0045: Add scan, prefix(while:), drop(while:), and iterate to the stdlib

I really don't want to see this discussion die as I have a vested interest in getting this functionality into
Swift 3. So let me suggest that

`sequence(_:, next:) -> AdHocSequence`

might be a Swift acceptable solution. We're not going to see fold/unfold pair happen. It's a given that
`reduce` is a fixed point in Swift space and `sequence` well describes what this should be doing.

So is it possible to push forward with `sequence`, whose only negative seems to be that it's not as well
loved as `unfold`?

-- Erica

···

On May 1, 2016, at 5:13 AM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:

The proposal has been updated as per feedback from the core team (https://github.com/apple/swift-evolution/pull/275\). This includes removing some last vestiges of Swift 2 naming as well as replacing `iterate(_:apply:)` with an overloaded function `unfold(_:applying:)`.

The proposal says this:

  public func unfold<T, State>(_ initialState: State, applying: State -> (T, State)?) -> UnfoldSequence<T>
  public func unfold<T>(_ initialElement: T, apply: T -> T) -> UnfoldSequence<T>

However, the comment implies that the second one should instead be this:

  public func unfold<T>(_ initialElement: T, applying: T -> T?) -> UnfoldSequence<T>

I'm not sure I like having these be overloaded on only the return type of the closure. Maybe we could do something like this?

  public func unfold<T, State>(fromState initialState: State, applying: State -> (T, State)?) -> UnfoldSequence<T>
  public func unfold<T>(fromFirst initialElement: T, apply: T -> T) -> UnfoldSequence<T>

That way you're calling either `unfold(fromState:applying:)` or `unfold(fromFirst:applying:)`. (Some further bikeshedding might be needed here—it's late and I'm tired.)

+1!

···

on Fri Apr 29 2016, Kevin Ballard <swift-evolution@swift.org> wrote:

On Thu, Apr 28, 2016, at 02:13 PM, Pyry Jahkola via swift-evolution wrote:

    I would really like a different name for scan. While it’s the term of art
        for Haskell and co, it really seems meaningless to regular programmers
        (why is “scanning” the way you produce an array of intermediate
        reduces?), and it would be better to follow the pattern already
        established elsewhere in the library to give friendlier names e.g.
        flatMap instead of bind, reduce instead of fold.

        I think Python calls it accumulate:
        itertools — Functions creating iterators for efficient looping — Python 3.12.0 documentation

    FWIW, Clojure calls it `reductions` which aligns pretty nicely with the
    `reduce` counterpart.

I like it.

--
Dave

I do like `sequence`, though I'm not sold on the name AdHocSequence
(just from that name it's hard to figure out what it does). An
alternative is `expand`, which is nice because it pairs with `reduce`,
but it's less obvious that it produces a sequence and the name isn't as
good with the stateful version.

As for return type name, we could go ahead and use UnfoldSequence<T>
anyway even though the function isn't named `unfold`, because this name
will make sense to people who do know what unfold is, and I'm not
convinced we can have a meaningful name for people who don't (since
SequenceSequence is too silly).

So given that, I'll suggest the following:

func sequence<T>(initial: T, next: T -> T?) -> UnfoldSequence<T>
func sequence<T, State>(state: State, next: (inout State) -> T?) ->
UnfoldSequence<T>

I'm suggesting `sequence(initial:next:)` instead of the previously-
suggested `sequence(from:applying:)` because the term "from" could
equally well mean the first element or the state, whereas "initial"
should make it more obvious that this value is the first element of the
resulting sequence. And I'm using "next" as suggested by Erica because
the function does return the next element, and it's similar to the
IteratorProtocol method. I've also chosen to change the stateful version
to use an inout parameter, as previously suggested, because it's
equivalent to the State -> (T, State)? in functionality but is less
likely to produce unwanted COW copies.

-Kevin Ballard

···

On Fri, May 13, 2016, at 11:08 AM, Erica Sadun wrote:

On May 1, 2016, at 5:13 AM, Brent Royal-Gordon via swift-evolution <swift- > evolution@swift.org> wrote:

The proposal has been updated as per feedback from the core team
(https://github.com/apple/swift-evolution/pull/275\). This includes
removing some last vestiges of Swift 2 naming as well as replacing
`iterate(_:apply:)` with an overloaded function
`unfold(_:applying:)`.

The proposal says this:

public func unfold<T, State>(_ initialState: State, applying: State
-> (T, State)?) -> UnfoldSequence<T>
public func unfold<T>(_ initialElement: T, apply: T -> T) ->
UnfoldSequence<T>

However, the comment implies that the second one should instead
be this:

public func unfold<T>(_ initialElement: T, applying: T -> T?) ->
UnfoldSequence<T>

I'm not sure I like having these be overloaded on only the return
type of the closure. Maybe we could do something like this?

public func unfold<T, State>(fromState initialState: State,
applying: State -> (T, State)?) -> UnfoldSequence<T>
public func unfold<T>(fromFirst initialElement: T, apply: T -> T) ->
UnfoldSequence<T>

That way you're calling either `unfold(fromState:applying:)` or
`unfold(fromFirst:applying:)`. (Some further bikeshedding might be
needed here—it's late and I'm tired.)

I really don't want to see this discussion die as I have a vested
interest in getting this functionality into
Swift 3. So let me suggest that

`sequence(_:, next:) -> AdHocSequence`

might be a Swift acceptable solution. We're not going to see
fold/unfold pair happen. It's a given that
`reduce` is a fixed point in Swift space and `sequence` well describes
what this should be doing.

So is it possible to push forward with `sequence`, whose only negative
seems to be that it's not as well
loved as `unfold`?

Would there be any issue with the return type being AnySequence? It’s used in other areas:

LazySequence & FlattenSequence’s
dropFirst(n: Int) -> AnySequence<Generator.Element>
dropLast(n: Int) -> AnySequence<Generator.Element>

No need to introduce another type, and it’s straight forward to implement with AnySequence.

···

On 14 May 2016, at 5:07 AM, Kevin Ballard via swift-evolution <swift-evolution@swift.org> wrote:

On Fri, May 13, 2016, at 11:08 AM, Erica Sadun wrote:

On May 1, 2016, at 5:13 AM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

The proposal has been updated as per feedback from the core team (https://github.com/apple/swift-evolution/pull/275\). This includes removing some last vestiges of Swift 2 naming as well as replacing `iterate(_:apply:)` with an overloaded function `unfold(_:applying:)`.

The proposal says this:

public func unfold<T, State>(_ initialState: State, applying: State -> (T, State)?) -> UnfoldSequence<T>
public func unfold<T>(_ initialElement: T, apply: T -> T) -> UnfoldSequence<T>

However, the comment implies that the second one should instead be this:

public func unfold<T>(_ initialElement: T, applying: T -> T?) -> UnfoldSequence<T>

I'm not sure I like having these be overloaded on only the return type of the closure. Maybe we could do something like this?

public func unfold<T, State>(fromState initialState: State, applying: State -> (T, State)?) -> UnfoldSequence<T>
public func unfold<T>(fromFirst initialElement: T, apply: T -> T) -> UnfoldSequence<T>

That way you're calling either `unfold(fromState:applying:)` or `unfold(fromFirst:applying:)`. (Some further bikeshedding might be needed here—it's late and I'm tired.)

I really don't want to see this discussion die as I have a vested interest in getting this functionality into
Swift 3. So let me suggest that

`sequence(_:, next:) -> AdHocSequence`

might be a Swift acceptable solution. We're not going to see fold/unfold pair happen. It's a given that
`reduce` is a fixed point in Swift space and `sequence` well describes what this should be doing.

So is it possible to push forward with `sequence`, whose only negative seems to be that it's not as well
loved as `unfold`?

I do like `sequence`, though I'm not sold on the name AdHocSequence (just from that name it's hard to figure out what it does). An alternative is `expand`, which is nice because it pairs with `reduce`, but it's less obvious that it produces a sequence and the name isn't as good with the stateful version.

As for return type name, we could go ahead and use UnfoldSequence<T> anyway even though the function isn't named `unfold`, because this name will make sense to people who do know what unfold is, and I'm not convinced we can have a meaningful name for people who don't (since SequenceSequence is too silly).

So given that, I'll suggest the following:

  func sequence<T>(initial: T, next: T -> T?) -> UnfoldSequence<T>
  func sequence<T, State>(state: State, next: (inout State) -> T?) -> UnfoldSequence<T>

I'm suggesting `sequence(initial:next:)` instead of the previously-suggested `sequence(from:applying:)` because the term "from" could equally well mean the first element or the state, whereas "initial" should make it more obvious that this value is the first element of the resulting sequence. And I'm using "next" as suggested by Erica because the function does return the next element, and it's similar to the IteratorProtocol method. I've also chosen to change the stateful version to use an inout parameter, as previously suggested, because it's equivalent to the State -> (T, State)? in functionality but is less likely to produce unwanted COW copies.

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

AnySequence is specifically used to erase the type of an underlying
sequence, and I'm guessing that using it here will make it harder to
optimize loops that use this.

-Kevin Ballard

···

On Fri, May 13, 2016, at 10:20 PM, Patrick Smith wrote:

Would there be any issue with the return type being AnySequence? It’s
used in other areas:

LazySequence & FlattenSequence’s
dropFirst(n: Int) -> AnySequence<Generator.Element>
dropLast(n: Int) -> AnySequence<Generator.Element>

No need to introduce another type, and it’s straight forward to
implement with AnySequence.

On 14 May 2016, at 5:07 AM, Kevin Ballard via swift-evolution <swift- >> evolution@swift.org> wrote:

On Fri, May 13, 2016, at 11:08 AM, Erica Sadun wrote:

On May 1, 2016, at 5:13 AM, Brent Royal-Gordon via swift-evolution >>> <swift-evolution@swift.org> wrote:

The proposal has been updated as per feedback from the core team
(https://github.com/apple/swift-evolution/pull/275\). This includes
removing some last vestiges of Swift 2 naming as well as replacing
`iterate(_:apply:)` with an overloaded function
`unfold(_:applying:)`.

The proposal says this:

public func unfold<T, State>(_ initialState: State, applying: State
-> (T, State)?) -> UnfoldSequence<T>
public func unfold<T>(_ initialElement: T, apply: T -> T) ->
UnfoldSequence<T>

However, the comment implies that the second one should instead be
this:

public func unfold<T>(_ initialElement: T, applying: T -> T?) ->
UnfoldSequence<T>

I'm not sure I like having these be overloaded on only the return
type of the closure. Maybe we could do something like this?

public func unfold<T, State>(fromState initialState: State,
applying: State -> (T, State)?) -> UnfoldSequence<T>
public func unfold<T>(fromFirst initialElement: T, apply: T -> T)
-> UnfoldSequence<T>

That way you're calling either `unfold(fromState:applying:)` or
`unfold(fromFirst:applying:)`. (Some further bikeshedding might be
needed here—it's late and I'm tired.)

I really don't want to see this discussion die as I have a vested
interest in getting this functionality into
Swift 3. So let me suggest that

`sequence(_:, next:) -> AdHocSequence`

might be a Swift acceptable solution. We're not going to see
fold/unfold pair happen. It's a given that
`reduce` is a fixed point in Swift space and `sequence` well
describes what this should be doing.

So is it possible to push forward with `sequence`, whose only
negative seems to be that it's not as well
loved as `unfold`?

I do like `sequence`, though I'm not sold on the name AdHocSequence
(just from that name it's hard to figure out what it does). An
alternative is `expand`, which is nice because it pairs with
`reduce`, but it's less obvious that it produces a sequence and the
name isn't as good with the stateful version.

As for return type name, we could go ahead and use UnfoldSequence<T>
anyway even though the function isn't named `unfold`, because this
name will make sense to people who do know what unfold is, and I'm
not convinced we can have a meaningful name for people who don't
(since SequenceSequence is too silly).

So given that, I'll suggest the following:

func sequence<T>(initial: T, next: T -> T?) -> UnfoldSequence<T>
func sequence<T, State>(state: State, next: (inout State) -> T?) ->
UnfoldSequence<T>

I'm suggesting `sequence(initial:next:)` instead of the previously-
suggested `sequence(from:applying:)` because the term "from" could
equally well mean the first element or the state, whereas "initial"
should make it more obvious that this value is the first element of
the resulting sequence. And I'm using "next" as suggested by Erica
because the function does return the next element, and it's similar
to the IteratorProtocol method. I've also chosen to change the
stateful version to use an inout parameter, as previously suggested,
because it's equivalent to the State -> (T, State)? in functionality
but is less likely to produce unwanted COW copies.

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