3

Please consider the following example

def foo(a: Int, b: Int = 100) = a + b
def bar(a: Int, b: Int = 100) = foo(a, b) * 2

This works, but note I have to supply the same default value to b in both functions. My intention is actually the following

def bar(a: Int, b: Int) = foo(a, b) * 2
def bar(a: Int)    = foo(a) * 2

But this becomes cumbersome when you have more optional arguments, and additional functions in the chain (such as baz that invokes bar in the same manner). Is there a more concise way to express this in scala?

1
  • 2
    Please state your question clearly: what do you consider cumbersome here? What exactly are you looking for? If you're looking for a more concise way to write default parameters, then there's none, and how could there be? Commented Aug 9, 2012 at 3:29

2 Answers 2

4

I don't think there is; if you compose foo with a doubling function:

val bar = (foo _).curried((_: Int)) andThen ((_: Int) *2)
// (please, please let there be a simpler way to do this...)

you lose the default arguments, because function objects don't have them.

If it's worth it in your use-case, you could create a case class containing your arguments which you pass instead of multiple individual ones, e.g.

case class Args(a: Int, b: Int = 100, c: Int = 42, d: Int = 69)
def foo(args: Args) = { import args._; a + b + c + d }
def bar(args: Args) = foo(args) * 2
Sign up to request clarification or add additional context in comments.

2 Comments

Totally awesome technique. It should be done by compiler itself every time it encounters overloaded method: converting it to associated data class and a function. Functions are much handy for manipulations than methods.
Yeah I guess the case class solution is the best you can do. It feels though that this might be a useful feature that can be easily implemented in scala compiler. What I have in mind is something like this: def bar(a: Int, b: Int = _) = foo(a, b) * 2, scala can check that b is only used in places where a default value has been defined, so it can interpret this without ambiguity.
2

I would suggest to use Option.

def bar(a: Int, b: Option[Int] = None) = b match {
  case Some(x) => foo(a,x) * 2
  case _ => foo(a) * 2
}

This will exactly do what you want. Another way would be using varargs.

def baz(a: Int)(b: Int*) = b.headOption match {
  case Some(x) => foo(a,x) * 2
  case _ => foo(a) * 2
}

I would prefer the first way, because it is obvious, that the parameter is optional. The second solution was not to deal with the wrapping in an Option, but it is not clear by the signature, that only the first element of the collection will be considered. baz(1)(2) == baz(1)(2,3,4,5) is true.

Edit

To make the one with the Option look like your desired calls, you might use implicits.

implicit def int2Some(i: Int) = Some(i)

Now you can call the function the following:

bar(1,2)
bar(1,Some(2))
bar(1)
bar(1,None)

The implicit is called automatically where ever it is usefull. But your users might get confused, why the function can be called with an Int instead of an Option[Int].

4 Comments

The first solution does not allow you to invoke bar(1). You would have to say bar(1, None). In addition, what used to be bar(1, 2) now needs to be written as bar(1, Some(2)). Using repeated parameter is closer to the desired syntax, but I guess it won't work if you have two or more optional parameters? And yes it also has the problem you mentioned.
You might fix the first issue by making it default None. I added that.
The second issue might be fixed by using implicits. I added that one too.
Yes, with the fixes your solution achieves the exact syntax I wanted to have. However, it is too much code to my liking to implement this seemingly simple feature. Consider the case where you have more optional parameters, you will end up with as many match statements, and they have to be repeated in each function that wants to pass on the default value. That is a lot of boiler plate, imho exactly the type of thing Scala tries to avoid. Another minor gripe is the int2some default seems a bit dangerous. But thanks for making this work. My complaint is mainly towards Scala compiler.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.