Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Define the traits required by for loops #1080

Closed
kyouko-taiga opened this issue Oct 11, 2023 · 1 comment
Closed

Define the traits required by for loops #1080

kyouko-taiga opened this issue Oct 11, 2023 · 1 comment

Comments

@kyouko-taiga
Copy link
Contributor

We have to define which traits will be required by for loops to describe how iteration is implemented.

I believe there are two kinds of for loops we want to consider: non-consuming and consuming. Non-consuming loops only need read and/or write access to container being iterated over. That information is described by the introducer of the element pattern, which should be let or inout:

public fun main() {
  var a: Array = [1, 2, 3]
  for inout x in &a { &x = x * x }
  print(a) // [1, 4, 9]
}

Consuming loops take ownership of the container's elements. They use a var or sink let introducer:

public fun main() {
  var a: Array = [1, 2, 3]
  var b = Array<Int>()
  for sink let x in a { &b.append(x) }
  // <- `a` is considered consumed here, accessing it causes a compile-time error
}

I think we should a different trait for each of these use cases. For non-consuming loops, Collection is probably the most appropriate choice. A for loop would desugar as a while loop breaking when we reach end_index. For example (desugared parts marked with //*):

public fun main() {
  var a: Array = [1, 2, 3]
  var i = a.start_index()    // *
  while i != a.end_index() { // *
    inout x = &a[i]          // *
    &x = x * x
    &i = a.index(after: i)   // *
  }
}

For consuming loops, I think we would need some kind of generator. We can re-use Swift's Sequence (or something similar to get a generator):

public fun main() {
  var a: Array = [1, 2, 3]
  var b = Array<Int>()
  var i = a.make_iterator()           // * (note: `make_iterator` is a `sink` method)
  while sink let x: Int = &i.next() { // *
    &b.append(x)
  }
}
@kyouko-taiga
Copy link
Contributor Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant