1
\$\begingroup\$

I have just picked up Scala like 2 hours ago, and I am thinking of printing a series like 1 to 10 but in a recursive fashion. I do not understand what is wrong with this:

def printSeries(x:Int):Int = {
  if(x==0) doNothing() else doSomething()

  def doNothing()  = {}

  def doSomething() = {
    println(x)
    printSeries(x-1)
  }

}

Sorry, this might be very basic. Please point out my mistakes or any alternative and simpler implementation. (I do not want to use loops).

Thanks,

\$\endgroup\$

migrated from stackoverflow.com Apr 7 '13 at 8:41

This question came from our site for professional and enthusiast programmers.

  • 3
    \$\begingroup\$ Unrelated but maybe of interest to you, Coursera just started a class on Scala last week taught by Martin Odersky (the creator of Scala): link \$\endgroup\$ – Nathan Bouscal Apr 6 '13 at 19:01
  • 1
    \$\begingroup\$ ^ And I just finished the lecture videos for Week 2. Such an awesome instructor he is. \$\endgroup\$ – Vaibhav Desai Apr 6 '13 at 19:03
  • \$\begingroup\$ Thanks Nathan for the coursera link. Will definitely check it out. \$\endgroup\$ – aryan Apr 6 '13 at 19:16
5
\$\begingroup\$

First of all, you are promising to return Int from printSeries. Why? If method is printing, isn't much more natural* to make it return Unit (aka void). This is usually can be done either explicitly

def printSeries(upTo: Int): Unit = { .... } 

or implicitly:

def printSeries(upTo: Int) { .... } 

(see, no equals sign in code above).

Next, why do you have explicit doNothing method? I think it would be better to write something like:

def printSeries(upTo: Int) {
  if(upTo > 0) {
    println(upTo)
    printSeries(upTo - 1)
  }
}

You also might want to place @tailrec annotation to ensure that code will be optimized and won't fail with Stackoverflow at big upTo numbers (if it will and function is annotated compiler will yell on you).

@annotation.tailrec
def printSeries(upTo: Int) {
  if(upTo > 0) {
    println(upTo)
    printSeries(upTo - 1)
  }
}

Finally, generally, it is better to produce sequences and only then make something with them.

P.S. you might better to post questions like this on code review site, not on stackoverlow itself

* there is a good rule in programming to make functions do one thing and be good at it so getXandMakeY usually is bad idea.

\$\endgroup\$
  • \$\begingroup\$ Thanks @om-nom-nom, I did not know about Unit. Also thanks for the code review web site link. I did not know about that. \$\endgroup\$ – aryan Apr 6 '13 at 19:14
1
\$\begingroup\$

Because your method signature is Int => Int, your method expects to return an Int. You might have wanted to define it like def printSeries(x:Int):Unit = { sot that it does not need to return something.

Besides, you can do it with the following shorter function

def printSeries(x:Int):Unit= {
  if(x>0) {
    println(x)
    printSeries(x-1)
  }
}

Other alternatives using val and pattern matching at the same time.

val printSeries: (Int)=> Unit = _ match {
   case x if x>0 =>
     println(x)
     printSeries(x-1)
   case _ =>
}

Another alternative using anonymous function

val printSeries: (Int)=> Unit = { x =>
   if(x>0) {
     println(x)
     printSeries(x-1)
   }
}
\$\endgroup\$
  • \$\begingroup\$ I think pattern matching here is kinda harmfull. \$\endgroup\$ – om-nom-nom Apr 6 '13 at 19:06
  • \$\begingroup\$ Because it concerns integers, yes, But this can be generalized for other cases. \$\endgroup\$ – Mikaël Mayer Apr 6 '13 at 19:08
  • \$\begingroup\$ ...can be generalized for other cases \$\endgroup\$ – om-nom-nom Apr 6 '13 at 19:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy