Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to used named parameters with a curried function in scala

I have a method with 4 parameters that gets used in blocks. Within each block, the first parameter is always the same:

// Block 1 - first parameter always "A"
foo(a="A", b="x", c="y", d="z")
foo(a="A", b=".", c=",", d="-")
foo(a="A", b="1", c="2", d="3")

// Block 2 - first parameter always "B"
foo(a="B", b="x", c="y", d="z")
foo(a="B", b=".", c=",", d="-")
foo(a="B", b="1", c="2", d="3")

I want a quick way to create a method for each block so that I only need to specify the other 3 parameters. Currently I can do this:

def fooCurried(a: String) = foo(a, _: String, _: String, _: String)

val fooA = fooCurreid("A")
fooA("x", "y", "z")
fooA(".", ",", "-")
fooA("1", "2", "3")

val fooB = fooCurried("B")
fooB("x", "y", "z")
fooB(".", ",", "-")
fooB("1", "2", "3")

The problem with this approach is that I lose my named parameters. They become v1, v2 and v3. Using named parameters is important in this case because the types of the other 3 parameters are the same and so are easy to mix up.

Is there a clean way to define a fooCurried function like above which I can use easily in different contexts but lets me used named parameters?

I'd like something I can use like this:

def fooCurried(a: String) = ???

val fooA = fooCurreid("A")
fooA(b="x", c="y", d="z")
fooA(b=".", c=",", d="-")
fooA(b="1", c="2", d="3")

Thanks in advance!

like image 397
rmin Avatar asked Jan 21 '16 11:01

rmin


2 Answers

How about this :

case class fooCurried(a: String) {
  def apply(b: String, c: String, d: String) = {
    // do something
    println(a + "," + b + "," + c + "," + d)
  }
}

You can use it like this :

scala> val fooA = fooCurried(a = "A")
fooA: fooCurried = fooCurried(A)

scala> fooA(b="B", c="C", d="D")
A,B,C,D

scala> fooA(b="x", c="y", d="z")
A,x,y,z
like image 83
ixguza Avatar answered Oct 31 '22 00:10

ixguza


One alternative way where you can is using case class:

case class Foo(a:String, b:String, c:String)

val f = Foo(a="a", b="b", c="c")
foo(f.copy(b ="b1", c="c1"))

But then your foo would take a class as argument instead of 4 multiple strings.

like image 26
Jatin Avatar answered Oct 31 '22 01:10

Jatin