- Learn Scala Programming
- Slava Schmidt
- 447字
- 2021-06-10 19:35:39
Added methods for chaining operations
Via import scala.util.chaining._, it is now possible to add tap and pipe methods to instances of any type. The functionality is provided by an implicit conversion to ChainingOps. We will look at implicits in detail in Chapter 4, Getting to Know Implicits and Type Classes.
The pipe method applies a given function to the value and returns the result. It might be helpful in situations where it is desirable to convert nested function calls into the fluid-interface-like code. The following snippet shows an example of an imaginary user database with nested function calls chained via pipe.
Consider the following the database interface:
object UserDb {
def getById(id: Long): User = ???
def update(u: User): User = ???
def save(u: User): Boolean = ???
}
We could apply all three actions to the user at once:
import UserDb._
val userId = 1L
save(update(getById(userId)))
pipe allows us to represent this in a more readable format:
getById(userId).pipe(update).pipe(save)
Arguably the same (or an even clearer) result could be achieved by combining functions before applying them:
val doEverything = (getById _).andThen(update).andThen(save)
doEverything(userId)
We will look at functions in general, and function composition in particular, in Chapter 3, Deep Dive into Functions.
tap applies a function given as an argument solely for the side-effects it produces and returns the original value. It might be useful, for example, for logging purposes and the simplest kind of performance measurements.
The next snippet demonstrates an elementary side-effect-causing performance-tracking implementation that utilizes a global variable:
scala> import scala.util.chaining._
import scala.util.chaining._
scala> val lastTick = new java.util.concurrent.atomic.AtomicLong(0)
lastTick: java.util.concurrent.atomic.AtomicLong = 0
scala> def measure[A](a: A): Unit = {
| val now = System.currentTimeMillis()
| val before = lastTick.getAndSet(now)
| println(s"$a: ${now-before} ms elapsed")
| }
measure: [A](a: A)Unit
scala> def start(): Unit = lastTick.set(System.currentTimeMillis())
start: ()Unit
scala> start()
scala> val result = scala.io.StdIn.readLine().pipe(_.toIntOption).tap(measure)
None: 291 ms elapsed
result: Option[Int] = None
scala> val anotherResult = scala.io.StdIn.readLine().pipe(_.toIntOption).tap(measure)
Some(3456): 11356 ms elapsed
anotherResult: Option[Int] = Some(3456)
Here, we defined a global value of the AtomicLong type to store the last measured timestamp. Then we define a polymorphic measure method that captures the time between the moment of the last measurement and now, and a start method to reset the clock. After that, we can use the tap method to track the execution times of our actions.
We will talk about types and polymorphism in Chapter 2, Understanding Types in Scala, side-effects and more general concept of effects in Chapter 8, Dealing with Effects, and show drawbacks of having global variables and a global state in Chapter 9, Familiarizing Yourself with Basic Monads.
- 演進式架構(gòu)(原書第2版)
- JavaScript前端開發(fā)模塊化教程
- Mobile Web Performance Optimization
- MySQL數(shù)據(jù)庫應用與管理 第2版
- Developing Mobile Web ArcGIS Applications
- 算法精粹:經(jīng)典計算機科學問題的Java實現(xiàn)
- iOS開發(fā)實戰(zhàn):從零基礎(chǔ)到App Store上架
- Web開發(fā)的貴族:ASP.NET 3.5+SQL Server 2008
- 數(shù)據(jù)結(jié)構(gòu)(Python語言描述)(第2版)
- 64位匯編語言的編程藝術(shù)
- GitLab Repository Management
- Java:High-Performance Apps with Java 9
- 從零開始:UI圖標設(shè)計與制作(第3版)
- Python Social Media Analytics
- Mastering Machine Learning with scikit-learn