[swift-evolution] Multi dimensional - iterator, Iterator2D, Iterator3D

Erica Sadun erica at ericasadun.com
Sun Jul 31 11:33:28 CDT 2016


I'm replying on Swift-Users and bcc'ing in Swift-Evolution to comply with the core team's request to focus SE on the current mission statement. 

At some point soon, Russ Bishop's PR https://github.com/apple/swift/pull/3600 <https://github.com/apple/swift/pull/3600> will be incorporated into Swift 3. This PR adds `prefix(while:)` and `drop(while:)` to finish implementing SE-0045.  Once that's done, you can  combine `sequence(first:, next:)` and `prefix(while:)` to into a single function `sequence(first:, next:, while:)` like this:

public func sequence<T>(first: T, next: (T) -> T?, while test: (T) -> Bool) -> UnfoldSequence<T, UnfoldSequence<T, (T?, Bool)>> {
    return sequence(first: first, next: next).prefix(while: test)
}

The combined sequence/prefix call allows you to create loops like this:

for outerIndex in sequence(first: 1, next: { $0 * 2 }, while: { $0 <= 64 }) {
    for innerIndex in sequence(first: 1, next: { $0 * 2 }, while: { $0 <= 64 }) {
        print(outerIndex, innerIndex)
    }
}

These loops can be nested. break and continue work.  You can use tuples for multiple arguments. While I'd like to see a combined form adopted into Swift 4b (the deferred "sugar"), it isn't a high priority.

-- E


> On Jul 31, 2016, at 7:18 AM, Ted F.A. van Gaalen via swift-evolution <swift-evolution at swift.org> wrote:
> 
> 
>> On 31.07.2016, at 04:28, jaden.geller at gmail.com <mailto:jaden.geller at gmail.com> wrote:
>> 
>> What benefit do Iterator2D and Iterator3D provide that nesting does not?
> Hi Jaden,
> well, simply because of hiding/enclosing repetitive functionality
> like with every other programming element is convenient,
> prevents errors and from writing the same over and over again.
> That is why there are functions.
> but you already know that, of course.
> Kind Regards
> TedvG
> 
>> 
>> On Jul 30, 2016, at 1:48 PM, Ted F.A. van Gaalen via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>> 
>>> Hi Chris,
>>> 
>>> thanks for the tip about Hirundo app!
>>> 
>>> A positive side-effect of removing the classical for;; loop
>>>  (yes, it’s me saying this :o)  is that it forces me to find
>>> a good and generic equivalent for it, 
>>> making the conversion of my for;;s to 3.0 easier.
>>> which is *not* based on collections or sequences and
>>> does not rely on deeper calls to Sequence etc.
>>> 
>>> so, I’ve made the functions [iterator, iterator2D, iterator3D]  (hereunder)
>>> wich btw clearly demonstrate the power and flexibility of Swift. 
>>> 
>>> Very straightforward, and efficient (i assume) just like the classical for;; loop.  
>>> It works quite well in my sources.
>>> 
>>> As a spin-off,  I’ve extended these to iterators for matrices 2D and cubes? 3D...
>>> 
>>> Question: 
>>> Perhaps implementing “multi dimensional iterator functions
>>> in Swift might  be a good idea. so that is no longer necessary to nest/nest/nest iterators. 
>>> 
>>> Met vriendelijke groeten, sorry for my “intensity” in discussing the classical for;; 
>>> I'll have to rethink this for;; again..  
>>> Thanks, Ted.
>>> 
>>> Any remarks ( all ), suggestions about the code hereunder:              ? 
>>> 
>>> protocol NumericType
>>> {
>>>     func +(lhs: Self, rhs: Self) -> Self
>>>     func -(lhs: Self, rhs: Self) -> Self
>>>     func *(lhs: Self, rhs: Self) -> Self
>>>     func /(lhs: Self, rhs: Self) -> Self
>>>     func %(lhs: Self, rhs: Self) -> Self
>>> }
>>> 
>>> extension Double : NumericType { }
>>> extension Float  : NumericType { }
>>> extension CGFloat: NumericType { }
>>> extension Int    : NumericType { }
>>> extension Int8   : NumericType { }
>>> extension Int16  : NumericType { }
>>> extension Int32  : NumericType { }
>>> extension Int64  : NumericType { }
>>> extension UInt   : NumericType { }
>>> extension UInt8  : NumericType { }
>>> extension UInt16 : NumericType { }
>>> extension UInt32 : NumericType { }
>>> extension UInt64 : NumericType { }
>>> 
>>> 
>>> /// Simple iterator with generic parameters, with just a few lines of code.
>>> /// for most numeric types (see above)
>>> /// Usage Example:
>>> ///
>>> ///   iterate(xmax, { $0 > xmin}, -xstep,
>>> ///    {x in
>>> ///        print("x = \(x)")
>>> ///        return true  // returning false acts like a break
>>> ///     } )
>>> ///
>>> ///  -Parameter vstart: Initial value
>>> ///  -Parameter step:    The iteration stepping value.
>>> ///  -Parameter test:    A block with iteration test. e.g. {$0 > 10}
>>> ///
>>> ///  -Parameter block:   A block to be executed with each step.
>>> ///       The block must include a return true (acts like "continue")
>>> ///                                   or false (acts like "break")
>>> ///  -Please Note: 
>>> ///  There is minor precision loss ca: 1/1000 ... 1/500 
>>> ///  when iterating with floating point numbers.
>>> ///  However, in most cases this can be safely ignored.
>>> ///  made by ted van gaalen.
>>> 
>>> 
>>> func iterate<T:NumericType> (
>>>                     vstart:  T,
>>>                    _ vstep:  T,
>>>                    _  test: (T) -> Bool,
>>>                    _ block: (T) -> Bool )
>>> {
>>>     var current = vstart
>>>     
>>>     while test(current) && block(current)
>>>     {
>>>         current = current + vstep
>>>     }
>>> }
>>> 
>>> 
>>> /// X,Y 2D matrix (table) iterator with generic parameters
>>> func iterate2D<T:NumericType> (
>>>      xstart:  T,  _ xstep: T, _ xtest: (T) -> Bool,
>>>    _ ystart:  T,  _ ystep: T, _ ytest: (T) -> Bool,
>>>    _ block: (T,T) -> Bool )
>>> {
>>>     var xcurrent = xstart
>>>     var ycurrent = ystart
>>>     
>>>     var dontStop = true
>>>     
>>>     while xtest(xcurrent) && dontStop
>>>     {
>>>         ycurrent = ystart
>>>         while ytest(ycurrent) && dontStop
>>>         {
>>>             dontStop = block(xcurrent, ycurrent)
>>>             ycurrent = ycurrent + ystep
>>>         }
>>>         xcurrent = xcurrent + xstep
>>>     }
>>> }
>>> 
>>> 
>>> /// X,Y,Z 3D (cubic) iterator with generic parameters:
>>> 
>>> func iterate3D<T:NumericType> (
>>>     xstart:  T,  _ xstep: T, _ xtest: (T) -> Bool,
>>>   _ ystart:  T,  _ ystep: T, _ ytest: (T) -> Bool,
>>>   _ zstart:  T,  _ zstep: T, _ ztest: (T) -> Bool,
>>>       _ block: (T,T,T) -> Bool )
>>> {
>>>     var xcurrent = xstart
>>>     var ycurrent = ystart
>>>     var zcurrent = zstart
>>>     
>>>     var dontStop = true
>>>     
>>>     while xtest(xcurrent) && dontStop
>>>     {
>>>         ycurrent = ystart
>>>         while ytest(ycurrent) && dontStop
>>>         {
>>>             zcurrent = zstart
>>>             while ztest(zcurrent) && dontStop
>>>             {
>>>                 dontStop = block(xcurrent, ycurrent, zcurrent)
>>>                 zcurrent = zcurrent + zstep
>>>             }
>>>             ycurrent = ycurrent + ystep
>>>         }
>>>         xcurrent = xcurrent + xstep
>>>     }
>>> }
>>> 
>>> 
>>> func testIterator()
>>> {
>>>     iterate(0.0, 0.5, {$0 < 1000.00000} ,
>>>             { value in
>>>                 print("Value = \(value) ")
>>>                 return true
>>>     } )
>>> 
>>>     let startv: CGFloat = -20.0
>>>     let stepv: CGFloat =   0.5
>>>     
>>>     iterate(startv, stepv, {$0 < 1000.00000} ,
>>>             { val in
>>>                 print("R = \(val)")
>>>                 return true
>>>     } )
>>> 
>>>     let tolerance = 0.01 // boundary tolerance for floating point type
>>>     
>>>     iterate2D( 0.0, 10.0, { $0 < 100.0 + tolerance } ,
>>>                0.0,  5.0, { $0 <  50.0 + tolerance } ,
>>>                {x,y in
>>>                 print("x = \(x) y = \(y)")
>>>                 return true  // false from block stops iterating ( like break)
>>>                 } )
>>> 
>>>     iterate3D( 0.0,  10.0, { $0 <   30.0 } ,  // x
>>>                0.0,   5.0, { $0 <   20.0 } ,  // y
>>>                10.0, -5.0, { $0 >  -10.0 } ,  // z
>>>                {x,y,z in
>>>                     print("x = \(x) y = \(y) z = \(z)")
>>>                     if z < 0.0
>>>                     {
>>>                         print ( "** z value \(z) is below zero! **" )
>>>                         
>>>                         return false  // (acts as break in for;;)
>>>                     }
>>>                     return true  // return stmt is obligatory (continue)
>>>                } )
>>> }
>>> 
>>> 
>>> 
>>> 
>>> 
>>> 
>>> 
>>> 
>>> _______________________________________________
>>> 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>
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

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


More information about the swift-evolution mailing list