5

I want to set a default value to variable. But my Scala compiler says:

Error:(20, 16) unbound placeholder parameter
    val p: T = _
               ^

Here is the code.

object InverseFunctionsExample extends App {

  type D = Double

  def f(x: D): D = 5 * x + 10
  def g(x: D): D = 0.2 * x - 2

  printMessage(isInversible(f, g))

  def printMessage(inv: Boolean): Unit = {
    if (inv) print("YES!") else print("NOPE!")
  }

  def isInversible[T](f: (T) => T, g: (T) => T): Boolean = {
    val p: T = _
    if (f(p) == g(p))
      true
    else
      false
  }
}

Is it possible to initialize a val p with default value somehow?

barbara
  • 3,111
  • 6
  • 30
  • 58
  • 2
    If you know nothing about a type, how would you get a default value from it. – bmaderbacher Mar 23 '15 at 00:38
  • What would T be? You'd probably need a constraint of being Defaultable on T, and implement such a Trait. This is hard for the same reason why you can't initialize an instance of T, then use it in a class. – Carcigenicate Mar 23 '15 at 00:39
  • 2
    Just an observation here. You've defined f as the inverse of g. But your test doesn't check for this, you'd want `f(g(p)) == p` and for all p, not just a single value. – Lucas Mar 23 '15 at 00:57

3 Answers3

3

Only var fields (not local variables) can be initialized in this way. If you want to define "default values" for different types, the standard approach is the type-class pattern:

case class Default[T](value: T)

object Default {
  implicit val defaultInt: Default[Int] = Default(0)
  implicit val defaultString: Default[String] = Default("")
  ...
}

def isInversible[T](f: (T) => T, g: (T) => T)(implicit d: Default[T]): Boolean = {
  if (f(d.value) == g(d.value))
    true
  else
    false
  // or just f(d.value) == g(d.value)
}
Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487
1

You can use reflection to instantiate a new instance of a class, but that's probably not going to be very useful for you here:

class Foo
classOf[Foo].getConstructor().newInstance()

You can read about the reflection API to see you how you can pick a suitable constructor here.

You could also have a parameter that specifies how to instantiate a new instance:

def isInversible[T](f: T => T, g: T => T, def: => T) = f(def) == g(def)

Since this looks like an inherently math-oriented problem, you might be interested in the Numeric type, which can help facilitate this kind of logic generically for different number types. For example:

def intersectAtOrigin[T](f: T => T, g: T => T)(implicit n: Numeric[T]) = {
    val zero = n.zero
    f(zero) == g(zero)
}

And then you can do:

def f(x: D): D = 5 * x + 10
def g(x: D): D = 0.2 * x - 2
intersectAtOrigin(f, g) //false, working with Doubles
intersectAtOrigin[Int](_ + 1, x => x * x + x + 1) //true, working with Ints

You can read more about Numeric in the docs here.

Community
  • 1
  • 1
Ben Reich
  • 16,222
  • 2
  • 38
  • 59
  • just a small note: `Numeric` comes with a [`zero` method](https://github.com/scala/scala/blob/v2.11.4/src/library/scala/math/Numeric.scala#L205), so you don't need to do `fromInt(0)`; `n.zero` will suffice. – dhg Mar 24 '15 at 04:55
  • @dhg Great. Thanks for the note, I've updated the answer to include use of `zero`. – Ben Reich Mar 24 '15 at 12:38
0

You could pass in the value as a parameter of type T

def isInversible[T](f: (T) => T, g: (T) => T)(p: T): Boolean = {

    if (f(p) == g(p))
      true
    else
      false
  }

An example printMessage(isInversible(f, g)(10))

firephil
  • 830
  • 10
  • 18