Skip to content

Commit 5acf8ac

Browse files
committed
Backport scala.util.chaining
1 parent 49c4f12 commit 5acf8ac

File tree

3 files changed

+121
-0
lines changed

3 files changed

+121
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Scala (https://www.scala-lang.org)
3+
*
4+
* Copyright EPFL and Lightbend, Inc.
5+
*
6+
* Licensed under Apache License 2.0
7+
* (http://www.apache.org/licenses/LICENSE-2.0).
8+
*
9+
* See the NOTICE file distributed with this work for
10+
* additional information regarding copyright ownership.
11+
*/
12+
13+
package scala.util
14+
15+
trait ChainingSyntax {
16+
@`inline` implicit final def scalaUtilChainingOps[A](a: A): ChainingOps[A] = new ChainingOps(a)
17+
}
18+
19+
/** Adds chaining methods `tap` and `pipe` to every type.
20+
*/
21+
final class ChainingOps[A](private val self: A) extends AnyVal {
22+
23+
/** Applies `f` to the value for its side effects, and returns the original value.
24+
*
25+
* {{{
26+
* scala> import scala.util.chaining._
27+
*
28+
* scala> val xs = List(1, 2, 3).tap(ys => println("debug " + ys.toString))
29+
* debug List(1, 2, 3)
30+
* xs: List[Int] = List(1, 2, 3)
31+
* }}}
32+
*
33+
* @param f the function to apply to the value.
34+
* @tparam U the result type of the function `f`.
35+
* @return the original value `self`.
36+
*/
37+
def tap[U](f: A => U): A = {
38+
f(self)
39+
self
40+
}
41+
42+
/** Converts the value by applying the function `f`.
43+
*
44+
* {{{
45+
* scala> import scala.util.chaining._
46+
*
47+
* scala> val times6 = (_: Int) * 6
48+
* times6: Int => Int = \$\$Lambda\$2023/975629453@17143b3b
49+
*
50+
* scala> val i = (1 - 2 - 3).pipe(times6).pipe(scala.math.abs)
51+
* i: Int = 24
52+
* }}}
53+
*
54+
* Note: `(1 - 2 - 3).pipe(times6)` may have a small amount of overhead at
55+
* runtime compared to the equivalent `{ val temp = 1 - 2 - 3; times6(temp) }`.
56+
*
57+
* @param f the function to apply to the value.
58+
* @tparam B the result type of the function `f`.
59+
* @return a new value resulting from applying the given function
60+
* `f` to this value.
61+
*/
62+
def pipe[B](f: A => B): B = f(self)
63+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Scala (https://www.scala-lang.org)
3+
*
4+
* Copyright EPFL and Lightbend, Inc.
5+
*
6+
* Licensed under Apache License 2.0
7+
* (http://www.apache.org/licenses/LICENSE-2.0).
8+
*
9+
* See the NOTICE file distributed with this work for
10+
* additional information regarding copyright ownership.
11+
*/
12+
13+
package scala
14+
15+
package object util {
16+
17+
/**
18+
* Adds chaining methods `tap` and `pipe` to every type. See [[ChainingOps]].
19+
*/
20+
object chaining extends ChainingSyntax
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package scala.util
2+
3+
import org.junit.Assert._
4+
import org.junit.Test
5+
6+
//import scala.tools.reflect.ToolBoxError
7+
//import scala.tools.testkit.RunTesting
8+
9+
class ChainingOpsTest {
10+
import scala.util.chaining._
11+
12+
@Test
13+
def testAnyTap(): Unit = {
14+
var x: Int = 0
15+
val result = List(1, 2, 3)
16+
.tap(xs => x = xs.head)
17+
18+
assertEquals(1, x)
19+
assertEquals(List(1, 2, 3), result)
20+
}
21+
22+
@Test def testAnyValTap(): Unit = assertEquals(42.tap(x => x), 42)
23+
24+
@Test
25+
def testAnyPipe(): Unit = {
26+
val times6 = (_: Int) * 6
27+
val result = (1 - 2 - 3)
28+
.pipe(times6)
29+
.pipe(scala.math.abs)
30+
31+
assertEquals(24, result)
32+
}
33+
34+
// @Test(expected = classOf[ToolBoxError])
35+
// def testNoSelf(): Unit =
36+
// runner.run("import scala.util.chaining._; Nil.self")
37+
}

0 commit comments

Comments
 (0)