Search code examples
scalaeta-expansion

Calling an anonymous function inside a map method


I was making a constructor with multiple possible arguments, when I realized my IDE was pointing out a type discrepancy:

  case class PathAndColumns(path: String, column: Array[Column]) {

  def this(path: String, column: Column) {
    this(path, Array(column))
  }

  def this(path: String, column: String) {
    this(path, column.split(",").map( _ => col(_))) // : Array[String=>Column]
  }

So I tried just passing the col function.

  def this(path: String, column: String) {
    this(path, column.split(",").map(col)) // I work!
  }

It works, and then, trying to understand why, I ended up with:

  def this(path: String, column: String) {
    this(path, column.split(",").map(letsSee)) // I work as well
  }

  def letsSee(myStringCol: String): Column = {
    (() => col(myStringCol))() // A pair of extra parenthesis to simulate a call
  }

So I found out that passing an anonymous function to methods like map doesn't return the result, but rather the whole function (because it's treated as an object I suppose).

So how do I make this work in order to get a Column rather than the function type, without declaring it separatedly?

  def this(path: String, column: String) {
    this(path, column.split(",").map(_ => {
      col(_)
    }))
  }

Solution

  • The simple answer is that you replace

    _ => col(_)
    

    with

    x => col(x)
    

    The problem is that you are treating _ is a normal variable identifier, but it isn't. The two uses of _ in the first expression are completely independent.

    The first _ is a placeholder for the argument to an anonymous function. The syntax _ => ... means that you are defining a function but will not use the argument to that function when calculating the result.

    The second _ is a placeholder for the argument to col. The syntax col(_) turns the method col into a free function.