[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