Skip to content

Commit 125e064

Browse files
committed
Revert "Simplify Using Dsl with the help of FlatMap"
This reverts commit eeb0567.
1 parent 0351be8 commit 125e064

File tree

1 file changed

+88
-60
lines changed
  • keywords-Using/src/main/scala/com/thoughtworks/dsl/keywords

1 file changed

+88
-60
lines changed
Lines changed: 88 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,94 +1,122 @@
11
package com.thoughtworks.dsl
22
package keywords
33

4-
import com.thoughtworks.dsl.bangnotation.{`*`, reify, reset, unary_!}
4+
import com.thoughtworks.dsl.bangnotation.{ `*`, reify, reset, unary_!}
55
import com.thoughtworks.dsl.Dsl
66
import com.thoughtworks.dsl.Dsl.!!
77
import com.thoughtworks.dsl.Dsl.AsKeyword
8+
// import com.thoughtworks.dsl.keywords.Catch.{CatchDsl, DslCatch}
89
import com.thoughtworks.dsl.keywords.TryFinally
910
import com.thoughtworks.dsl.Dsl.cpsApply
1011

1112
import scala.concurrent.{ExecutionContext, Future}
1213
import scala.language.implicitConversions
1314
import scala.util.control.NonFatal
1415

15-
/** This [[Using]] keyword automatically manage resources in
16-
* [[scala.concurrent.Future]], [[domains.task.Task]], and other asynchronous
17-
* domains derived from `Future` or `Task`.
16+
/** This [[Using]] keyword automatically manage resources in [[scala.concurrent.Future]], [[domains.task.Task]],
17+
* and other asynchronous domains derived from `Future` or `Task`.
1818
*
19-
* @author
20-
* 杨博 (Yang Bo)
21-
* @see
22-
* [[dsl]] for usage of this [[Using]] keyword in continuations
19+
* @author 杨博 (Yang Bo)
20+
* @see [[dsl]] for usage of this [[Using]] keyword in continuations
2321
*/
24-
opaque type Using[R <: AutoCloseable] = R
22+
final case class Using[R <: AutoCloseable](open: () => R) extends AnyVal
2523

2624
object Using {
2725
given [R <: AutoCloseable]: AsKeyword.IsKeyword[Using[R], R] with {}
2826

29-
given [R <: AutoCloseable]: AsKeyword[R, Using[R], R] = Using(_)
27+
given [R <: AutoCloseable]: AsKeyword[R, Using[R], R] = r => Using(() => r)
3028

3129
trait ScopeExitHandler extends AutoCloseable
3230

33-
/** Returns a [[Using]] keyword to execute a [[ScopeExitHandler]] when exiting
34-
* the nearest enclosing scope that is annotated as [[Dsl.reset @reset]], (or
35-
* the nearest enclosing function if [[compilerplugins.ResetEverywhere]] is
36-
* enabled).
31+
/** Returns a [[Using]] keyword to execute a [[ScopeExitHandler]] when exiting the nearest enclosing scope
32+
* that is annotated as [[Dsl.reset @reset]],
33+
* (or the nearest enclosing function if [[compilerplugins.ResetEverywhere]] is enabled).
3734
*
38-
* @note
39-
* This method is similar to [[apply]], except the parameter type is
40-
* changed from a generic `R` to the SAM type [[ScopeExitHandler]], which
41-
* allows for function literal expressions in Scala 2.12+ or Scala 2.11
42-
* with `-Xexperimental` compiler option.
35+
* @note This method is similar to [[apply]],
36+
* except the parameter type is changed from a generic `R` to the SAM type [[ScopeExitHandler]],
37+
* which allows for function literal expressions
38+
* in Scala 2.12+ or Scala 2.11 with `-Xexperimental` compiler option.
4339
*
44-
* @example
45-
* The following function will perform `n *= 2` after `n += 20`:
40+
* @example The following function will perform `n *= 2` after `n += 20`:
4641
*
47-
* {{{
48-
* import scala.concurrent.Future
49-
* import com.thoughtworks.dsl.keywords.Using.scopeExit
50-
* import com.thoughtworks.dsl.bangnotation._
51-
* var n = 1
52-
* def multiplicationAfterAddition = *[Future] {
53-
* !scopeExit { () =>
54-
* n *= 2
55-
* }
56-
* n += 20
57-
* }
58-
* }}}
42+
* {{{
43+
* import scala.concurrent.Future
44+
* import com.thoughtworks.dsl.keywords.Using.scopeExit
45+
* import com.thoughtworks.dsl.bangnotation._
46+
* var n = 1
47+
* def multiplicationAfterAddition = *[Future] {
48+
* !scopeExit { () =>
49+
* n *= 2
50+
* }
51+
* n += 20
52+
* }
53+
* }}}
5954
*
60-
* Therefore, the final value of `n` should be `(1 + 20) * 2 = 42`.
55+
* Therefore, the final value of `n` should be `(1 + 20) * 2 = 42`.
6156
*
62-
* {{{
63-
* multiplicationAfterAddition.map { _ =>
64-
* n should be(42)
65-
* }
66-
* }}}
57+
* {{{
58+
* multiplicationAfterAddition.map { _ =>
59+
* n should be(42)
60+
* }
61+
* }}}
6762
*/
68-
def scopeExit(r: ScopeExitHandler) = r
63+
def scopeExit(r: => ScopeExitHandler) = new Using(() => r)
6964

70-
def apply[R <: AutoCloseable]: R =:= Using[R] = summon
65+
def apply[R <: AutoCloseable](r: => R)(implicit
66+
dummyImplicit: DummyImplicit = DummyImplicit.dummyImplicit
67+
): Using[R] = new Using(() => r)
7168

72-
given [
73-
R <: AutoCloseable,
74-
Mapped,
75-
MappedValue,
76-
OuterDomain,
77-
BlockDomain,
78-
FinalizerDomain
79-
](using
80-
AsKeyword.IsKeyword[Mapped, MappedValue],
81-
Dsl.TryFinally[MappedValue, OuterDomain, BlockDomain, FinalizerDomain],
82-
Dsl.PolyCont[Mapped, BlockDomain, MappedValue]
83-
): Dsl.PolyCont[FlatMap[Using[R], R, Mapped], OuterDomain, MappedValue] = {
84-
case (FlatMap(r, flatMapper), handler) =>
85-
reset {
86-
handler(try {
87-
!flatMapper(r)
88-
} finally {
89-
r.close()
90-
})
69+
implicit def continuationUsingDsl[Domain, Value, R <: AutoCloseable](implicit
70+
tryFinally: Dsl.TryFinally[Value, Domain, Domain, Domain],
71+
// shiftDsl: Dsl[Shift[Domain, Value], Domain, Value]
72+
): Dsl[Using[R], Domain !! Value, R] = { (keyword: Using[R], handler: R => Domain !! Value) =>
73+
*[[X] =>> Domain !! X] {
74+
val r = keyword.open()
75+
try {
76+
!Shift[Domain, Value](handler(r))
77+
} finally {
78+
r.close()
9179
}
80+
}
9281
}
9382

83+
implicit def scalaFutureUsingDsl[R <: AutoCloseable, A](implicit executionContext: ExecutionContext)
84+
: Dsl[Using[R], Future[A], R] = { (keyword: Using[R], handler: R => Future[A]) =>
85+
Future(keyword.open()).flatMap { (r: R) =>
86+
def onFailure(e: Throwable): Future[Nothing] = {
87+
try {
88+
r.close()
89+
Future.failed(e)
90+
} catch {
91+
case NonFatal(e2) =>
92+
Future.failed(e2)
93+
}
94+
}
95+
96+
def onSuccess(a: A): Future[A] = {
97+
try {
98+
r.close()
99+
Future.successful(a)
100+
} catch {
101+
case NonFatal(e2) =>
102+
Future.failed(e2)
103+
}
104+
}
105+
106+
def returnableBlock(): Future[A] = {
107+
val fa: Future[A] = try {
108+
handler(r)
109+
} catch {
110+
case NonFatal(e) =>
111+
return onFailure(e)
112+
}
113+
fa.recoverWith {
114+
case NonFatal(e) =>
115+
onFailure(e)
116+
}
117+
.flatMap(onSuccess)
118+
}
119+
returnableBlock()
120+
}
121+
}
94122
}

0 commit comments

Comments
 (0)