[swift-evolution] A (better) Swift Equivalent For The Classical For-Loop With Numeric Scalars

Jonathan Tang jonathan.d.tang at gmail.com
Tue Mar 22 18:16:14 CDT 2016


On Mon, Mar 21, 2016 at 9:05 AM, ted van gaalen via swift-evolution <
swift-evolution at swift.org> wrote:

> Hello Taras
> Please take a look here:
> https://en.m.wikipedia.org/wiki/For_loop
>
> More than 30  !  programming languages since 1957 until now, have their
> implementation of the for-loop. If it was or is an inferior construct, it
> would have disappeared long ago. That alone proves that it is not inferior,
> but indeed very useful.
>
>
FWIW, a number of recent programming languages don't support it anymore.
Python, Ruby, and Rust all support the iterable form only, with a Range
object to represent a sequence of numbers.  It *is* disappearing, but it
takes 10+ years for a new programming language to get serious adoption, so
what's filtering its way down to mainstream programming is stuff that was
invented 20 years ago and played with by early-adopters 10 years ago.


> There is imho no longer any need to compare the for... variants any longer
> (but of course feel free to do so), because they both serve different
> purposes very well. Neither one or the other is inferior! I would protest
> with equal energy also when the for...in... was removed, because this would
> make iterating with collections cumbersome, e.g. I am now very happy that I
> can now iterate through an array, without specifying start, length and
> where we are..
>
> Concerning my intended proposal for a good alternative for the classicsl
> for-loop, I am currently in favor of very much something like this version,
> as it is implemented in Maple:
>   -----------start copy from wkpd page-----------------------------------
>
> Maple has two forms of for-loop, one for iterating of a range of values,
> and the other for iterating over the contents of a container. The value
> range form is as follows:
>
> *for* *i* *from* *f* *by* *b* *to* *t* *while* *w* *do*
>     *# loop body**od*;
>
> All parts except *do* and *od* are optional. The *for* *i* part, if
> present, must come first. The remaining parts (*from* *f*, *by* *b*, *to*
> *t*, *while* *w*) can appear in any order.
>
> Iterating over a container is done using this form of loop:
>
> *for* *e* *in* *c* *while* *w* *do*
>     *# loop body**od*;
>
> The *in* *c* clause specifies the container, which may be a list, set,
> sum, product, unevaluated function, array, or an object implementing an
> iterator.
>
> A for-loop may be terminated by *od*, *end*, or *end do*.
>
> ------------------------------end
> copy-------------------------------------------
> ( in the above example replace "do" and "od" by { } )
> Maple has two forms of for-loop, one for iterating of a range of values,
> and the other for iterating over the contents of a container.
> In Maple, which by the way is a very advanced programming language for
> mathematicians ( i am not), both variants are available and co-exist
> independently, which is exactly my point!  So again, it is not replacing or
> even changing the for-in as it is now available in Swift, both versions
> should be available. (This would still be the case if the for ;; had not
> been removed in the first place)
> To get back to the Maple for-loop implementation, in Swift I'd drop the
> "while" extension.
> To summarize:
>
> I would like to see in Swift:
>
>      for v from v1 to v2 by v3  {...}
>
> for numerical values Int, Double, Float...
> The "by" clause would be optional: when omitted, it should
> default to 1 for integers and 1.0 for floating point values.
>
> The loop variable ("v" here) cannot be altered in the loop.
> The loop can exited with the "break" statement.
> Use "continue" to directly go to the next iteration( if any)
> ("break" and "continue" functional as it is now)
>
>
> Examples:
>      for v from 0.5 to 30.0 by 0.3
>      for v from 0 to 100 by 5
>      for v from 12.0 to -10.0 by -2
>
> Imho, this is super clean and very readable, Why would anyone have
> objections against it? Also the compiler can optimize this construct very
> easely.
> Yes, the classical for ;; had more options, but are they still needed?
>
>
Curious, would you have any objections if 'by' were a method on ranges,
which already exist in Swift?

for v in 0.5...30.0.by(0.3)
for v in 0...100.by(5)
for v in 12.0...-10.0.by(-2)

The advantage of using range objects instead of special syntax is that then
they're composable with all functions that operate on iterables.  You can,
for example get all primes from 0 to 100 with 0...100.filter(isPrime), or
retrieve the last 5 with such elements with
0...100.filter(isPrime).suffix(5).

I also liked the idea Brent proposed up-thread of having stride() take a
by: parameter that could be an arbitrary function of the last element.
That's very similar to 'unfold' in Haskell, which turns out to be very
useful for constructing arbitrary sequences in a memory-efficient way.


> Note that we also have discussed the floating point number tolerance
> problem previously.
> the for ... from ... to ... by ... could therefore for floating point
> numbers perhaps be enhanced like so:
>
>      for v from 0.0 to 10.0 by 0.1 tolerance 0.01     // tolerance
> optional clause
>
> so that it reaches the end value 10.0 in this case
>
> (I am not in favor to automatically set tolerance based upon magnitude)
>
> To summarize:
>
> 1. the existing for ... in ...  which is nearly perfect for collections
> can remain as is. No conflicts here. There is no need to drop one for the
> other, they are completely independent.
>
> 2. The new for ... from ... to ... by ... is simple,straightforward and
> easy to implement.
>
> You've mentioned this:
>
> for (i,j,k) in matrix.indices {...}
>
> but here we are working with collection (descendants), are we?
>
> I'd kindly recommend us all to travel much to other programming worlds,
> because there are so many (often forgotten) very interesting aspects and
> ideas that can be very useful to implement in new languages.
>
> Kind Regards
> TedvG
>
> On 21 Mar 2016, at 14:30, Taras Zakharko <taras.zakharko at uzh.ch> wrote:
>
> To be honest, I have difficulty understanding the premise of this
> discussion. I have always found the C-style  for(;;) loop an awkward
> construct, because it is essentially just an alternative form of writing a
> general-purpose while loop.  It is perfectly reasonable to restrict the for
> construct to, well, ‘for’ contexts: iterating through a sequence of items.
> If you need something more complex, either write your own iterator or use a
> general-purpose while loop.
>
> As discussed previously, an optimising compiler generates the same machine
> code whether you are using an iterator abstraction or low-level coding.
> Besides, the for .. in .. construct potentially offers more potential for
> optimisation, because it makes the counter variable as well as the
> semantics of the entire loop more explicit (a for(;;) can contain arbitrary
> stuff). Talking about numerical algorithms: this is something I can’t
> understand at all. I have been working with numerical algorithms in Python
> and R for years, and I have never ever missed the C-style for loop. These
> languages offer convenient functions for generating iterable sequences,
> which are more readable and also represent the loop  semantics much better
> then the for(;;;). Not to mention that the iterator pattern allows you to
> write simpler and more maintainable code. Imagine iterating through a
> sparse matrix or something. With a proper iterator pattern you just do:
>
> for (i,j,k) in matrix.indices {
>
> }
>
> With a for(;;) loop you’l probably end up writing a nested construct of
> quite some complexity.
>
> Swift could certainly use some improvements to its iterators (for example
> something like Python generator expressions might be useful), but that is a
> different topic.
>
> To sum it up:
> - for(;;) is an awkward construct which is closer to a while loop than an
> actual sequence iterator pattern (that it should be)
> - a proper iterator pattern is more convenient, more readable and offers
> the same performance
> - numerical code does not need a for(;;) construct, in fact, using the
> proper iterator pattern makes writing numeric code easier, not more
> difficult, because you can abstract away some common processing/aggregating
> steps easily, and without any drawback
> - we should think about how to improve the iterators offered by Swift
> standard library, not go back to an inferior construction
>
> — Taras
>
>
>
> On 21 Mar 2016, at 12:37, Greg Parker via swift-evolution <
> swift-evolution at swift.org> wrote:
>
>
> On Mar 19, 2016, at 12:46 AM, Dmitri Gribenko via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> Hi Ted,
>
> Thank you for starting this thread.  I agree that removing the C-style
> for loop has degraded the readability and clarity of some of numerics
> code.
>
> In the feedback to SE-0007 many people have said that they can convert
> their code to for-in loops, but I think this actually means that in
> code that is typically written in Swift today, loops primarily operate
> on sequences and collections.  It means that numerics is a domain that
> not many people work in.  But it is a very important domain
> nevertheless, and clarity for numerics code matters at least as much
> as it does everywhere else.
>
> I think one way to approach this discussion would be to present
> multiple concrete code samples that contain C-style for loops and are
> awkward to write without them.  We can then try looking for patterns,
> generalize and simplify, and discuss possible solutions.
>
>
> Let me emphasize this more strongly. *Concrete*, *real-world* examples are
> quite likely the only way that you are going to get `for(;;)` back or get
> any sort of semantically-similar syntactically-different replacement.
>
> There have been lots of suggestions. None of them are perfect. If we
> assume that there is in fact no perfect solution then the only way to
> proceed is to provide sufficient justification for some imperfect solution.
>
> I'm still waiting for something like this: "We ported our code to Swift 3.
> Here are 5 reasonable-looking for(;;) loop shapes from 150 call sites, and
> here are their ugly-looking rewrites."
>
> (Personally I think removing for(;;) without direct replacement was too
> aggressive. That view lost. Now its advocates will need to do more work to
> upend the status quo.)
>
>
> --
> Greg Parker     gparker at apple.com     Runtime Wrangler
>
>
> _______________________________________________
> 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
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160322/c78b2f1a/attachment.html>


More information about the swift-evolution mailing list