4

I recently started learning Scala and came across currying. From an answer in this post, this code snippet

def sum(a: Int)(b: Int) = a + b

expands out to this

def sum(a: Int): Int => Int = b => a + b

Then I saw a snippet from scala-lang, which shows it's possible to write something like this to emulate a while loop

  def whileLoop (cond : => Boolean) (body : => Unit) : Unit = {
      if (cond) {
          body
          whileLoop (cond) (body)
      }
  }

Out of curiosity, I tried to expand this out, and got this

  def whileLoop2 (cond : => Boolean) : (Unit => Unit) =
      (body : => Unit) =>
          if (cond) {
              body
              whileLoop2 (cond) (body)
          }

But there seems to be some syntax that I'm missing because I get an error

error: identifier expected but '=>' found.
(body : => Unit) => 
        ^

What is the proper way to expand out the emulated while loop?

Community
  • 1
  • 1
azelo
  • 129
  • 2
  • 6

1 Answers1

6

The tricky part is dealing with the parameterless function or "thunk" type => Unit. Here is my version:

def whileLoop2 (cond: => Boolean): (=> Unit) => Unit =
  body =>
    if (cond) {
      body
      whileLoop2 (cond)(body)
    }

var i = 5
val c = whileLoop2(i > 0)
c { println(s"loop $i"); i -= 1 }

It appears that you can annotate the return type with (=> Unit) => Unit, but you cannot annotate (body: => Unit), so you have to rely on the type inference here.

0__
  • 66,707
  • 21
  • 171
  • 266
  • Is it possible change this solution such that i can write whileLoop2 (i > 0) { println "..." } instead of whileLoop2(i > 0) { () => println "..." } ? The example in the scala-lang page doesn't have the extra () => bit when using their emulated while loop. – azelo Sep 29 '14 at 21:38
  • Sorry, it _is_ possible to use parameterless function arguments. See my edited version. – 0__ Sep 29 '14 at 21:50