ruff 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +18 -1
- data/Gemfile.lock +1 -1
- data/README.md +3 -14
- data/docs/Ruff.html +3 -3
- data/docs/Ruff/Effect.html +2 -2
- data/docs/Ruff/Handler.html +73 -113
- data/docs/Ruff/Standard.html +33 -3
- data/docs/Ruff/Standard/CurrentTime.html +150 -14
- data/docs/Ruff/Standard/CurrentTime/Instance.html +183 -25
- data/docs/Ruff/Standard/Defer.html +152 -15
- data/docs/Ruff/Standard/Defer/Instance.html +213 -37
- data/docs/Ruff/Standard/State.html +215 -30
- data/docs/Ruff/Standard/State/Instance.html +389 -72
- data/docs/Ruff/Throws.html +2 -2
- data/docs/Ruff/Throws/Eff.html +6 -4
- data/docs/Ruff/Throws/Resend.html +14 -12
- data/docs/_index.html +3 -3
- data/docs/file.README.html +7 -23
- data/docs/frames.html +1 -1
- data/docs/index.html +7 -23
- data/docs/method_list.html +84 -28
- data/docs/top-level-namespace.html +2 -2
- data/lib/ruff/handler.rb +50 -49
- data/lib/ruff/objects.rb +4 -2
- data/lib/ruff/standard.rb +16 -0
- data/lib/ruff/standard/current_time.rb +29 -2
- data/lib/ruff/standard/defer.rb +33 -3
- data/lib/ruff/standard/state.rb +69 -14
- data/lib/ruff/version.rb +1 -1
- data/version +1 -1
- metadata +2 -3
- data/.rubocop_todo.yml +0 -366
@@ -6,7 +6,7 @@
|
|
6
6
|
<title>
|
7
7
|
Top Level Namespace
|
8
8
|
|
9
|
-
— Ruff 1.0.
|
9
|
+
— Ruff 1.0.1 Documentation
|
10
10
|
|
11
11
|
</title>
|
12
12
|
|
@@ -100,7 +100,7 @@
|
|
100
100
|
</div>
|
101
101
|
|
102
102
|
<div id="footer">
|
103
|
-
Generated on
|
103
|
+
Generated on Fri Oct 4 13:57:07 2019 by
|
104
104
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
105
105
|
0.9.20 (ruby-2.6.4).
|
106
106
|
</div>
|
data/lib/ruff/handler.rb
CHANGED
@@ -13,7 +13,6 @@ class Ruff::Handler
|
|
13
13
|
#
|
14
14
|
# @example
|
15
15
|
# handler = Handler.new
|
16
|
-
|
17
16
|
def initialize
|
18
17
|
@handlers = {}
|
19
18
|
@valh = ->(x) { x }
|
@@ -24,7 +23,8 @@ class Ruff::Handler
|
|
24
23
|
# Value handler is the handler for *the result value of the computation*.
|
25
24
|
# For example, `Handler.new.to{|_x| 0}.run { value }` results in `0` .
|
26
25
|
#
|
27
|
-
# The value handler modifies the result of the call of continuation
|
26
|
+
# The value handler modifies the result of the call of continuation
|
27
|
+
# in effect handlers of the handler.
|
28
28
|
#
|
29
29
|
# @param [Proc<A, B>] fun
|
30
30
|
# value handler
|
@@ -52,7 +52,6 @@ class Ruff::Handler
|
|
52
52
|
# # msg>> hello
|
53
53
|
# # msg>> world
|
54
54
|
# # returns !
|
55
|
-
|
56
55
|
def to(&fun)
|
57
56
|
@valh = fun
|
58
57
|
|
@@ -67,14 +66,14 @@ class Ruff::Handler
|
|
67
66
|
# a handler to handle `eff`;
|
68
67
|
# First argument of `&fun` is *continuation*, proc object
|
69
68
|
# to go back to the handled computation.
|
70
|
-
# @return [Handler<A!{Effect<Arg, Ret>, e}, B!{e}>]
|
69
|
+
# @return [Handler<A!{Effect<Arg, Ret>, e}, B!{e}>]
|
70
|
+
# itself updated with handling `Effect<Arg, Ret>`
|
71
71
|
#
|
72
72
|
# @example
|
73
73
|
# handler.on(Log) {|k, msg|
|
74
74
|
# puts "Logger: #{msg}"
|
75
75
|
# k[]
|
76
76
|
# }
|
77
|
-
|
78
77
|
def on(eff, &fun)
|
79
78
|
@handlers[eff.id] = fun
|
80
79
|
|
@@ -86,7 +85,8 @@ class Ruff::Handler
|
|
86
85
|
# @param [Proc<(), A>] prc
|
87
86
|
# a thunk to be handled and returns `A`
|
88
87
|
# @return [B]
|
89
|
-
# a value modified by value handler `Proc<A, B>` ,
|
88
|
+
# a value modified by value handler `Proc<A, B>` ,
|
89
|
+
# or returned from the effect handler throwing continuation away
|
90
90
|
#
|
91
91
|
# @example
|
92
92
|
# handler.run {
|
@@ -103,57 +103,58 @@ class Ruff::Handler
|
|
103
103
|
# Log.perform 3
|
104
104
|
# }
|
105
105
|
# }
|
106
|
-
|
107
106
|
def run(&prc)
|
108
|
-
co = Fiber.new
|
109
|
-
continue = nil
|
110
|
-
rehandles = nil
|
111
|
-
|
112
|
-
handle = lambda { |r|
|
113
|
-
case r
|
114
|
-
when Eff
|
115
|
-
if effh = @handlers[r.id]
|
116
|
-
effh[continue, *r.args]
|
117
|
-
else
|
118
|
-
Fiber.yield Resend.new(r, continue)
|
119
|
-
end
|
120
|
-
when Resend then
|
121
|
-
eff = r.eff
|
122
|
-
next_k = rehandles.call(r.k)
|
123
|
-
|
124
|
-
if effh = @handlers[eff.id]
|
125
|
-
effh.call(next_k, *eff.args)
|
126
|
-
else
|
127
|
-
Fiber.yield Resend.new(eff, next_k)
|
128
|
-
end
|
129
|
-
else
|
130
|
-
@valh.call(r)
|
131
|
-
end
|
132
|
-
}
|
107
|
+
co = Fiber.new(&prc)
|
133
108
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
109
|
+
continue(co).call(nil)
|
110
|
+
end
|
111
|
+
|
112
|
+
# is also private method.
|
113
|
+
def handlers=(handlers)
|
114
|
+
@handlers = handlers.dup
|
115
|
+
end
|
139
116
|
|
140
|
-
|
141
|
-
|
117
|
+
private
|
118
|
+
|
119
|
+
def continue(co)
|
120
|
+
->(*arg) { handle(co, co.resume(*arg)) }
|
121
|
+
end
|
122
|
+
|
123
|
+
# rubocop:disable Metrics/AbcSize
|
124
|
+
def handle(co, r)
|
125
|
+
case r
|
126
|
+
when Eff
|
127
|
+
if (effh = @handlers[r.id])
|
128
|
+
effh[continue(co), *r.args]
|
129
|
+
else
|
130
|
+
Fiber.yield Resend.new(r, continue(co))
|
142
131
|
end
|
132
|
+
when Resend then
|
133
|
+
eff = r.eff
|
134
|
+
next_k = rehandles(co, r.k)
|
143
135
|
|
144
|
-
|
145
|
-
|
136
|
+
if (effh = @handlers[eff.id])
|
137
|
+
effh.call(next_k, *eff.args)
|
138
|
+
else
|
139
|
+
Fiber.yield Resend.new(eff, next_k)
|
146
140
|
end
|
141
|
+
else
|
142
|
+
@valh.call(r)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
# rubocop:enable Metrics/AbcSize
|
147
146
|
|
148
|
-
|
149
|
-
|
150
|
-
}
|
151
|
-
}
|
147
|
+
def rehandles(co, k)
|
148
|
+
newh = self.class.new
|
152
149
|
|
153
|
-
|
154
|
-
handle.call(co.resume(*arg))
|
155
|
-
}
|
150
|
+
newh.handlers = @handlers
|
156
151
|
|
157
|
-
|
152
|
+
lambda { |*args|
|
153
|
+
newh
|
154
|
+
.to { |v| continue(co).call(v) }
|
155
|
+
.run { k.call(*args) }
|
156
|
+
}
|
158
157
|
end
|
158
|
+
|
159
|
+
private_methods :handlers=
|
159
160
|
end
|
data/lib/ruff/objects.rb
CHANGED
@@ -14,7 +14,8 @@ class Ruff::Throws::Eff
|
|
14
14
|
|
15
15
|
# creates a new object with `id` and `args`.
|
16
16
|
def initialize(id, args)
|
17
|
-
@id = id
|
17
|
+
@id = id
|
18
|
+
@args = args
|
18
19
|
end
|
19
20
|
end
|
20
21
|
|
@@ -30,6 +31,7 @@ class Ruff::Throws::Resend
|
|
30
31
|
|
31
32
|
# creates a new object with `eff` and `k`.
|
32
33
|
def initialize(eff, k)
|
33
|
-
@eff = eff
|
34
|
+
@eff = eff
|
35
|
+
@k = k
|
34
36
|
end
|
35
37
|
end
|
data/lib/ruff/standard.rb
CHANGED
@@ -1,5 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# `Ruff::Standard` provides several pre-defined effect handlers modules.
|
4
|
+
# Each module provides `Instance` class to instantiate and handle the indivisual effect instances.
|
5
|
+
# @example
|
6
|
+
# include Ruff::Standard
|
7
|
+
#
|
8
|
+
# state1 = State::Instance.new
|
9
|
+
# state2 = State::Instance.new
|
10
|
+
#
|
11
|
+
# state1.with_init(3) {
|
12
|
+
# state2.with_init(4) {
|
13
|
+
# state2.modify {|s| s + state1.get }
|
14
|
+
#
|
15
|
+
# puts state1.get #==> 3
|
16
|
+
# puts state2.get #==> 7
|
17
|
+
# }}
|
18
|
+
#
|
3
19
|
module Ruff::Standard end
|
4
20
|
|
5
21
|
require 'ruff/standard/current_time'
|
@@ -1,30 +1,57 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# `CurrentTime` provides an effect `CurrentTime.eff` and the implementation returning `Time.now` .
|
4
|
+
#
|
5
|
+
# The module has an instance of `Instance` and provides its methods as module method.
|
6
|
+
# @see Standard::CurrentTime::Instance
|
3
7
|
module Ruff::Standard::CurrentTime
|
4
8
|
class Instance
|
9
|
+
# makes a new instance.
|
5
10
|
def initialize
|
6
11
|
@eff = Ruff.instance
|
7
12
|
end
|
8
13
|
|
14
|
+
# is a smart method to invoke the effect operation.
|
15
|
+
# @return [Time]
|
16
|
+
# with `with` , returns `Time.now`
|
9
17
|
def get
|
10
18
|
@eff.perform
|
11
19
|
end
|
12
20
|
|
21
|
+
# is a handler to interpret the effect invokation as requesting the current time.
|
22
|
+
# This handler receives the *request* and returns current time.
|
23
|
+
#
|
24
|
+
# @param [Proc<(), A>!{CurrentTime.eff, e}] th
|
25
|
+
# is a thunk returning `A` with the possibility to invoke effects,
|
26
|
+
# including `CurrentTime.eff` .
|
27
|
+
#
|
28
|
+
# @return [A!{e}]
|
29
|
+
# returns `A` , without modification by value handler.
|
30
|
+
# But it still has the possibility to invoke effects(`e`).
|
13
31
|
def with(&th)
|
14
|
-
Ruff.handler.on(@eff) { |k| k[Time.now] }.run
|
32
|
+
Ruff.handler.on(@eff) { |k| k[Time.now] }.run(&th)
|
15
33
|
end
|
34
|
+
|
35
|
+
# You can reimplement the handler using this effect instance.
|
36
|
+
attr_reader :eff
|
16
37
|
end
|
17
38
|
|
18
39
|
# ---
|
19
40
|
@inst = Instance.new
|
41
|
+
@eff = @inst.eff
|
20
42
|
|
43
|
+
# @see Ruff::Standard::CurrentTime::Instance#get
|
21
44
|
def get
|
22
45
|
@inst.get
|
23
46
|
end
|
24
47
|
|
48
|
+
# @see Ruff::Standard::CurrentTime::Instance#with
|
25
49
|
def with(&th)
|
26
|
-
@inst.with
|
50
|
+
@inst.with(&th)
|
27
51
|
end
|
28
52
|
|
29
53
|
module_function :get, :with
|
54
|
+
|
55
|
+
# @see Ruff::Standard::CurrentTime::Instance#eff
|
56
|
+
attr_reader :eff
|
30
57
|
end
|
data/lib/ruff/standard/defer.rb
CHANGED
@@ -1,16 +1,36 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# `Defer` provides effects `Defer.eff` ,
|
4
|
+
# and the implementation to defer procedures .
|
5
|
+
#
|
6
|
+
# The module has an instance of `Instance` and provides its methods as module method.
|
7
|
+
# @see Standard::Defer::Instance
|
3
8
|
module Ruff::Standard::Defer
|
4
9
|
class Instance
|
10
|
+
# makes a new instance.
|
5
11
|
def initialize
|
6
12
|
@eff = Ruff.instance
|
7
13
|
end
|
8
14
|
|
15
|
+
# is a smart method to invoke the effect operation.
|
16
|
+
# @param [Proc<(), ()>] prc
|
17
|
+
# is deferred, or "registerred", and called on the end of computation.
|
18
|
+
# @return [()]
|
9
19
|
def register(&prc)
|
10
20
|
@eff.perform prc
|
11
21
|
end
|
12
22
|
|
23
|
+
# is a handler to interpret the effect invocation as registering a procedure.
|
24
|
+
# Registerred procedures are run on the end of computation, by value handler.
|
25
|
+
#
|
26
|
+
# @param [Proc<(), A>!{Defer.eff, e}] th
|
27
|
+
# is a thunk returning `A` with the possibility to invoke effects, including `Defer.eff` .
|
28
|
+
#
|
29
|
+
# @return [A!{e}]
|
30
|
+
# returns `A` , without modification by value handler.
|
31
|
+
# But it still has the possibility to invoke effects(`e`).
|
13
32
|
def with(&th)
|
33
|
+
# This is a stack to store deferred procedures.
|
14
34
|
procs = []
|
15
35
|
|
16
36
|
Ruff.handler
|
@@ -19,22 +39,32 @@ module Ruff::Standard::Defer
|
|
19
39
|
k[]
|
20
40
|
end
|
21
41
|
.to do |_|
|
42
|
+
# Like Go's defer functions, it crashes the thunk by reversed order.
|
22
43
|
procs.reverse_each(&:[])
|
23
44
|
end
|
24
|
-
.run
|
45
|
+
.run(&th)
|
25
46
|
end
|
47
|
+
|
48
|
+
# You can reimplement the handler using this effect instance.
|
49
|
+
attr_reader :eff
|
26
50
|
end
|
27
51
|
|
28
52
|
# ---
|
29
53
|
@inst = Instance.new
|
54
|
+
@eff = @inst.eff
|
30
55
|
|
56
|
+
# @see Ruff::Standard::Defer::Instance#register
|
31
57
|
def register(&prc)
|
32
|
-
@inst.register
|
58
|
+
@inst.register(&prc)
|
33
59
|
end
|
34
60
|
|
61
|
+
# @see Ruff::Standard::Defer::Instance#with
|
35
62
|
def with(&th)
|
36
|
-
@inst.with
|
63
|
+
@inst.with(&th)
|
37
64
|
end
|
38
65
|
|
39
66
|
module_function :register, :with
|
67
|
+
|
68
|
+
# @see Ruff::Standard::Defer::Instance#eff
|
69
|
+
attr_reader :eff
|
40
70
|
end
|
data/lib/ruff/standard/state.rb
CHANGED
@@ -1,65 +1,120 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'ostruct'
|
4
|
+
|
5
|
+
# `State` provides effects `State.get` and `State.modify` ,
|
6
|
+
# and the implementation of the mutable cell or so-called *state* .
|
7
|
+
#
|
8
|
+
# The module has an instance of `Instance` and provides its methods as module method.
|
9
|
+
# @see Standard::State::Instance
|
3
10
|
module Ruff::Standard::State
|
4
11
|
class Instance
|
12
|
+
# makes new instances.
|
5
13
|
def initialize
|
6
|
-
|
7
|
-
|
14
|
+
get = Ruff.instance
|
15
|
+
modify = Ruff.instance
|
16
|
+
|
17
|
+
# delegates effect instances
|
18
|
+
@eff = OpenStruct.new(get: get, modify: modify)
|
8
19
|
end
|
9
20
|
|
21
|
+
# is a smart method to invoke the effect operation `State.get` .
|
22
|
+
# @return [S]
|
23
|
+
# with `with` , returns `S` , the current state.
|
10
24
|
def get
|
11
|
-
@get.perform
|
25
|
+
@eff.get.perform
|
12
26
|
end
|
13
27
|
|
28
|
+
# is a smart hetmod to invoke the effect operation `State.modify` .
|
29
|
+
# @param [Proc<S, U>] fn
|
30
|
+
# is the function to modify the state `S` to `U` .
|
31
|
+
# This function has an argument receiving the state.
|
32
|
+
# @return [()]
|
14
33
|
def modify(&fn)
|
15
|
-
@modify.perform fn
|
34
|
+
@eff.modify.perform fn
|
16
35
|
end
|
17
36
|
|
37
|
+
# is a short hand for `modify {|_| s }`
|
38
|
+
# @param [S] s
|
39
|
+
# is the new state.
|
40
|
+
# @return [()]
|
18
41
|
def put(s)
|
19
|
-
@modify.perform ->(_) { s }
|
42
|
+
@eff.modify.perform ->(_) { s }
|
20
43
|
end
|
21
44
|
|
22
|
-
|
45
|
+
# is a handler to interpret the effect invocations like *state monad* .
|
46
|
+
#
|
47
|
+
# @param [S] init
|
48
|
+
# is the initial state.
|
49
|
+
# @param [Proc<(), A!{State.get, State.modify,, e}>] th
|
50
|
+
# is a thunk returning `A` with the possibility to invoke effects,
|
51
|
+
# including `State.get` and `State.modify` .
|
52
|
+
# @return [A!{e}]
|
53
|
+
# returns `A` , without modification by value handler.
|
54
|
+
# But it still has the possibility to invoke effects(`e`).
|
55
|
+
def with_init(init, &th)
|
56
|
+
# not a parameter passing style, or so-called *pure* implementation,
|
57
|
+
# just using mutable assignment
|
23
58
|
state = init
|
24
59
|
|
25
60
|
Ruff.handler
|
26
|
-
.on(@modify) do |k, fn|
|
61
|
+
.on(@eff.modify) do |k, fn|
|
27
62
|
state = fn[state]
|
28
63
|
k[nil]
|
29
|
-
end
|
30
|
-
.on(@get) do |k|
|
64
|
+
end.on(@eff.get) do |k|
|
31
65
|
k[state]
|
32
66
|
end
|
33
|
-
.run
|
67
|
+
.run(&th)
|
34
68
|
end
|
35
69
|
|
36
|
-
|
37
|
-
|
70
|
+
# is a short hand for `with_init(nil, th)` .
|
71
|
+
#
|
72
|
+
# @param [Proc<(), A!{State.get, State.modify,, e}>] th
|
73
|
+
# is a thunk returning `A` with the possibility to invoke effects,
|
74
|
+
# including `State.get` and `State.modify` .
|
75
|
+
# @return [A!{e}]
|
76
|
+
# returns `A` , without modification by value handler.
|
77
|
+
# But it still has the possibility to invoke effects(`e`).
|
78
|
+
def with(&th)
|
79
|
+
with_init(nil, &th)
|
38
80
|
end
|
81
|
+
|
82
|
+
# You can reimplement the handler using these effect instances
|
83
|
+
# with accessing `#eff.get` and `#eff.modify` .
|
84
|
+
attr_reader :eff
|
39
85
|
end
|
40
86
|
|
41
87
|
# ---
|
42
88
|
@inst = Instance.new
|
89
|
+
@eff = @inst.eff
|
43
90
|
|
91
|
+
# @see Ruff::Standard::State::Instance#get
|
44
92
|
def get
|
45
93
|
@inst.get
|
46
94
|
end
|
47
95
|
|
96
|
+
# @see Ruff::Standard::State::Instance#modify
|
48
97
|
def modify(&fn)
|
49
|
-
@inst.modify
|
98
|
+
@inst.modify(&fn)
|
50
99
|
end
|
51
100
|
|
101
|
+
# @see Ruff::Standard::State::Instance#put
|
52
102
|
def put(s)
|
53
103
|
@inst.put s
|
54
104
|
end
|
55
105
|
|
106
|
+
# @see Ruff::Standard::State::Instance#with_init
|
56
107
|
def with_init(init, &task)
|
57
108
|
@inst.with_init init, &task
|
58
109
|
end
|
59
110
|
|
111
|
+
# @see Ruff::Standard::State::Instance#with
|
60
112
|
def with(&task)
|
61
|
-
@inst.with
|
113
|
+
@inst.with(&task)
|
62
114
|
end
|
63
115
|
|
64
116
|
module_function :get, :put, :modify, :with, :with_init
|
117
|
+
|
118
|
+
# @see Ruff::Standard::Instance#eff
|
119
|
+
attr_reader :eff
|
65
120
|
end
|