Terminology: In the list comprehension the result and the input collections are all lists. I guess what I am talking about would be called just "comprehensions" or "generic comprehensions".
Keean. On 9 February 2015 at 17:53, Keean Schupke <[email protected]> wrote: > The comprehension does not need to know the types as it can use > type-classes. > > Keean. > > On 9 February 2015 at 15:37, Jonathan S. Shapiro <[email protected]> wrote: > >> Keean: >> >> Thanks for sticking with this. We're talking past each other again, so >> let's see if we can dig this out using your example. Before I start, let me >> ask a basic terminology question: >> >> When people speak of a "list comprehension", do the mean that the FOR >> loop is iterating over a list, or do they mean that the resulting >> accumulation is being *returned* as a list? Either way we still need to >> determine the type of /f/ somehow, but clarification on this bit of >> terminology will probably save us all from me writing stupidly in my >> confusion. :-) In other words, is: >> >> [ c | c <- s : String ] >> >> >> a string comprehension, or a list comprehension? >> >> >> Back to your note... >> >> First, you wrote that "x <- xs" is equivalent to "for x in xs" where xs >> is any collection. It's a little richer than that, because "c <- s:String" >> works, and String isn't a collection. So I think a better characterization >> is the xs, ys are iterables rather than collections. That isn't the part >> that's confusing me. >> >> You also wrote that "x <- xs, y <- ys" is equivalent to "for x in xs do { >> for y in ys do { ... }}". I understand what you are trying to say about how >> the iteration unpacks, but it's a somewhat puzzling unpacking of things, >> because there's no real way to implement that unpacking in functional >> style. We're ultimately interested in the results produced by the innermost >> body of those for loops, which we need to accumulate in some fashion. >> >> That would appear to mean that either (a) the *result* of the generator >> is *also* a collection and this is going to get implemented using some form >> of tail recursion that carries the result collection along as we accumulate >> its content, or (b) we're going to construct an empty collection first and >> then add content to it using a mutating insert operation. Your C++ >> translation using push_back() adopts approach (b). In a functional >> language, the tail-recursive unpacking of the FOR loops seems like an >> easier way to think about things conceptually once filters get introduced >> into the picture. >> >> OK. So here are my questions: >> >> 1. Given that FOR does not have any intrinsically associated collection >> type for its result, how is it determined what collection type will be used >> for that result? Presumably it can't be an arbitrary collection type, >> because it has to be a collection type that supports a functional-style >> "add element to collection giving new collection" sort of operation so that >> we can implement the FOR in functional style. >> >> 2. Assuming we agree that the result collection is being "built by >> accumulation" in this fashion, how do we get from that collection to an >> array or vector construction in a principled way? >> >> If the overall comprehension actually yields a type that supports >> accumulation, then I can more or less see how the rewrite goes once we know >> the result type. I can even see a really ugly way to get to vectors from >> there, but I truly do *not* see how to get to (fixed length) arrays. >> Hmm. I guess we could use a truncating accumulation. >> >> >> So: given "pattern | generator" we certainly know from the pattern what >> the element type being accumulated is. My question is: how do we know the >> type of the thing that is accumulating those elements? >> >> >> On Mon, Feb 9, 2015 at 6:16 AM, Keean Schupke <[email protected]> wrote: >> >>> f.clear(); >>> for (auto j = ys.begin(), auto& y = *j; j != ys.end(); ++j ) { >>> for (auto i = xs.begin(), auto& x = *i; i != xs.end(); ++i) { >>> if (x > y) { >>> f.push_back(make_tuple(x, y)); >>> } >>> } >>> } >>> >>> Not only do we not care what they type of container "xs" and "ys" are >>> (they could be different), we don't care about the type of "f" either. All >>> we care is they implement the right interface. >>> >> >> Yes and no. I agree that f merely needs to be of some type that >> implements the necessary interface. Still, we must *somewhere* determine >> what the type of f actually is. >> >> >> shap >> >> _______________________________________________ >> bitc-dev mailing list >> [email protected] >> http://www.coyotos.org/mailman/listinfo/bitc-dev >> >> >
_______________________________________________ bitc-dev mailing list [email protected] http://www.coyotos.org/mailman/listinfo/bitc-dev
