Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

scala: optional default argument as function of other arguments

I have a constructor, which takes one main argument (data), and another argument (model), that has a reasonable default initialization, which depends on the main argument.

I want to have the possibility to give another value for model whenever that's appropriate.

A simplified example:

1) without default arguments:

class trainer(data:Int,model:Double) {}

2) initialization:

def init(data:Int): Double = 1.0/data

3) it would work if initialization were independent of other arguments:

class trainer(data:Int, model:Double = init(1)) {}

4) what I would like to have, but what gives an error:

class trainer(data:Int, model:Double = init(data)) {}

What's the best/closest way to achieve what I want to do?

(my particular case deals with a constructor, but I would be interested whether there is a way in the general case for functions as well)

like image 616
benroth Avatar asked Feb 19 '15 16:02

benroth


People also ask

What is the function parameter with a default value in Scala?

Scala provides the ability to give parameters default values that can be used to allow a caller to omit those parameters. The parameter level has a default value so it is optional. On the last line, the argument "WARNING" overrides the default argument "INFO" .

How do you pass parameters to a Scala function?

Scala - Functions with Named Arguments Named arguments allow you to pass arguments to a function in a different order. The syntax is simply that each argument is preceded by a parameter name and an equals sign. Try the following program, it is a simple example to show the functions with named arguments.

Are optional arguments bad?

The thing with optional parameters is, they are BAD because they are unintuitive - meaning they do NOT behave the way you would expect it. Here's why: They break ABI compatibility ! so you can change the default-arguments at one place.

What is function with default argument?

A default argument is a value provided in a function declaration that is automatically assigned by the compiler if the calling function doesn't provide a value for the argument. In case any value is passed, the default value is overridden.


1 Answers

You can simply have an overloaded constructor:

class Trainer(data:Int, model:Double) {
    def this(data:Int) = this(data, init(data))
}

Then you can instantiate using:

new Trainer(4)
new Trainer(4, 5.0)

Another approach is to use a companion object with different apply overloads:

//optionally make the constructor protected or private, so the only way to instantiate is using the companion object
class Trainer private(data:Int, model:Double)

object Trainer {
    def apply(data:Int, model:Double) = new Trainer(data, model)
    def apply(data:Int) = new Trainer(data, init(data))
}

Then you can instantiate using

Trainer(4)
Trainer(4, 5.0)

Another approach is to use an Option with a default of None, and then initialize a private variable in the class body:

class Trainer(data:Int, model:Option[Double] = None) {
    val modelValue = model.getOrElse(init(data))
}

Then you instantiate using:

new Trainer(5)
new Trainer(5, Some(4.0))
like image 113
Ben Reich Avatar answered Oct 18 '22 16:10

Ben Reich