Rylander
Rylander

Reputation: 20169

Method signature for a function with default values

In Scala, is there a way to specify that a function should have default parameter values declared?

For example, in the code below, is there a way to specify in the signature of indirectHelloName that the provided function must provide a default value for the second parameter?

def helloName(name: String, greating: String = "hello"): Unit = { 
  println(s"$greating $name")
}

def indirectHelloName(name: String, function: (String,String) => Unit): Unit = {
  if (name == "Ted") {  
    function(name, "Custom Greeting for Ted!")
  } else {
    function(name) //This would use the default value for the second argument.
  }
}

Upvotes: 5

Views: 490

Answers (3)

Jörg W Mittag
Jörg W Mittag

Reputation: 369526

In Scala, is there a way to specify that a function should have default parameter values declared?

For example, in the code below, is there a way to specify in the signature of indirectHelloName that the provided function must provide a default value for the second parameter?

A function cannot have an optional parameter with default argument, therefore there is no way to specify one:

val f = (a: Int, b: Int) => a + b
//⇒ f: (Int, Int) => Int = $$Lambda$1073/0x000000080070c840@6cd98a05

val g = (a: Int, b: Int = 5) => a + b
// <console>:1: error: ')' expected but '=' found.
//        val g = (a: Int, b: Int = 5) => a + b
//                                ^

val h = new Function2[Int, Int, Int] { 
  override def apply(a: Int, b: Int) = a + b
}
//⇒ h: (Int, Int) => Int = <function2>

val i = new Function2[Int, Int, Int] {
  override def apply(a: Int, b: Int = 5) = a + b
}
//⇒ i: (Int, Int) => Int{def apply$default$2: Int @scala.annotation.unchecked.uncheckedVariance} = <function2>

i(3, 5)
//⇒ res: Int = 8

i(3)
// <console>:13: error: not enough arguments for method apply: (v1: Int, v2: Int)Int in trait Function2.
// Unspecified value parameter v2.
//        h(3)
//         ^

Upvotes: 2

jwvh
jwvh

Reputation: 51271

One thing you could do is move the default value from the parameter list to inside the method.

def helloName(in :String*) :Unit =
  println(in.lift(1).getOrElse("hello") + ", " + in.head)

def indirectHelloName(name: String, function: (String*) => Unit): Unit =
  if (name == "Ted") function(name, "Custom Greeting")
  else               function(name) //use default

usage:

indirectHelloName("Ted", helloName)  //Custom Greeting, Ted
indirectHelloName("Tam", helloName)  //hello, Tam

Upvotes: 3

user51
user51

Reputation: 10213

I tried and come up with the below answer

    def helloName(name: String, greeting: String = "hello"): Unit = {
        println(s"$greeting $name")
    }

    val helloNameFn = (x: String, y :String) =>  println(x + y)

    type fn = (String, String) => Unit

    def indirectHelloName(name: String, function:fn = helloNameFn): Unit = {
        if (name == "Ted") {
        function(name, "Custom Greeting for Ted!")
        } else {
        helloName(name) //This would use the default value for the second argument.
        }
    }

    helloNameFn("123", "123")

Please try and let me know your comments.

Upvotes: 0

Related Questions