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

Reply via email to