-
Notifications
You must be signed in to change notification settings - Fork 29
/
Put.scala
66 lines (63 loc) · 2.29 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
package com.thoughtworks.dsl
package keywords
import com.thoughtworks.dsl.Dsl.Keyword
/** [[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.
*
* {{{
* def upperCasedLastCharacter: 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`.
*
* {{{
* // Output: 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.
*
* {{{
* def formatter: 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)
*/
final case class Put[S](value: S) extends AnyVal with Keyword[Put[S], Unit]
object Put {
implicit def putDsl[S0, S >: S0, A] = new Dsl[Put[S0], S => A, Unit] {
def cpsApply(keyword: Put[S0], handler: Unit => S => A): S => A = {
val newValue = keyword.value;
{ oldValue =>
handler(())(newValue)
}
}
}
}