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

Reply via email to