-
Notifications
You must be signed in to change notification settings - Fork 29
/
Put.scala
77 lines (74 loc) · 2.34 KB
/
Put.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package com.thoughtworks.dsl
package keywords
import com.thoughtworks.dsl.Dsl.IsKeyword
/** [[Put]] is a [[Dsl.Keyword Keyword]] to replace the [[value]] of the current
* context.
*
* Purely functional programming languages usually do not support native
* first-class mutable variables. In those languages, mutable states can be
* implemented in state monads.
*
* [[Put]] and [[Get]] are the [[Dsl]]-based replacements of state monads.
*
* We use unary function as the domain of mutable state. The parameter of the
* unary function can be read from the [[Get]] keyword, and changed by the
* [[Put]] keyword.
*
* @example
* The following example creates a function that accepts a string parameter
* and returns the upper-cased last character of the parameter.
*
* {{{
* import com.thoughtworks.dsl.macros.Reset.Default.reset
* def upperCasedLastCharacter = reset[String => Char] {
* val initialValue = !Get[String]
* !Put(initialValue.toUpperCase)
*
* val upperCased = !Get[String]
* Function.const(upperCased.last)
* }
* }}}
*
* For example, given a string of `foo`, the upper-cased last character should
* be `O`.
*
* {{{
* upperCasedLastCharacter("foo") should be('O')
* }}}
*
* @example
* [[Put]] and [[Get]] support multiple states.
*
* The following code creates a formatter that [[Put]] parts of content into a
* `Vector[Any]` of string buffers.
*
* {{{
* import com.thoughtworks.dsl.macros.Reset.Default.reset
* def formatter = reset[Double => Int => Vector[Any] => String] {
* !Put(!Get[Vector[Any]] :+ "x=")
* !Put(!Get[Vector[Any]] :+ !Get[Double])
* !Put(!Get[Vector[Any]] :+ ",y=")
* !Put(!Get[Vector[Any]] :+ !Get[Int])
*
* !Return((!Get[Vector[Any]]).mkString)
* }
*
* formatter(0.5)(42)(Vector.empty) should be("x=0.5,y=42")
* }}}
* @see
* [[Get]]
* @author
* 杨博 (Yang Bo)
*/
opaque type Put[+S] <: Dsl.Keyword.Opaque = Dsl.Keyword.Opaque.Of[S]
def Put[S](using
dummyImplicit: DummyImplicit = DummyImplicit.dummyImplicit
): S =:= Put[S] = Dsl.Keyword.Opaque.Of
object Put {
given [S]: IsKeyword[Put[S], Unit] with {}
given [S0, S >: S0, A]: Dsl.Original[Put[S0], S => A, Unit] =
Dsl.Original[Put[S0], S => A, Unit] {
(keyword: Put[S0], handler: Unit => S => A) => oldValue =>
handler(())(keyword)
}
}