0

I've been trying to enhance my knowledge with scala. I am trying to implement this function recursively but having difficulty.

enter image description here

My main question IS, how can you accept a list in the parameter that accepts either a list or numbers.

5
  • List[Any] would go. Commented Oct 18, 2015 at 0:44
  • This is what I have so far but it is not working. def depth(l: List[Any]) : Int = { for (i <- l){ i match { case list: List[Any] => 1 + depth(list) } } Commented Oct 18, 2015 at 1:29
  • 1
    And that would not be. for (i <- l) {} gives you Unit and not Int as you intended. To take results out from for expression you need to yield them Commented Oct 18, 2015 at 1:33
  • Im so confused @ayvango Commented Oct 18, 2015 at 1:41
  • for {x <- collection} f(x) is syntax sugar for the foreach function in scala-lang.org/files/archive/nightly/docs/library/… . Its signature is def foreach[U](f: (A) ⇒ U): Unit. So it returns Unit but you need to get Int somehow Commented Oct 18, 2015 at 1:45

4 Answers 4

3

depth(x: Any): Int is the signature you want, then pattern match on x to determine if it's a List[_] or not, where _ indicates you don't care what's in the list. (Using Seq[_] would be the more idiomatic Scala type to use, actually.) Note that the example shown is missing a pair of parens, List(1, 2, List(3))... It also assumes that depth(8) == 0 (for example).

A tricky part is that you shouldn't assume that a nested list will either be the first or last element in the "parent" list, i.e., ...List(1,List(2,3),4)... is possible.

A final bit worth mentioning; if you were building a "production" depth method, it would be worth having a Tree abstraction with Node and Leaf concrete types so you can use a better type signature, depth(tree: Tree[_]): Int, to make it explicitly clear when something represents part of the tree structure vs. data in the tree. Using List here is convenient for the exercise, but a bit ambiguous otherwise, since you could have a tree of stuff where some nodes are actually lists.

Sign up to request clarification or add additional context in comments.

1 Comment

oh, yes. Kill him with catamorphism abstraction
1

I will try to answer this by giving a shot on the recursive solution:

def depth(listOrNum: Any): Int = {
  def help(y: Any, c: Int): Int = {
    y match {
      case y: Int => c
      case List(curHead, rest @ _*) =>
        Math.max(help(curHead, c+1), help(rest, c))
      case _ => 0
    }
  }
  help(listOrNum, 0)
}

Comments

1

collect is handy here:

def depth(xs: List[Any]): Int =
  1 + xs.collect{case xs: List[_] => depth(xs)}
        .foldLeft(0)(_ max _)

P.S. I agree with Dean's comments about the type List[Any] being a poor way to represent trees. List[Any] is a type that should never appear in ordinary Scala code, so I'm sad to see it used in an exercise intended for beginners.

Comments

0

If you are insisting on using for comprehension, I can provide implementation that works with it.

First you define two useful classes

import scala.collection.generic.CanBuildFrom
import scala.collection.mutable.Builder

class Folder[T](init : T, step : (T,T) => T) extends Builder[T,T] {
  private[this] var state = init
  override def += (elem : T) = {
    state = step(state, elem)
    this
  }
  override def clear() {
    state = init
  }
  override def result() : T = state
}

class CanBuildFolder[F,T](init : T, step : (T,T) => T) extends CanBuildFrom[F,T,T] {
  override def apply() : Builder[T,T] = new Folder(init, step)
  override def apply(from : F) : Builder[T,T] = new Folder(init, step)
}

than you can use them with the for comprehension

import scala.math.max

object Test {
  val example = List(1, List(2, 3), List( List(4, 5), 6, List(7, List(List(8), 9))))
  implicit val maxFolder = new CanBuildFolder[List[Any], Int](0, max)

  def depth(source : List[Any]) : Int =
    for (x <- source) yield x match {
      case l : List[Any] => depth(l) + 1
      case _ => 1
    }

  assert(depth(example) == 5)
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.