[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