1

Question

Is there a way to define the insert function inside the makeOrderedLeafList match block?

Problem

Since insert function is only used in makeOrderedLeafList, I would like to define it inside it. However, if placed at the bottom, an error "Unit required". Cannot place at the top as "case" is being expected.

def makeOrderedLeafList(freqs: List[(Char, Int)]): List[Leaf] = freqs match {
    case List() => List()
    case h :: t => insert(h, makeOrderedLeafList(t))
    case _      => throw new IllegalStateException
}

//--------------------------------------------------------------------------------
// Insert Leaf in the sorted list of Leaf.
//--------------------------------------------------------------------------------
def insert(c: (Char, Int), list: List[Leaf]): List[Leaf] = list match {
    case List() => List(new Leaf(c._1, c._2))
    case h :: t => {
        //--------------------------------------------------------------------------------
        // If C:[char, counter] is smaller, prepend it to the List[Leaf].
        // Otherwise, recurse call insert to find a position in the tail of the list.
        //--------------------------------------------------------------------------------
        if (c._2 <= h.weight) new Leaf(c._1, c._2) :: list
        else h :: insert(c, t)
    }
}
4
  • 1
    Of course, it's possible. Not for you? Could show your code with error or something like that? Commented Aug 12, 2016 at 8:18
  • 1
    Its better to define the insert function as it is defined now. If you define it inside the match call it will redefine this function every time you will use your makeOrderedLeafList function. Commented Aug 12, 2016 at 8:22
  • @SarveshKumarSingh No, it won't. It'll generate basically the same code, except insert will be private and likely name-mangled. Commented Aug 12, 2016 at 8:47
  • It will... look at my answer Commented Aug 12, 2016 at 9:34

2 Answers 2

3

Just place it inside the case before calling it:

scala> "hello" match {
 | case "hel" => 1
 | case "hello" =>
 |   def f(i: Int): Int = {
 |     i * 2
 |   }
 |   f(3) // don't forget to call the function...
 | }
res0: Int = 6

The right-hand side of a case expression can be any code block that returns the expected type. A code block can contain function definitions.

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

Comments

0

If you define you function inside the outer function call, it will create a new instance of inner function on every call of outer function.

val getInnerFuncHash = () => {
  val func = (x: Int) => x + 1
  func.hashCode().toString
}

println(getInnerFuncHash())
println(getInnerFuncHash())
println(getInnerFuncHash())

this will print the hashCodes for the inner functions, and will output something like,

1136974570
1030088901
2115208183

which means every call to outer function will create a new instanc eof inner function.

The same thing happens in case of defs

def getInnerFuncHash(): String = {
  val func = (x: Int) => x + 1
  func.hashCode().toString()
}

println(getInnerFuncHash())
println(getInnerFuncHash())
println(getInnerFuncHash())

2 Comments

But insert is not a function, it's a method (even though the OP used the wrong term in the question).
Yes... that works in case of def because of a peculiar trick used by scala compiler - stackoverflow.com/a/2482410/1151929

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.