[swift-evolution] [swift-users] Multi dimensional - iterator, Iterator2D, Iterator3D
Ted F.A. van Gaalen
tedvgiosdev at gmail.com
Tue Aug 2 10:02:13 CDT 2016
> On 01.08.2016, at 17:45, Saagar Jha <saagar at saagarjha.com> wrote:
>
> With your method, don't you need to write a new method for every dimension?
Hi Saagar,
Yes, one could solve this by writing a function
that propagates though all iteration levels, possibly recursively,
I might try to implement that.
left “as an exercise to the astute reader” :o)
Kind regards
Ted
> On Mon, Aug 1, 2016 at 08:43 Ted F.A. van Gaalen via swift-users <swift-users at swift.org <mailto: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 <http://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 <http://www.ravelnotes.com/>
>
>
>
>
>
>
>
>> On 31.07.2016, at 18:33, Erica Sadun <erica at ericasadun.com <mailto: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 <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 <mailto: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 <mailto:swift-evolution at swift.org>
>>> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>
>
> _______________________________________________
> swift-users mailing list
> swift-users at swift.org <mailto:swift-users at swift.org>
> https://lists.swift.org/mailman/listinfo/swift-users <https://lists.swift.org/mailman/listinfo/swift-users>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160802/bc15f525/attachment-0001.html>
More information about the swift-evolution
mailing list