Question

I have a case class which takes a list of functions:

case class A(q:Double, r:Double, s:Double, l:List[(Double)=>Double])

I have over 20 functions defined. Some of these functions have their own parameters, and some of them also use the q, r, and s values from the case class. Two examples are:

def f1(w:Double) = (d:Double) => math.sin(d) * w
def f2(w:Double, q:Double) = (d:Double) => d * q * w

The problem is that I then need to reference q, r, and s twice when instantiating the case class:

A(0.5, 1.0, 2.0, List(f1(3.0), f2(4.0, 0.5))) //0.5 is referenced twice

I would like to be able to instantiate the class like this:

A(0.5, 1.0, 2.0, List(f1(3.0), f2(4.0))) //f2 already knows about q!

What is the best technique to accomplish this? Can I define my functions in a trait that the case class extends?

EDIT: The real world application has 7 members, not 3. Only a small number of the functions need access to the members. Most of the functions don't care about them.

Was it helpful?

Solution

There's the obvious val declaration:

val a = 0.5
A(a, 1.0, 2.0, List(f1(3.0), f2(4.0, a)))

Otherwise, f2 needs a reference to A's this, which it will have if it's a member of class A or that particular instance of A. Part of the problem is that the functions are fully baked before the instance of A is instantiated. So you have to define f2, as opposed to simply instantiate it, in the context of A.

Finally, you could make the functions partial functions. The first group of params will be as they are, but a second group will be added that is of type A.

OTHER TIPS

If q in f2 is always referring to the q in you case class, then one quick hack :

trait TraitA {                                                                                       
  def q:Double                                                                                       
  def r:Double                                                                                       
  def s:Double                                                                                       

  def f1(w:Double) = (d:Double) => math.sin(d) * w                                                   
  def f2(w:Double) = (d:Double) => d * q * w                                                         
}                                                                                                    

case class A(q:Double, r:Double, s:Double, l:List[(Double)=>Double]=Nil) extends TraitA              

val a=new A(0.5, 1.0, 2.0){override val l= List(f1(3.0), f2(4.0))}                                   

One simple idea would be to change the function to take a list of functions that take 3 doubles (q, r, and s) and return a function from double to double. That way those functions that need any of the values can use them, and others just ignore them all.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top