deamon
deamon

Reputation: 92387

Initialize class parameter with a function in Scala

Is it possible to initialize a class parameter with a function in Scala?

Example:

def square(x: Int) = x*x

class Foo(val x: Int = square(x))

This doesn't compile but I hope you get the idea.

Upvotes: 1

Views: 1347

Answers (4)

Ben James
Ben James

Reputation: 125139

Hard to guess what you're trying to achieve, but let me have a go:

class Foo private (val x: Int)

object Foo {
  def apply(x: Int) = new Foo(square(x))
}

Note that if you try this in the REPL, you must enter both the class and its companion object at the same time (in paste mode, via :pa), or the object Foo won't have access to the private class constructor.

This applies the square function to the parameter x before creating a Foo instance:

scala> Foo(3).x
res1: Int = 9

Upvotes: 4

Shrey
Shrey

Reputation: 2404

Here it is.. you can initialize a class with a function ! :)

  class Foo(f : Int => Int)

  def square(x : Int) = x*x                     

  val foo = new Foo(square)

Or Probably you must be looking for this.

  class Foo(f : Int => Int, _p1 : Int){
   val p1 = f(_p1)
  }

  def square(x : Int) = x*x                       //> square: (x: Int)Int
  def add2(x : Int) = x+2                         //> add2: (x: Int)Int

  val fooSqr = new Foo(square,5)                  
  fooSqr.p1                                       //> res0: Int = 25

  val fooAdd2 =  new Foo(add2,5)                 
  fooAdd2.p1                                      //> res1: Int = 7

Upvotes: 1

Malte Schwerhoff
Malte Schwerhoff

Reputation: 12852

This is not possible because you try to calculate x based on x (without having any kind of base case). You could do the following:

class Foo(_x: Int) {
  val x = square(_x)
}

println(new Foo(10).x) // 100


EDIT

You could also generalise this and implicitly pass a function to the class constructor that transforms x:

implicit val square = (x: Int) => x*x

class Foo(private val _x: Int)(implicit f: Int => Int) {
  val x = f(_x)
}

println(new Foo(10).x) // 100

This unfortunately doesn't compile as-is (Scala 2.9.2, 2.10.0), because there is another implicit in scope (Predef.conforms). I don't know how to overcome this ambiguity, but it should certainly be possible.

Upvotes: 3

Johannes Luong
Johannes Luong

Reputation: 584

In general you can use arbitrary expressions when defining the default value (source).

Your problem is that you can not use x on the right hand side of the initialization, because x is probably neither declared nor initialized at that point.

Upvotes: 0

Related Questions