ruff 0.0.4 → 0.0.5

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.
@@ -6,10 +6,23 @@ require 'securerandom'
6
6
 
7
7
  module Ruff
8
8
  class << self
9
+ # is alias for `Effect.new`
10
+ # @see Effect.initialize Effect.initialize
11
+ #
12
+ # @example
13
+ # Log = Ruff.instance # === Ruff::Effect.new
9
14
  def instance
10
15
  Effect.new
11
16
  end
12
17
 
18
+ # is alias for `Handler.new`
19
+ # @see Handler.initialize Handler.initialize
20
+ #
21
+ # @example
22
+ # log_handler = Ruff.handler.on(Log){|msg, k|
23
+ # puts "Logger: #{msg}"
24
+ # k[]
25
+ # }
13
26
  def handler
14
27
  Handler.new
15
28
  end
@@ -1,12 +1,25 @@
1
1
  module Ruff
2
+ # This class provides an effect instance.
2
3
  class Effect
3
- attr_accessor :id
4
+ # Each instance must be unique so they have unique id with UUID
5
+ attr_reader :id
6
+
7
+ # instaciates an effect setting `id`.
8
+ # @return [Effect<Arg, Ret>]
9
+ # @example
10
+ # Log = Effect.new #==> it _might_ be Effect<string, nil>
4
11
  def initialize
5
12
  @id = SecureRandom.uuid
13
+ @id.freeze
6
14
  end
7
15
 
16
+ # sends an effect ID and its arguments to a nearmost handler.
17
+ # @param [Arg] a of the object `Effect<Arg, Ret>`
18
+ # @return [Ret] of the object `Effect<Arg, Ret>`
19
+ # @example
20
+ # Log.perform "hello"
8
21
  def perform(*a)
9
- return Fiber.yield Eff.new(@id, a)
22
+ return Fiber.yield Throws::Eff.new(@id, a)
10
23
  end
11
24
  end
12
25
  end
@@ -1,32 +1,72 @@
1
1
  module Ruff
2
+ # In algebraic effects, handler is an first-class object.
2
3
  class Handler
4
+ # makes a new handler, internally having fresh empty hash.
5
+ # This is a effect-handler store and when handliong it is looked up.
6
+ # @example
7
+ # handler = Handler.new
3
8
  def initialize
4
9
  @handlers = Hash.new
5
10
  end
6
11
 
12
+ # sets effec handler `&prc` for `eff`
13
+ #
14
+ # @param [Effect<Arg, Ret>] eff
15
+ # the effect instance to be handled
16
+ # @param [Proc<Arg, Ret => A>] prc
17
+ # a handler to handle `eff`;
18
+ # last argument of `&prc` is *continuation*, proc object
19
+ # to go back to the handled computation.
20
+ # @return [Handler{Effect<Arg, Ret>, e}] itself updated with handling `Effect<Arg, Ret>`
21
+ #
22
+ # @example
23
+ # handler.on(Log) {|msg, k|
24
+ # puts "Logger: #{msg}"
25
+ # k[]
26
+ # }
7
27
  def on(eff, &prc)
8
28
  @handlers[eff.id] = prc
9
29
 
10
30
  self
11
31
  end
12
32
 
33
+ # @param [Proc<(), T>]
34
+ # @return [T]
35
+ #
36
+ # handles the computation.
37
+ #
38
+ # @example
39
+ # handler.run {
40
+ # Log.perform "hello"
41
+ # }
42
+ #
43
+ # @example `handler` can be layered.
44
+ # handler.run {
45
+ # Handler.new
46
+ # .on(Double){|v, k|
47
+ # k[v * v]
48
+ # }.run {
49
+ # v = Double.perform 3
50
+ # Log.perform 3
51
+ # }
52
+ # }
13
53
  def run(&prc)
14
54
  co = Fiber.new &prc
15
55
  continue = nil
16
56
  rehandles = nil
17
57
 
18
58
  handle = ->(r) {
19
- if r.is_a? Eff
59
+ if r.is_a? Throws::Eff
20
60
  if effh = @handlers[r.id]
21
61
  effh[continue, *r.args]
22
62
  else
23
- Fiber.yield (Resend.new r, continue)
63
+ Fiber.yield (Throws::Resend.new r, continue)
24
64
  end
25
- elsif r.is_a? Resend
65
+ elsif r.is_a? Throws::Resend
26
66
  if effh = @handlers[r.eff.id]
27
67
  effh[rehandles[r.k], *r.eff.args]
28
68
  else
29
- Fiber.yield (Resend.new r, rehandles[r.k])
69
+ Fiber.yield (Throws::Resend.new r, rehandles[r.k])
30
70
  end
31
71
  else
32
72
  r
@@ -43,6 +83,10 @@ module Ruff
43
83
  newh.add_handler id, h
44
84
  }
45
85
 
86
+ class << newh
87
+ undef add_handler
88
+ end
89
+
46
90
  ->(*args) {
47
91
  continue[
48
92
  newh.run {
@@ -1,15 +1,39 @@
1
1
  module Ruff
2
- class Eff
3
- attr_accessor :id, :args
4
- def initialize(id, args)
5
- @id = id; @args = args
2
+ module Throws
3
+ # `Eff` is internal object.
4
+ #
5
+ # They make effects encapsulate with ID and arguments to be sent to the handler.
6
+ class Eff
7
+
8
+ # makes the object unique.
9
+ attr_reader :id
10
+
11
+ # passes to a handler which can catch the effect.
12
+ attr_reader :args
13
+
14
+ # creates a new object with `id` and `args`.
15
+ def initialize(id, args)
16
+ @id = id; @args = args
17
+ end
6
18
  end
7
19
  end
8
20
 
9
- class Resend
10
- attr_accessor :eff, :k
11
- def initialize(eff, k)
12
- @eff = eff; @k = k
21
+ module Throws
22
+ # `Resend` is internal object like `Eff`.
23
+ #
24
+ # It is used when an effect is unable to be handled and should be thrown to the outer handler.
25
+ class Resend
26
+
27
+ #is abstracted effect (such as `Eff` or (re)thrown `Resend`).
28
+ attr_reader :eff
29
+
30
+ # is a continuation of `eff` thrown context.
31
+ attr_reader :k
32
+
33
+ # creates a new object with `eff` and `k`.
34
+ def initialize(eff, k)
35
+ @eff = eff; @k = k
36
+ end
13
37
  end
14
38
  end
15
39
  end
@@ -0,0 +1,5 @@
1
+ # // This file is passed to CPP
2
+ #include "../../version.h"
3
+ module Ruff
4
+ VERSION = RUFF_VERSION
5
+ end
@@ -1,3 +1,3 @@
1
1
  module Ruff
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
@@ -3,7 +3,7 @@ lib = File.expand_path("../lib", __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require "ruff/version"
5
5
 
6
- Gem::Specification.new do |spec|
6
+ Gem::Specification.new{|spec|
7
7
  spec.name = "ruff"
8
8
  spec.version = Ruff::VERSION
9
9
  spec.authors = ["nymphium"]
@@ -13,14 +13,17 @@ Gem::Specification.new do |spec|
13
13
  spec.description = %q{ONE-SHOT Algebraic Effects for Ruby!}
14
14
  spec.homepage = "https://github.com/nymphium/ruff"
15
15
  spec.license = "MIT"
16
+
16
17
 
17
18
  spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
18
19
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
20
  end
20
- spec.bindir = "exe"
21
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
21
  spec.require_paths = ["lib"]
23
22
 
24
23
  spec.add_development_dependency "bundler", "~> 2.0"
25
24
  spec.add_development_dependency "rake", "~> 10.0"
26
- end
25
+
26
+ spec.metadata = {
27
+ "documentation_url" => "https://nymphium.github.io/ruff"
28
+ }
29
+ }
@@ -0,0 +1 @@
1
+ #define RUFF_VERSION "0.0.5"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruff
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - nymphium
8
8
  autorequire:
9
- bindir: exe
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-06 00:00:00.000000000 Z
11
+ date: 2019-08-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -51,16 +51,39 @@ files:
51
51
  - LICENSE
52
52
  - README.md
53
53
  - Rakefile
54
+ - docs/Ruff.html
55
+ - docs/Ruff/Effect.html
56
+ - docs/Ruff/Handler.html
57
+ - docs/Ruff/Throws.html
58
+ - docs/Ruff/Throws/Eff.html
59
+ - docs/Ruff/Throws/Resend.html
60
+ - docs/_index.html
61
+ - docs/class_list.html
62
+ - docs/css/common.css
63
+ - docs/css/full_list.css
64
+ - docs/css/style.css
65
+ - docs/file.README.html
66
+ - docs/file_list.html
67
+ - docs/frames.html
68
+ - docs/index.html
69
+ - docs/js/app.js
70
+ - docs/js/full_list.js
71
+ - docs/js/jquery.js
72
+ - docs/method_list.html
73
+ - docs/top-level-namespace.html
54
74
  - lib/ruff.rb
55
75
  - lib/ruff/effect.rb
56
76
  - lib/ruff/handler.rb
57
77
  - lib/ruff/objects.rb
78
+ - lib/ruff/version.cpp.rb
58
79
  - lib/ruff/version.rb
59
80
  - ruff.gemspec
81
+ - version.h
60
82
  homepage: https://github.com/nymphium/ruff
61
83
  licenses:
62
84
  - MIT
63
- metadata: {}
85
+ metadata:
86
+ documentation_url: https://nymphium.github.io/ruff
64
87
  post_install_message:
65
88
  rdoc_options: []
66
89
  require_paths: