[swift-evolution] About the PermutationGenerator

Dave Abrahams dabrahams at apple.com
Thu Dec 31 23:22:19 CST 2015


> On Dec 31, 2015, at 8:22 PM, 鄭齊峯 via swift-evolution <swift-evolution at swift.org> wrote:
> 
> if you try my modification, it will crash.

Only because your Sequence genereates an arithmetic underflow.  I don’t understand what point you’re trying to make
> 
> struct Fib : SequenceType {
>     
>     var a: Int
>     var b: Int
>     
>     var limit: Int
>     
>     func generate() -> FibGenerator {
>         return Generator(a: a, b: b, limit: limit)
>     }
> }
> 
> let c = Multipass(Fib(a: 1, b: -1, limit: 10))
> 
> A SequenceType becomes a CollectionType only work by adding a Index. that the most significantly different of sequence and collection.

I think I understand that pretty well, having designed both of those abstractions, but still don’t get your point.  Sorry, I’m trying here, but I can’t figure out what you’re trying to tell me.

> 
> /// A `CollectionType` containing the same elements as `Base`, without storing them.
> ///
> /// - Requires: `Base` supports multiple passes (traversing it does not
> ///   consume the sequence), and `Base.Generator` has value semantics
> public struct Multipass<Base: SequenceType> : CollectionType {
>     public var startIndex: MultipassIndex<Base> {
>         var g = _base.enumerate().generate()
>         if let (idx, val) = g.next() {
>             return MultipassIndex(index: idx, buffer: val, generator: g)
>         }
>         return MultipassIndex(index: nil, buffer: nil, generator: g)
>     }
>     
>     public var endIndex: MultipassIndex<Base> {
>         return MultipassIndex(index: nil, buffer: nil, generator: _base.enumerate().generate())
>     }
>     
>     public subscript(position: MultipassIndex<Base>) -> Base.Generator.Element {
>         return position.buffer!
>     }
>     
>     public init(_ base: Base) {
>         _base = base
>     }
>     
>     var _base: Base
> }
> 
> // Note: Requires T.Generator has value semantics
> public struct MultipassIndex<T: SequenceType> : ForwardIndexType {
>     public func successor() -> MultipassIndex {
>         var r = self
>         if let (idx, val) = r.generator.next() {
>             r.index = idx
>             r.buffer = val
>         } else {
>             r.index = nil
>             r.buffer = nil
>         }
>         return r
>     }
>     var index: Int?
>     var buffer: T.Generator.Element?
>     var generator: EnumerateSequence<T>.Generator
> }
> 
> public func == <T>(x: MultipassIndex<T>, y: MultipassIndex<T>) -> Bool {
>     return x.index == y.index
> }
> 
> //===--- An example fibonacci sequence ------------------------------------===//
> struct FibGenerator : GeneratorType {
>     mutating func next() -> Int? {
>         let c = a + b
>         a = b
>         b = c
>         return a < limit ? a : nil
>     }
>     var a, b, limit: Int
> }
> 
> 
> struct Fib : SequenceType {
>     var limit = 100
>     
>     func generate() -> FibGenerator {
>         return Generator(a: 0, b: 1, limit: limit)
>     }
> }
> 
> It's true that ForwardIndexType is also run-through the base one by one but it also correct that getting specific value with specific index.
> 
> c[c.startIndex.successor().successor().successor()] // it's a defined behave

Again, not sure what you’re trying to say here.

> 
> 
>> Dave Abrahams <dabrahams at apple.com <mailto:dabrahams at apple.com>> 於 2016年1月1日 下午12:00 寫道:
>> 
>>> 
>>> On Dec 31, 2015, at 7:46 PM, Susan Cheng <susan.doggie at gmail.com <mailto:susan.doggie at gmail.com>> wrote:
>>> 
>>> 
>>> How GeneratorType confirm to Equatable??
>> 
>> I don’t understand the question.  In the code I posted there’s a working example of how a GeneratorType model can conform to Equatable..
>> 
>>> 
>>> struct Fib : SequenceType {
>>>     
>>>     var a: Int
>>>     var b: Int
>>>     
>>>     var limit: Int
>>>     
>>>     func generate() -> FibGenerator {
>>>         return Generator(a: a, b: b, limit: limit)
>>>     }
>>> }
>>> 
>>> let c = Multipass(Fib(a: 1, b: -1, limit: 10))
>>> 
>>> -Susan
>>> 
>>> 
>>> 2016-01-01 11:17 GMT+08:00 Dave Abrahams <dabrahams at apple.com <mailto:dabrahams at apple.com>>:
>>> FWIW, Indexable is an implementation artifact that will go away when Swift’s generics system is improved.
>>> 
>>> But if your real objection is that you have to come up with an Index and a subscripting operator, I can understand that.  Part of the reason for this is our reluctance to create any distinct protocols with identical syntactic requirements <http://news.gmane.org/find-root.php?message_id=2A3E0C76-1C88-4752-8A70-AA64BB14223A@apple.com <http://news.gmane.org/find-root.php?message_id=2A3E0C76-1C88-4752-8A70-AA64BB14223A@apple.com>>.  To justify having a separate multi-pass sequence protocol, there would have to be a significant/important class of multi-pass sequences for which CollectionType was unimplementable without serious costs.
>>> 
>>> In principle there’s a way to ease the pain of creating CollectionType conformances for multipass SequenceTypes…if only it didn’t crash the compiler <https://bugs.swift.org/browse/SR-427 <https://bugs.swift.org/browse/SR-427>> ;-).  Here’s a variation that uses a generic adapter instead of a protocol conformance declaration:
>>> 
>>> /// A `CollectionType` containing the same elements as `Base`, without storing them.
>>> ///
>>> /// - Requires: `Base` supports multiple passes (traversing it does not
>>> ///   consume the sequence), and `Base.Generator` has value semantics
>>> public struct Multipass<Base: SequenceType where Base.Generator: Equatable> : CollectionType {
>>>   public var startIndex: MultipassIndex<Base> {
>>>     var g = _base.generate()
>>>     return MultipassIndex(buffer: g.next(), generator: g)
>>>   }
>>> 
>>>   public var endIndex: MultipassIndex<Base> {
>>>     return MultipassIndex(buffer: nil, generator: _base.generate())
>>>   }
>>> 
>>>   public subscript(position: MultipassIndex<Base>) -> Base.Generator.Element {
>>>     return position.buffer!
>>>   }
>>> 
>>>   public init(_ base: Base) {
>>>     _base = base
>>>   }
>>> 
>>>   var _base: Base
>>> }
>>> 
>>> // Note: Requires T.Generator has value semantics
>>> public struct MultipassIndex<T: SequenceType where T.Generator: Equatable> : ForwardIndexType {
>>>   public func successor() -> MultipassIndex {
>>>     var r = self
>>>     r.buffer = r.generator.next()
>>>     return r
>>>   }
>>>   var buffer: T.Generator.Element?
>>>   var generator: T.Generator
>>> }
>>> 
>>> public func == <T>(x: MultipassIndex<T>, y: MultipassIndex<T>) -> Bool {
>>>   return x.buffer == nil && y.buffer == nil || x.generator == y.generator
>>> }
>>> 
>>> //===--- An example fibonacci sequence ------------------------------------===//
>>> struct FibGenerator : GeneratorType {
>>>   mutating func next() -> Int? {
>>>     let c = a + b
>>>     a = b
>>>     b = c
>>>     return a < limit ? a : nil
>>>   }
>>>   var a, b, limit: Int
>>> }
>>> 
>>> 
>>> struct Fib : SequenceType {
>>>   var limit = 1000
>>> 
>>>   func generate() -> FibGenerator {
>>>     return Generator(a: 0, b: 1, limit: limit)
>>>   }
>>> }
>>> 
>>> //===--- Adapt Fib for use with Multipass ---------------------------------===//
>>> extension FibGenerator : Equatable {}
>>> func == (x: Fib.Generator, y: Fib.Generator) -> Bool {
>>>   return x.a == y.a
>>> }
>>> 
>>> //===--- Demonstration ----------------------------------------------------===//
>>> let c = Multipass(Fib())
>>> print(c.first)
>>> print(c.count)
>>> print(c.lazy.map { $0 + 1 })
>>> 
>> 
>> -Dave
> 
>  _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
-Dave

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151231/8c157adf/attachment.html>


More information about the swift-evolution mailing list