Idiomatic way to "loop until"

2,540 views
Skip to first unread message

Andreas Joseph Krogh

unread,
Jun 24, 2013, 3:57:28 AM6/24/13
to scala...@googlegroups.com
What is the most idiomatic way to do this in Scala?
val l = List(1,2,3,4)
val i = l.iterator
var cont = true
while (i.hasNext) {
        val k = i.next()
        if (isValid(k)) {
                val result = doStuff(k)
                if (result.stopProcessing) {
                        cont = false
                }
        }
}
I know takeWhile exists but I don't need to return anything.
 
Thanks.
 
--
Andreas Joseph Krogh <and...@officenet.no>      mob: +47 909 56 963
Senior Software Developer / CTO - OfficeNet AS - http://www.officenet.no
Public key: http://home.officenet.no/~andreak/public_key.asc

Dennis Haupt

unread,
Jun 24, 2013, 4:02:23 AM6/24/13
to Andreas Joseph Krogh, scala...@googlegroups.com
make a method out of your code and attach it to all collections via implicits :)
or:
list.view.takeWhile(...).foreach(...)
 
Gesendet: Montag, 24. Juni 2013 um 09:57 Uhr
Von: "Andreas Joseph Krogh" <and...@officenet.no>
An: scala...@googlegroups.com
Betreff: [scala-user] Idiomatic way to "loop until"
--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Dennis Haupt

unread,
Jun 24, 2013, 4:20:38 AM6/24/13
to Dennis Haupt, Andreas Joseph Krogh, scala...@googlegroups.com
you can also foreach & break out of it
 
Gesendet: Montag, 24. Juni 2013 um 10:02 Uhr
Von: "Dennis Haupt" <h-s...@gmx.de>
An: "Andreas Joseph Krogh" <and...@officenet.no>
Cc: scala...@googlegroups.com
Betreff: Aw: [scala-user] Idiomatic way to "loop until"

Lanny Ripple

unread,
Jun 28, 2013, 8:04:28 PM6/28/13
to scala...@googlegroups.com
I would do

  List(1,2,3,4,5)
    .iterator
    .takeWhile(isValid(_))
    .map{doStuff(_)}
    .takeWhile(!_.stopProcessing)
    .foreach{_ => ()}

The clunky foreach{} is in case your doStuff() uses a lot of resources and trying to force the iterator with .toList would overflow something.

Your code works just fine though.  Put it all behind a def and forget about it.

  def foreachWithStop[A,B](xs: Iterable[A], trans: A => B, stopWhen: B => Boolean)

Alexandru Nedelcu

unread,
Jul 2, 2013, 11:20:29 AM7/2/13
to Andreas Joseph Krogh, scala-user

On Mon, Jun 24, 2013 at 10:57 AM, Andreas Joseph Krogh and...@officenet.no wrote:

What is the most idiomatic way to do this in Scala?

Here's another version:

@tailrec
def loop(l: List[Int]) {
  val cont = l match {
    case head :: tail if isValid(head) =>
      !doStuff(head).stopProcessing
    case head :: tail =>
      true
    case Nil =>
      false
  }

  if (cont) loop(l.tail)
}


Alexandru Nedelcu
https://bionicspirit.com

Andreas Joseph Krogh

unread,
Jul 2, 2013, 11:47:31 AM7/2/13
to scala...@googlegroups.com
Nice, thanks!

Josh Suereth

unread,
Jul 2, 2013, 8:15:41 PM7/2/13
to Andreas Joseph Krogh, scala-user
Perhaps a simpler version....

list.iterator takeWhile isValid takeWhile (x => !doStuff(x).stopProcessing)


*or* a more familiar syntax..

list.iterator.takeWhile(isValid).takeWhile(x => !doStuff(x).stopProcessing)


*OR* maybe lazier?

list.iterator takeWhile { x =>
  isValid(x) && !doStuff(x).stopProcessing
}



Hope that helps :)

- Josh


--

Alexandru Nedelcu

unread,
Jul 3, 2013, 2:23:31 AM7/3/13
to Josh Suereth, Andreas Joseph Krogh, scala-user
On Wed, Jul 3, 2013 at 3:15 AM, Josh Suereth <joshua....@gmail.com> wrote:
list.iterator takeWhile { x =>
  isValid(x) && !doStuff(x).stopProcessing
}

In his example, the loop does not break on the first isValid(x) that fails.
The loop simply skips all invalid items, until it finds one that isValid but that wants to stopProcessing.

--
Alexandru Nedelcu
https://bionicspirit.com

Josh Suereth

unread,
Jul 3, 2013, 10:26:00 AM7/3/13
to Alexandru Nedelcu, Andreas Joseph Krogh, scala-user
Ah, my bad.  Had misread.  SO then:

list.iterator filter isValid takeWhile { x =>
  !doStuff(x).stopProcessing

Josh Suereth

unread,
Jul 3, 2013, 10:27:23 AM7/3/13
to Alexandru Nedelcu, Andreas Joseph Krogh, scala-user
Also, technically the original loop (as written) just goes through everything in the iterator, since done doesn't show up in a condition.  I assume he wanted early exit by the description.

Alexandru Nedelcu

unread,
Jul 3, 2013, 11:40:10 AM7/3/13
to Josh Suereth, Andreas Joseph Krogh, scala-user
On Wed, Jul 3, 2013 at 5:27 PM, Josh Suereth <joshua....@gmail.com> wrote:
Also, technically the original loop (as written) just goes through everything in the iterator, since done doesn't show up in a condition.

I've missed that too :-) I also misread "cond" as an early exit.

Reply all
Reply to author
Forward
0 new messages