[swift-evolution] [Pitch] Remove destructive consumption from Sequence
Dave Abrahams
dabrahams at apple.com
Thu Jun 30 18:24:29 CDT 2016
on Thu Jun 30 2016, Russ Bishop <xenadu-AT-gmail.com> wrote:
>> On Jun 30, 2016, at 3:37 PM, Dave Abrahams <dabrahams at apple.com> wrote:
>>
>>
>>>>> I use it in a LazyRowSequence<T: SqlModelConvertible> where
>>>>> querying Sqlite in WAL mode allows multiple concurrent readers to
>
>>>>> get point-in-time snapshots of the database. The query can’t be
>>>>> replayed without buffering all the rows in memory because Sqlite’s
>>>>> step functions are not bi-directional. In some cases we are talking
>>>>> about tens of thousands of rows (or even hundreds of thousands) and
>>>>> the ability to avoid buffering them is a feature, not a bug.
>>>
>>> IMHO the typical case for single-pass is IO.
>>
>> Yes. Also, truly-random number generators.
>>
>>> In this case it would work just as well as LazyRowIterator<T> assuming
>>> the language allows for-in on an iterator.
>>
>> So, you're not interested in using algorithms like map and filter on
>> these things?
>>
>> If it was just about for-in, we could say you can for-in over any
>> instance of
>>
>> ()->T?
>>
>
> Fair point; we actually do take advantage of the lazy versions of
> filter and map.
>
> Does it make sense to say that single-pass sequences are always lazy?
It might. Would it be inconvenient?
>
> Iterable
> / \
> / \
> LazyIterable EagerIterable
> | |
> LazyCollection Collection
>
> LazyCollection is a wrapper around Collection so you can still use
> .lazy the way you would today.
Is it a protocol? Wrappers are usually generics.
>
> LazyIterables are single-pass. EagerIterables are multi-pass.
> Maybe this doesn’t work because we’re talking about somewhat
> orthogonal things? I could imagine trying to model the idea of single
> vs multi pass and lazy vs eager separately:
The goal of generic programming is not to separate every idea into its
own protocol. Discovering the natural dependency relationships and
clusters of requirements and capabilities is a crucial part of it. As
far as I can tell, lazy operations are always appropriate.
>
>> protocol Iterable {
>> associatedtype Iterator: IteratorProtocol
>> associatedtype Element = Iterator.Element
>> func makeIterator() -> Iterator
>> }
>> protocol MultiIterable: Iterable { }
>> protocol SingleIterable: Iterable { }
>> protocol LazyIterable: Iterable { }
>> protocol EagerIterable: Iterable { }
>>
>> extension MultiIterable where Self: EagerIterable {
>> func map<U>(t: @noescape (Element) -> U) -> [U] { }
>> }
>>
>> extension MultiIterable where Self: LazyIterable {
>> func map<U>(t: (Element) -> U) -> LazyMapMultiIterable<Self> { }
>> }
>>
>> extension SingleIterable where Self: LazyIterable {
>> func map<U>(t: (Element) -> U) -> LazyMapSingleIterable<Self> { }
>> }
>
> I guess it comes back to what you and others have pointed out - it
> might not be worth the effort to provide this level of flexibility.
--
Dave
More information about the swift-evolution
mailing list