Skip to content

Latest commit

 

History

History
118 lines (63 loc) · 8.66 KB

08-10.md

File metadata and controls

118 lines (63 loc) · 8.66 KB

August 10, 2020 Incubator Call Notes

Attendees:

  • John Hax (JHX)
  • Chengzhong Wu (CZW)
  • Jack Works (JWK)
  • Michael Ficarra (MF)
  • Richard Gibson (RGN)
  • Yulia Startsev (YSV)
  • Shu-yu Guo (SYG)
  • Tab Atkins (TAB)

API Style for Range: Iterator or Iterable? Plain function or class?

JWK: The two API design questions are related.

SYG: So if it were an iterator then it should be a function. If it were an iterable then it should be a class.

MF: I’m not sure if we can separate that two. IMO, either style makes sense to me.

SYG: Is there anyone on the call who feel differently?

MF: I think Jordan’s position on making consistency on language makes sense to me.

JWK: (...)

SYG: Does Jordan’s position conflict at all?

JHX: Actually I don’t understand why these two issues have to be bound together. If the thing is class, we still can have a plain function or static method as the factory which returns an object.

JWK: we can bind these options behind the scene, and expose these APIs simpler. Like the array constructor, it can be called and this is apply-able to the Range too. Although after the ES6 era new classes are not callable, I think it is acceptable for an exception for the range.

SYG: (...) The main difference is that the thing you get back is single use or multiple use.

TAB: Jordan made a point that the point to re-use is to use arrow functions. I think I strongly agree here, it's extraordinarily cheap. The way a JS author would do this is with a generator function, which is a single use. The vast majority of uses of an iterator you'll just run it through once anyway.

JWK: That makes sense. But sometimes people will forget that the iterator can only be used once, they will get accidentally reused, and there is no error, but just give you an empty result.

TAB: Most of the uses are going to be inline in for loops. So people aren't going to run into it.

SYG: Is it possible to reuse in Python?

TAB: Yes it is.

SYG: Most people are not going to reuse. Maybe accidentally?

JHX: Most languages run into a reusable pattern. Only in Rust and D use iterator semantics. I think JW has discussed the Rust case (Rust compiler protects the programmers). Iterator in D language is value type. If you want to reuse, you just assign it to a new binding, with copy semantic, these two iterators will not affect each other. This is why D language does not have the reuse issue. All other languages use iterables. I think we should be very careful to choose a different path.

TAB: If we're going for a reified Range object, it lets us put other methods on that. What other methods could there be on it?

JWK: You don't have to make it a class to add helpers on it. The current design lets you add helpers on the Range iterator prototype.

JHX: Always possible to add methods on the iterator prototype, but the problem here is what do programmers expect the methods to do? For example, "includes". If “includes” is on the iterator prototype, what's the semantics? Consume the iterator until meet the value and stop in that point? It's a little bit confusing if you think deeply about it. I think everything on the iterator should be related to iteration. Any other thing on the iterator prototype seems to have problems, causing confusion.

TAB: I agree.

MF: I also agree with that.

JWK: So if we want to add methods on the Range object, we should make it a class?

SYG: I'm getting a weak feeling that the room feels that way?

JWK: The view that supports its being an iterator is that we will implement it that way. If we'll add methods on the Range, then we will implement it as a class.

YSV: How would this interact with iterator helpers?

JWK: If we choose iterators, then it is obvious. If we choose the class way, then it wouldn't be too hard. Hax pointed out we can add a values() method, like Array.values(), and return the iterator, so range.values().some_iterator_helper_method(). It can be written in a chainable way, In this way there is no obvious difference between iterator vs iterable.

TAB: If we start from the point of just a Range object and have the iterator method provide the step, then that works fine. E.g. Number.range(1,10).by(1).

JHX: Ruby has a very similar API like .step(), using .step() to return iterators IIRC.

TAB: Nice thing about shaping the class this way is -- it sidesteps the earlier question. E.g. does contains() observe the stepping or not? In this design obviously it doesn't, since the Range is just a start and end, and the iterator method is what gives you the stepping.

MF: I like this!

TAB: I know Jordan still likes iterator. If we go with iterable I want a more featured proposal than just a Range. It'd be a lost opportunity if we go with a class for more fully featured. If just a simple iterator, I'd still favor iterator.

JWK: I've seen an issue that we should have a global Range concept, numbers, strings, even developer-defined classes, making Range somehow like a protocol. I'm not confident if we should go this way to design the API.

TAB: I don't know if a full featured abstract range protocol is called for yet. We shouldn't preclude it though. I'd be fine right now with just a numeric one.

JWK: Yeah, don't know how to range on Unicode.

JHX: I have some comments about Jordan's comment that reusability isn't important due to generators. AIUI a generator allows you to implement the iterable protocol in userland. And that's what ??? Python. In the previous discussion, in the repo issue of iterable vs iterator I also wrote examples to explain why arrow functions can't solve reusability problem. Because currently the method values/keys/entries() returns an iterator are all instance methods with no arguments. If you want to reuse something you just reuse the object. But for Range you have 2 or 3 arguments, that's very different. That means you do not have a reuse point directly. The current language design didn't really have a big reuse problem for iterators because you can reuse the instance object.

SYG: ISTM there're a lot of contingent agreement here: if we go fully featured then classes is the way to go, otherwise simple iterators might be okay, even though Hax still has concerns there. I recommend the next step for the champions here is to make a decision on which use case (simple or fully featured) this proposal wants to solve. Maybe a questionnaire, but should be careful about interpreting the data.

JWK: I want to extend with helpers but don't have examples for concrete helpers in mind.

MF: On the repo there are suggestions for count(), bounds.

SYG: Also note that Hax has made an argument that choosing iterators precludes future extensibility in a natural way. Are champions okay with remaining with the functionality of simple Ranges if they go with iterators?

JHX: I want to comment on count. It's possible to add to iterator helpers, but it needs to iterate the whole thing to get the final count. But you can get the count in a simple way.

JWK: I think you can calculate the count with simple math calculations.

JHX: If you can use simple math operations then I think it should not be iterator. If it's an iterator you have to consume the iterator.

JWK: Wait, if count is on iterator helpers, then that count must consume the iterator. But we can override it in the Range's iterator prototype.

JHX: I think it's not a good idea to override it. You change the behavior if we do not consume. It's possible, yeah.

JHD: (In response to earlier point in TCQ): Receiver is implicit first argument.

JHX: My point was there's no implicit reuse point for Range. Yeah you can wrap it up in an arrow function, but you need to call the arrow function, it's not an object. The usage patterns are very different, and that's why people may forget to wrap it. Many people do not know the difference between iterable and iterator. Maybe first it's only used once, when it evolves suddenly you use it twice and something goes wrong.

SYG: Why do you think reusability is going to be a real problem, given anecdotes from Python where most uses of Range are inline in the for loop?

JWK: I have a case where I want to re-use it. E.g. I might want to mock 20 objects in the UI developing, then I want to create a range from 0 to 20 and create some mocked data. Then if I want to create another piece of 20 items mocked data, I might re-use the previous range object then get into bugs.

SYG: Next action item for the champions is to figure out which use case they want their proposal to solve: the simple range question or the fully featured use case.

YSV: Maybe the research call can help you formulate a questionnaire.

SYG: Questionnaires and anecdotes can help you come to a position, but it is also valid for the champion to choose a use case and try to convince the committee it is the right use case to solve.