[swift-evolution] Feature proposal: Range operator with step

Ted F.A. van Gaalen tedvgiosdev at gmail.com
Wed Apr 6 16:45:36 CDT 2016


Hi Milos

Yes,  (v1…v2).by(v3)  it can determine the going of either in  + or - direction,
but only at run time! because the contents of v1, v2, v3 are of course unknown at compile time. 
Ergo: it cannot expected be an absolute value.

however, I suggested (coded) that here on 4.3.2016…  Works in Playground Xcode 7.3
look in the struct its “init”   where the direction is determined
by wether “from” or “to” is bigger” 
implemented like this  (and also with a floating point number tolerance)
(The struct should be numerical generic, but I didn’t manage to change it to generic,) 
Anyway, should be compilerized/hand coded in asm perhaps (I can’t do that)

TedvG

public struct StriderGenerator : GeneratorType
{
    private let low: Double
    private let high: Double
    private var step : Double
    private var tol  : Double

    private var iterator  = 0

    private let moveForward: Bool
    
    private var done  = false
        
    
    public init(from: Double, to: Double, by: Double, tolerance: Double)
    {
        step = by
        if from < to
        {
            low  = from
            high = to
            moveForward = true
        }
        else
        {
            low  = to
            high = from
            moveForward = false
        }
        self.tol   = tolerance * 0.5  // center it.
    }
    
    /// return next value or nil, if no next
    /// element exists.
    
    public mutating func next() -> Double?
    {
        let current:Double
        if done
        {
            return nil
        }
        
        if moveForward
        {
            current = low + Double(iterator) * step
        }
        else
        {
            current = high - Double(iterator) * step
        }
        iterator += 1
        
        
        // done if exceeding low or high limits + tolerance
        
        done = current > high   + tol  ||
               current < low    - tol
        
        if done
        {
            return nil
        }
        else
        {
            return current
        }
    }
}

public struct Strider : SequenceType   // Aragorn
{
    private let start:  Double
    private let end:    Double
    private let step:   Double
    private let tol:    Double

    init(from: Double, to: Double, by: Double, tolerance : Double)
    {
        _precondition(by > 0.0 ,
            "Init of struct Strider: 'by:...' value must be > 0.0.")
        _precondition(abs(by) > tolerance,
            "Init of struct Strider: 'by:...' value must be > tolerance.")
        _precondition(tolerance >= 0.0,
            "Init of struct Strider: tolerance:... value must be >= 0.0")
        
        start = from
        end   = to;
        step  = by
        tol   = tolerance
    }
    
    /// Return a *generator* over the elements of this *sequence*.
    
    public func generate() -> StriderGenerator
    {
        return StriderGenerator(from: start, to: end, by: step, tolerance:  tol)
    }
}

public extension Double
{
    
    public func strider(to to: Double, by: Double, tolerance: Double ) -> Strider
    {
        return Strider( from: self, to: to, by: by, tolerance: tolerance)
    }
}

print("Testing the new .strider extension")

let testvalues =
[
    // fr:     to:     by:   tolerance:
    [ 0.0,     5.0,    1.0,    0.0 ],
    [-3.0,     4.0,    0.12,   0.1 ],
    [ 2.0,    -1.0,    0.34,   0.1  ],
    [ 0.001,  -0.002,  0.0001, 0.00001 ]
]

for parm in testvalues
{
    
    print("==============Stride from: \(parm[0]) to: \(parm[1]) by: \(parm[2]) tolerance: \(parm[3])\n")
    
    for val in parm[0].strider(to: parm[1], by: parm[2], tolerance: parm[3])
    {
        print("\(val) ", terminator:"")
    }
    print("\n\n")
}




TedvG



> On 06.04.2016, at 23:15, Milos Rankovic <milos at milos-and-slavica.net> wrote:
> 
> Hi Ted,
> 
>> that would imply the ‘by”value should/must always be an absolute value?
> 
> 
> In a way: Instead of `Strideable.Stride` I would suggest `Strideable.Distance`.
> 
> At any rate, leaving the sign to be direction indicator makes it forever necessary for everyone to make this counterintuitive metal gymnastics, since most of the time in life we do not walk backwards, even when we are returning back whence we came from!
> 
> What do you think?
> 
> milos
> 
> 
>> On 6 Apr 2016, at 21:34, Ted F.A. van Gaalen <tedvgiosdev at gmail.com <mailto:tedvgiosdev at gmail.com>> wrote:
>> 
>> Hello Milos,
>> Good question
>> was thinking about this too.
>> that would imply the ‘by”value should/must always be an absolute value?
>> however (if it is a var) it cannot be guaranteed to be + or - 
>> that’s why I thought to leave it as is.
>> ?
>> TedvG
>> 
>>> On 06.04.2016, at 22:18, Milos Rankovic <milos at milos-and-slavica.net <mailto:milos at milos-and-slavica.net>> wrote:
>>> 
>>> 
>>>> On 6 Apr 2016, at 21:08, Ted F.A. van Gaalen via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>>> 
>>>> v1 >  v2:   is allowed and correctly evaluated.  e.g. (8.0…-3.14159).by(-0.0001) 
>>> 
>>> If the range does not assume `start >= end`, is it still necessary to also indicate the traversal direction with the sign of the step (`-0.0001`)?
>>> 
>>> milos
>> 
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160406/5a0c965a/attachment-0001.html>


More information about the swift-evolution mailing list