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

Saagar Jha saagar at saagarjha.com
Mon Aug 1 10:45:15 CDT 2016


With your method, don't you need to write a new method for every dimension?
On Mon, Aug 1, 2016 at 08:43 Ted F.A. van Gaalen via swift-users <
swift-users at swift.org> wrote:

> Hi Erica
>
> That would also be a workable solution, but imho still too tedious as
> it has been so for many years, with nested iteration statements…
> many times this is for;; for;; for tables and for;;for;;for;; for 3D
> structuring.
>
>
> Swift offers nice features (like protocols and generics as you know) to
> improve this.
>
> - I no longer have to nest for;; s  so, Now I rather do this:
> Your example can already be coded like this:
>
>    iterate2D( 1, 2, { $0 < 64 } ,
>               1, 2, { $0 < 64 } ,
>                   {outerIndex,innerIndex in
>                       print (outerIndex,InnerIndex)
>
>                       return true // Obligatory. return “false" to break
>                    }  )
>
> With no chances in Swift, this already works like a charm!
> Imho much more readable and compact,
>
> Uses - AFAICS from a programmers’s perspective - no
> underlying deep collection based coding with Sequence. etc.
>
> I am already deploying it in my own apps e.g. l
> (replaced for;; for;; for;; in the app)
>
> By using this new iterator…() functions my coding gets leaner
> and errors are easier to spot.
>
> Actual working code with Swift 2.x here:
>
>   func generateTiles()
>   {
>         let w:      Float =   20  // tile size
>         let h:      Float =    5
>         let l:      Float =    5
>
>
>         let xstart: Float = -120
>         let ystart: Float =  -60
>         let zstart: Float =  -10
>
>
>         let xend: Float = 120
>         let yend: Float =  60
>         let zend: Float =  10
>
>
>         let tolerance:Float = 0.001 // float drift compensation
>
>
>         iterate3D( xstart, w * 1.2, { $0 < xend + tolerance } ,
>                    ystart, h * 1.2, { $0 < yend + tolerance } ,
>                    zstart, l * 1.2, { $0 < zend + tolerance } ,
>                    {
>                     x,y,z in
>                     self.addTile(x,y,z,
>                                  w,h,l)
>                     return true
>                    }  )
>     }
>
> This generates a group of blocks or tiles in my Apple TV app (under
> construction)
> like the one you can see  in the image “Cloinckz” on my website
> www.tedvg.com.
>
> I also prefer the one dimensional iterate(..  too above the for;; or
> stride()
>
> One could extend these iterator…() functions by adding closures for pre
> and post iteration handling,
> like for printing headers and footers before and/or after a complete
> [inner] iteration.
>
> Note that breaking with *return false* -which is equivalent to the “break”
> stmt in
> a classical for;; -  does not only leave a nested iteration, but also the
> outer ones.
> (maybe a TODO to make individual level- break possible)  As it is now, If
> one
> wants to break at the deep iteration level, then one should nest this
> using 1D iterators.
>
>
> Anyway, this is just a thought starting to think about multi-dimensional
> iterators,
> and other (encapsulation?) of multi dimensional data as well.
> In any case for 2D because table data is used very frequently in many
> apps. as
> most data are in tables.
>
> You won’t believe this :o) but in a sense I might not make so much fuzz
> anymore
> to keep the for;;  as this proves to me that I can solve things much
> better that I thought.
> So, I have to rethink this.
>
> Kind Regards
> Ted
> www.ravelnotes.com
>
>
>
>
>
>
>
> On 31.07.2016, at 18:33, Erica Sadun <erica at ericasadun.com> wrote:
>
> 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 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 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> 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
> 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
>
>
>
> _______________________________________________
> swift-users mailing list
> swift-users at swift.org
> https://lists.swift.org/mailman/listinfo/swift-users
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20160801/7ee4d4e0/attachment.html>


More information about the swift-users mailing list