Implicit Parameters

In Providing Default Values for Parameters you learned about default values for parameters—if you don’t pass an argument for a parameter, Scala will give it a default value. That’s nice; we don’t have to give values that are intuitively obvious or that can be inferred by default. But the default value that’s given is decided by the creator of the function and not the caller. Scala provides an alternative, so the caller can decide what value to send—by default—instead of the function definer deciding that.

Let’s consider an example that will benefit from this feature. With smartphones and mobile devices that we all carry around, we constantly have to connect to different networks: one network at home, another at the office, yet another at the airline lounge… The operation we perform is the same—connecting to a network—but the network we connect to, by default, depends on the context. We don’t want to specify the network each and every time; that becomes tiring. At the same time, we don’t want one default value to take effect all the time either. We can solve this problem using a special type of parameter called an implicit parameter.

The function definer should first mark the parameter as implicit. For this, Scala insists that implicit parameters are in a separate parameter list than regular parameters—Scala supports multiple parameter lists as you’ll learn in Currying. If a parameter is defined as implicit, an argument for that parameter is optional, just like default valued parameters. However, if the argument is not passed, Scala will look for an implicit variable in the scope of the call. The implicit variable is required to have the same type as the implicit parameter—thus there can be at most one implicit variable for each type within a scope.

Let’s create an example to use this feature.

FromJavaToScala/ImplicitParameters.scala
 
class​ Wifi(name: ​String​) {
 
override​ ​def​ toString = name
 
}
 
 
def​ connectToNetwork(user: ​String​)(​implicit​ wifi: Wifi) {
 
println(s​"User: $user connected to WIFI $wifi"​)
 
}
 
 
def​ atOffice() = {
 
println(​"--- at the office ---"​)
 
implicit​ ​def​ officeNetwork = ​new​ Wifi(​"office-network"​)
 
val​ cafeteriaNetwork = ​new​ Wifi(​"cafe-connect"​)
 
 
connectToNetwork(​"guest"​)(cafeteriaNetwork)
 
connectToNetwork(​"Jill Coder"​)
 
connectToNetwork(​"Joe Hacker"​)
 
}
 
 
def​ atJoesHome() = {
 
println(​"--- at Joe's home ---"​)
 
implicit​ ​def​ homeNetwork = ​new​ Wifi(​"home-network"​)
 
 
connectToNetwork(​"guest"​)(homeNetwork)
 
connectToNetwork(​"Joe Hacker"​)
 
}
 
 
atOffice()
 
atJoesHome()

The connectToNetwork function has two parameter lists, one with a regular parameter of type String and the other with an implicit parameter of type Wifi.

In the atOffice function we’ve defined two instances of the Wifi class, one of them marked implicit. We make three calls to the connectToNetwork function, but we provide an argument for the wifi parameter only on the first call. The other two calls expect the compiler to fill in the argument. If the parameter has a default value, the compiler would go looking for the value in the function definition. However, since this is an implicit parameter, the compiler looks for the value defined as implicit in the scope of the function call.

In the atJoesHome function we’ve defined only one instance of Wifi but marked it as implicit. Passing this parameter to the connectToNetwork method is optional. For example, a guest user would want to know what network to connect to, but it may be the same one that the resident uses implicitly. In this case, it’s okay to explicitly specify the parameter that is defined as implicit.

If a parameter is defined as implicit, then the caller should pass an argument for it or skip it if there is an implicit variable of the appropriate type in scope; otherwise, the compiler will raise an error.

Run the script and observe the output:

 
--- at the office ---
 
User: guest connected to WIFI cafe-connect
 
User: Jill Coder connected to WIFI office-network
 
User: Joe Hacker connected to WIFI office-network
 
--- at Joe's home ---
 
User: guest connected to WIFI home-network
 
User: Joe Hacker connected to WIFI home-network

The output shows that when the arguments were skipped, the implicit variables in the respective scope were used. Even though it’s the same function that’s called from different functions, the missing arguments passed in were not the same. While both default valued parameters and implicit parameters let the caller skip the argument, the value that the compiler binds the argument to is quite different.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.217.12.175