odbhut.shei.chhele
odbhut.shei.chhele

Reputation: 6254

How to pass implicit value to a function?

I am new to scala. I am learning implicit variables. How can a pass an implicit variable to a function that calls another function that is gonna use that variable. I know this question seems stupid. Just look at the code that I have written.

class Person{

    def whoAmI(implicit name: String): Unit = {
        println(s"I am $name")
    }
}

class NewPerson{
    def whoAmI: Unit = {
        val p: Person = new Person
        p.whoAmI
    }
}

object Main extends App {
    implicit val name: String = "a Shamir"
    val person: NewPerson = new NewPerson
    person.whoAmI
}

This code doesn't work. But this does.

class Person{

    def whoAmI(implicit name: String): Unit = {
        println(s"I am $name")
    }
}

class NewPerson{
    implicit val name: String = "a Shamir"
    def whoAmI: Unit = {
        val p: Person = new Person
        p.whoAmI
    }
}

object Main extends App {
    val person: NewPerson = new NewPerson
    person.whoAmI
}

I want something like this.

class Person{

    def whoAmI(implicit name: String): Unit = {
        println(s"I am $name")
    }
}

class NewPerson{
    def whoAmI: Unit = {
        val p: Person = new Person
        p.whoAmI
    }
}

object Main extends App {
    implicit val name: String = "a Shamir"
    val person: NewPerson = new NewPerson
    person.whoAmI()(name)
}

Is it possible?

Upvotes: 1

Views: 3244

Answers (2)

flavian
flavian

Reputation: 28511

First of all you should pick a more refined type for implicits, having a primitive as an implicit is not very neat. A String or Int implicit is ALWAYS a bad idea in production code. Now you are learning so it's good to get used to this.

So let's say we have:

case class Name(name: String)

Now it's important to understand implicit propagation and forwarding. Implicits propagate through either inheritance or higher scope, so you either extend something that has the implicit you are looking for or you import it in a higher scope.

It's also best to define implicits in the secound group of function params, like this:

def test(p1: T1, p2: T2..)(implicit ev1: E1, ev2: E2): ReturnType = {}

This is because when you call the function whoAmI with parantheses, the compiler expects the implicit passed explicitly, which voids the very point of using implicits.

So when you write the whoAmI lik this:

def whoAmI(implicit name: Name): Unit

And you call like this: whoAmI() with the (), compiler is expecting you to pass the name manually. Implicits are "hidden", meaning that once defined they are meant to be "just there", so long as you abide scoping rules they are used to eliminate typing boilerplate.

class Person {

    def whoAmI()(implicit name: Name): Unit = {
        println(s"I am ${name.name}")
    }
}

class NewPerson {
    // Here your implicit is mising
    def whoAmI()(implicit name: Name): Unit = {
        val p: Person = new Person
        p.whoAmI
    }
}

object Main extends App {
    implicit val name: Name = Name("a Shamir")
    val person: NewPerson = new NewPerson
    // Now you don't actually need to manually type in the implicit
    person.whoAmI()
}

Upvotes: 5

Dmitry  Meshkov
Dmitry Meshkov

Reputation: 931

You should specify, that NewPerson.whoAmI takes implicit parameter and it'll be used in Person.whoAmI

 class Person {

    def whoAmI(implicit name: String): Unit = {
      println(s"I am $name")
    }
  }

  class NewPerson {
    def whoAmI()(implicit name: String): Unit = {
      val p: Person = new Person
      p.whoAmI
    }
  }

  object Main extends App {    
    implicit val name: String = "a Shamir"
    val person: NewPerson = new NewPerson
    person.whoAmI()(name)
  }

Upvotes: 1

Related Questions