wrapper_based 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 860bb92daa686c64bcb7807cc743a0e1f41d892d
4
- data.tar.gz: 15482c725f191bc7fa9a336fddebbc10e71a3051
3
+ metadata.gz: ff350bc479ae984adc21032e70fab33aea8f1ce5
4
+ data.tar.gz: 281d02a14989a788d9b53ba6eb0b3f41c1ed86a6
5
5
  SHA512:
6
- metadata.gz: ab743403db24d5918f180321e2c6f45c93f5284c7d9bfab97038cf19b399abcb2d0f28870e98db9d0dc854d99e79a1afafa38e35288ccdb3c63285ab6718fbcb
7
- data.tar.gz: 817c1a3a8494e3d259df6602f59eaf15a6931208ea530333201895dc8c8c1bb124160e4e75712ca62bb675ca515654330a6d1795bc700949af2096a4b950012a
6
+ metadata.gz: 4b0f9bab7b974ff6a94b8be0e91e63f779f8df8c0fd6e6d959a4d28632c91ef85ad5382a0ec6521ed572d82e060e0e9add15117370649ebd298d5d669eac8330
7
+ data.tar.gz: 696723ab1d675cf1acb1cb9a6765823853bb84b31e95fe689dd4fcfe7afdf427c8bf9f00f7594c1316129675443366b22c3c424f2a760a457ab39722d4524b83
data/README.md CHANGED
@@ -34,22 +34,22 @@ module Map
34
34
  end
35
35
 
36
36
  def distance_of(path)
37
- Distance[within: self].of(path)
37
+ GetDistance[within: self].of(path)
38
38
  end
39
39
  end
40
40
 
41
41
  module CurrentIntersection
42
- def neighbors(nearest:)
43
- east_neighbor = nearest.east_neighbor_of(self)
44
- south_neighbor = nearest.south_neighbor_of(self)
45
- [south_neighbor, east_neighbor].compact
42
+ def neighbors(manhattan:)
43
+ east_neighbor = manhattan.east_neighbor_of(self)
44
+ south_neighbor = manhattan.south_neighbor_of(self)
45
+ [south_neighbor, east_neighbor].compact # excludes nil neighbors
46
46
  end
47
47
  end
48
48
 
49
49
  module DestinationNode
50
50
  def shortest_path(from:, within:)
51
51
  return [self] if equal? from
52
- Shortest[to: self, from: from, city: within].path
52
+ FindShortest[to: self, from: from, city: within].path
53
53
  end
54
54
  end
55
55
 
@@ -57,7 +57,7 @@ end
57
57
 
58
58
  DCI = WrapperBased::DCI.new unless defined? DCI
59
59
 
60
- class Distance < DCI::Context(:within)
60
+ class GetDistance < DCI::Context(:within)
61
61
  within.as Map
62
62
 
63
63
  def between(from, to)
@@ -69,7 +69,7 @@ class Distance < DCI::Context(:within)
69
69
  end
70
70
  end
71
71
 
72
- class Shortest < DCI::Context(:from, :to, :city)
72
+ class FindShortest < DCI::Context(:from, :to, :city)
73
73
  from.as CurrentIntersection
74
74
  to.as DestinationNode
75
75
  city.as Map
@@ -79,14 +79,14 @@ class Shortest < DCI::Context(:from, :to, :city)
79
79
  end
80
80
 
81
81
  def path
82
- _shortest_path + [@from]
82
+ shortest_path_from_city_neighbors << @from
83
83
  end
84
84
 
85
85
  private
86
86
 
87
- def _shortest_path
87
+ def shortest_path_from_city_neighbors
88
88
  from.
89
- neighbors(nearest: @city).
89
+ neighbors(manhattan: @city).
90
90
  map { |neighbor| to.shortest_path from: neighbor, within: @city }.
91
91
  min_by { |path| city.distance_of path }
92
92
  end
@@ -0,0 +1,27 @@
1
+ # Derived from https://tonyarcieri.com/dci-in-ruby-is-completely-broken
2
+ require 'rubygems'
3
+ require 'benchmark/ips'
4
+ require 'wrapper_based'
5
+
6
+ class ExampleClass
7
+ def foo; 42; end
8
+ end
9
+
10
+ module ExampleMixin
11
+ def foo; 43; end
12
+ end
13
+
14
+ wrapper = WrapperBased::FORWARDING[ExampleClass, ExampleMixin]
15
+
16
+ Benchmark.ips do |bm|
17
+ bm.report("without dci") { ExampleClass.new.foo }
18
+ bm.report("with wrapper") do
19
+ wrapper.new(ExampleClass.new).foo
20
+ end
21
+ bm.report("with extend") do
22
+ obj = ExampleClass.new
23
+ obj.extend(ExampleMixin)
24
+ obj.foo
25
+ end
26
+ bm.compare!
27
+ end
@@ -9,22 +9,22 @@ module Map
9
9
  end
10
10
 
11
11
  def distance_of(path)
12
- Distance[within: self].of(path)
12
+ GetDistance[within: self].of(path)
13
13
  end
14
14
  end
15
15
 
16
16
  module CurrentIntersection
17
- def neighbors(nearest:)
18
- east_neighbor = nearest.east_neighbor_of(self)
19
- south_neighbor = nearest.south_neighbor_of(self)
20
- [south_neighbor, east_neighbor].compact
17
+ def neighbors(manhattan:)
18
+ east_neighbor = manhattan.east_neighbor_of(self)
19
+ south_neighbor = manhattan.south_neighbor_of(self)
20
+ [south_neighbor, east_neighbor].compact # excludes nil neighbors
21
21
  end
22
22
  end
23
23
 
24
24
  module DestinationNode
25
25
  def shortest_path(from:, within:)
26
26
  return [self] if equal? from
27
- Shortest[to: self, from: from, city: within].path
27
+ FindShortest[to: self, from: from, city: within].path
28
28
  end
29
29
  end
30
30
 
@@ -32,7 +32,7 @@ end
32
32
 
33
33
  DCI = WrapperBased::DCI.new unless defined? DCI
34
34
 
35
- class Distance < DCI::Context(:within)
35
+ class GetDistance < DCI::Context(:within)
36
36
  within.as Map
37
37
 
38
38
  def between(from, to)
@@ -44,7 +44,7 @@ class Distance < DCI::Context(:within)
44
44
  end
45
45
  end
46
46
 
47
- class Shortest < DCI::Context(:from, :to, :city)
47
+ class FindShortest < DCI::Context(:from, :to, :city)
48
48
  from.as CurrentIntersection
49
49
  to.as DestinationNode
50
50
  city.as Map
@@ -54,14 +54,14 @@ class Shortest < DCI::Context(:from, :to, :city)
54
54
  end
55
55
 
56
56
  def path
57
- _shortest_path + [@from]
57
+ shortest_path_from_city_neighbors << @from
58
58
  end
59
59
 
60
60
  private
61
61
 
62
- def _shortest_path
62
+ def shortest_path_from_city_neighbors
63
63
  from.
64
- neighbors(nearest: @city).
64
+ neighbors(manhattan: @city).
65
65
  map { |neighbor| to.shortest_path from: neighbor, within: @city }.
66
66
  min_by { |path| city.distance_of path }
67
67
  end
@@ -1,4 +1,4 @@
1
- Log = method(:puts)
1
+ LogTransaction = method(:puts)
2
2
  Account = Struct.new(:number, :balance)
3
3
  NotEnoughFunds = Class.new(StandardError)
4
4
 
@@ -23,12 +23,12 @@ class TransferMoney < DCI::Context(:from, :to)
23
23
 
24
24
  def withdraw(amount)
25
25
  from.decrease_balance_by(amount)
26
- Log["Withdraw", amount, from]
26
+ LogTransaction["Withdraw", amount, from.number]
27
27
  end
28
28
 
29
29
  def deposit(amount)
30
30
  to.increase_balance_by(amount)
31
- Log["Deposit", amount, to]
31
+ LogTransaction["Deposit", amount, to.number]
32
32
  end
33
33
 
34
34
  def call(amount:)
@@ -1,7 +1,8 @@
1
1
  module WrapperBased
2
2
  class Context
3
3
  def initialize(**where)
4
- where.each { |role, player| instance_variable_set :"@#{role}", player }
4
+ @_casting = {}
5
+ where.each { |role, player| send :"#{role}=", player }
5
6
  end
6
7
 
7
8
  def to_proc
@@ -12,25 +13,32 @@ module WrapperBased
12
13
  call(*args, &block)
13
14
  end
14
15
 
16
+ UnassignedRole = StandardError
17
+
15
18
  class << self
16
19
  def [](**role_cast, &block)
17
20
  context_class = Class.new(self, &block)
18
21
 
19
22
  context_class.class_eval do
20
23
  role_cast.each do |role, cast|
21
- class_variable_set :"@@#{role}", cast
24
+ role_player = :"@#{role}"
25
+
26
+ define_method(:"#{role}=") do |actor|
27
+ instance_variable_set(role_player, actor)
28
+ @_casting[role] = context_class.send(role).typecast(actor)
29
+ end
30
+
22
31
  define_method(role) do
23
- self.class.class_variable_get(:"@@#{role}").
24
- typecast instance_variable_get(:"@#{role}")
32
+ @_casting.fetch(role) { fail UnassignedRole, "Role '#{role}' is missing." }
25
33
  end
26
34
  end
27
35
  end
28
36
 
29
37
  context_class.singleton_class.class_eval do
30
- role_cast.each do |role, _|
31
- define_method(role) do
32
- class_variable_get :"@@#{role}"
33
- end
38
+ role_cast.each do |role, cast|
39
+ variable = :"@@#{role}"
40
+ define_method(role) { class_variable_get variable }
41
+ context_class.class_variable_set variable, cast
34
42
  end
35
43
 
36
44
  alias_method :[], :new
@@ -1,3 +1,3 @@
1
1
  module WrapperBased
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wrapper_based
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ritchie Paul Buitre
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-06-16 00:00:00.000000000 Z
11
+ date: 2017-06-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -67,6 +67,7 @@ files:
67
67
  - Rakefile
68
68
  - bin/console
69
69
  - bin/setup
70
+ - examples/benchmark.rb
70
71
  - examples/dijkstra.rb
71
72
  - examples/dijkstra/data.rb
72
73
  - examples/money_transfer.rb