yzz 2.0.11 → 2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bda3a0b18dda005b0b0d54a41dc9908c573dde80
4
- data.tar.gz: 26f8361a80470e97fa4b834e143554f482629b10
3
+ metadata.gz: f0090b2be4794a0cc39d852aa7a99f3f359802ed
4
+ data.tar.gz: 0a58007a6dc23b65ac78d6825443cef1777c20fe
5
5
  SHA512:
6
- metadata.gz: ed056ee307f1f2117d32ddb2db2f3b0b3a36afdee85b05eb22b37d04af1fbfd9da8a14568a228c530ca5b8709db346a25f24c7d3c6a629e5b88103b3ad1cecd1
7
- data.tar.gz: 95608ce640a6c937454e0db378fe80fb1c8f8932b2896be4729ad382181caabeee451953af5b408a735ac18b5d887f24f1df35fd0df5b7d24e1f922c29f215ac
6
+ metadata.gz: cd37148cea5bb9840e9066aea9c47b7799d1c260035353f4118d09fcd3521f3c51fea0a4ed0a2c5b7991bba7fe9dc0e47c2ed7885bdd3f59539385e0eb8526b8
7
+ data.tar.gz: f31e4e33755aa01f1ed8129ca185ed2996ac1e6d91799203f569d6a201530e26f1cd4dd54751cf1e9a13b0dfb223cabe4da93c0444a47d2651d2718f9dbb07cf
data/lib/yzz.rb CHANGED
@@ -2,8 +2,13 @@
2
2
 
3
3
  require_relative "yzz/version"
4
4
  require_relative "yzz/side"
5
+ require_relative "yzz/posward_side"
6
+ require_relative "yzz/negward_side"
5
7
  require_relative "yzz/side_pair"
6
8
 
9
+ require "y_support/core_ext/object"
10
+ require "y_support/core_ext/class"
11
+
7
12
  # Module Yzz is a mixin that provides qualities of a ZZ structure cell to its
8
13
  # includers.
9
14
  #
@@ -28,29 +33,57 @@ require_relative "yzz/side_pair"
28
33
  # in <em>y_nelson</em> gem.
29
34
  #
30
35
  module Yzz
31
- # Adds initialization of the @zz_dimensions hash to #initialize.
36
+ # A hash whose #[] method expects a dimension as an argument and returns
37
+ # a dimension-specific mixin.
38
+ #
39
+ Dimensions = Hash.new { |ꜧ, missing_dimension|
40
+ ꜧ[ missing_dimension ] = Module.new do
41
+ define_singleton_method :dimension do missing_dimension end
42
+ define_method :dimension do missing_dimension end
43
+ end
44
+ }
45
+
46
+ # An accessor method for a dimension-specific mixin from Yzz::Dimensions hash.
47
+ #
48
+ def self.Dimension dimension
49
+ Dimensions[ dimension ]
50
+ end
51
+
52
+ # A reader method that returns a hash whose #[] method returns an appropriate
53
+ # side pair for a supplied dimension. The hash is constructed upon first call
54
+ # of the reader. This reader subsequently redefines itself (shadows itself with
55
+ # a newly defined singleton method) so as to always simply return the same hash.
56
+ #
57
+ def zz_dimensions
58
+ Hash.new { |ꜧ, missing_dimension|
59
+ ꜧ[ missing_dimension ] = Class.new SidePair() do
60
+ include ::Yzz.Dimension missing_dimension # ::Yzz just in case
61
+ end.new
62
+ }.tap { |ꜧ| define_singleton_method :zz_dimensions do ꜧ end }
63
+ end
64
+
65
+ # A reader method that returns a parametrized subclass of Yzz::SidePair. This
66
+ # reader subsequently redefines itself (shadows itself with a newly defined
67
+ # singleton method) so as to always simply return the same parametrized
68
+ # subclass.
32
69
  #
33
- def initialize *args
34
- @zz_dimensions = Hash.new { |ꜧ, missing_dimension|
35
- ꜧ[ missing_dimension ] = Yzz::SidePair
36
- .new( zz: self, dimension: missing_dimension )
37
- } # initialize the @zz_dimensions hash
38
- super # and proceed as usual
70
+ def SidePair
71
+ SidePair.parametrize( zz: self )
72
+ .tap { |ç| define_singleton_method :SidePair do ç end }
39
73
  end
40
74
 
41
75
  # Returns a SidePair instance along the requested dimension.
42
76
  #
43
77
  def along dimension
44
- @zz_dimensions[ dimension ]
78
+ zz_dimensions[ dimension ]
45
79
  end
46
80
 
47
81
  # Returns all sides actually connected to a zz object.
48
82
  #
49
83
  def connections
50
- @zz_dimensions.map { |_, pair| [ pair.negward, pair.posward ] }
84
+ zz_dimensions.map { |_, pair| [ pair.negward, pair.posward ] }
51
85
  .reduce( [], :+ ).select { |side| side.neighbor.is_a_zz? }
52
86
  end
53
- alias connectivity connections
54
87
 
55
88
  # Returns all neighbors of a zz object.
56
89
  #
@@ -63,7 +96,7 @@ module Yzz
63
96
  # more than 1 dimension.
64
97
  #
65
98
  def towards other
66
- connectivity.select { |side| side.neighbor == other }
99
+ connections.select { |side| side.neighbor == other }
67
100
  end
68
101
 
69
102
  # Prints the labels of the sides facing towards a given zz object.
@@ -72,7 +105,7 @@ module Yzz
72
105
  puts towards( other ).map &:label
73
106
  end
74
107
 
75
- # Short string describing the object.
108
+ # A string describing the object with respect to its zz qualities.
76
109
  #
77
110
  def to_s
78
111
  "#<Yzz, #{connections.size} conn.>"
@@ -0,0 +1,41 @@
1
+ # Separate class for negward sides of zz objects.
2
+ #
3
+ class Yzz::NegwardSide
4
+ include Yzz::Side
5
+
6
+ # The direction of a NegwardSide is always :negward.
7
+ #
8
+ def direction; :negward end
9
+
10
+ # Opposite direction of a NegwardSide is always :negward.
11
+ #
12
+ def opposite_direction; :posward end
13
+
14
+ # Given a +Yzz+ object, returns its negward side along the dimension same
15
+ # as the receiver's dimension. If no object is given, the method simply
16
+ # returns the receiver.
17
+ #
18
+ def same_side( of: zz )
19
+ of.along( dimension ).negward
20
+ end
21
+
22
+ # Given a +Yzz+ object, returns its posward side along the dimension same
23
+ # as the receiver's dimension. If no object is given, posward side opposite
24
+ # to the receiver is returned.
25
+ #
26
+ def opposite_side( of: zz )
27
+ of.along( dimension ).posward
28
+ end
29
+
30
+ # Returns the "side label" string.
31
+ #
32
+ def label
33
+ "<-#{dimension}"
34
+ end
35
+
36
+ # Returns the string briefly describing the instance.
37
+ #
38
+ def to_s
39
+ "#<Yzz::NegwardSide of #{zz} along #{dimension}>"
40
+ end
41
+ end # class Yzz::NegwardSide
@@ -0,0 +1,41 @@
1
+ # Separate class for posward sides of zz objects.
2
+ #
3
+ class Yzz::PoswardSide
4
+ include Yzz::Side
5
+
6
+ # The direction of a PoswardSide is always :posward.
7
+ #
8
+ def direction; :posward end
9
+
10
+ # Opposite direction of a PoswardSide is always :negward.
11
+ #
12
+ def opposite_direction; :posward end
13
+
14
+ # Given a +Yzz+ object, returns its posward side along the dimension same
15
+ # as the receiver's dimension. If no object is given, the method simply
16
+ # returns the receiver.
17
+ #
18
+ def same_side( of: zz )
19
+ of.along( dimension ).posward
20
+ end
21
+
22
+ # Given a +Yzz+ object, returns its negward side along the dimension same
23
+ # as the receiver's dimension. If no object is given, negward side opposite
24
+ # to the receiver is returned.
25
+ #
26
+ def opposite_side( of: zz )
27
+ of.along( dimension ).negward
28
+ end
29
+
30
+ # Returns the "side label" string.
31
+ #
32
+ def label
33
+ "#{dimension}->"
34
+ end
35
+
36
+ # Returns the string briefly describing the instance.
37
+ #
38
+ def to_s
39
+ "#<Yzz::PoswardSide of #{zz} along #{dimension}>"
40
+ end
41
+ end # class Yzz::PoswardSide
@@ -2,34 +2,35 @@
2
2
  # has exactly two sides, posward side and negward side, along each dimension.
3
3
  # This is represented by +Yzz::Side+ class here.
4
4
  #
5
- class Yzz::Side
6
- attr_reader :zz, :dimension, :direction, :neighbor
5
+ module Yzz::Side
6
+ attr_reader :neighbor
7
7
 
8
- # The constructor expects 3 arguments: +:zz+, +:dimension+, +:direction+,
9
- # plus 1 optional argument, +:neighbor+.
8
+ # Reader #zz delegates to the class, relying on parametrized subclassing.
9
+ #
10
+ def zz; self.class.zz end
11
+
12
+ # Reader #dimension delegates to the class, relying on parametrized
13
+ # subclassing.
14
+ #
15
+ def dimension; self.class.dimension end
16
+
17
+ # The constructor has one optional named parameter :neighbor.
10
18
  #
11
- def initialize( zz: ( fail ArgumentError, ":zz missing!" ),
12
- dimension: ( fail ArgumentError, ":dimension missing!" ),
13
- direction: ( fail ArgumentError, ":direction missing!" ),
14
- neighbor: nil )
15
- fail TypeError, "Wrong :zz type!" unless zz.is_a_zz?
16
- @zz, @dimension, @direction = zz, dimension, direction.to_sym
17
- fail TypeError, "Direction must be either :posward or :negward!" unless
18
- [ :posward, :negward ].include? direction.to_sym
19
+ def initialize neighbor: nil
19
20
  set_neighbor! neighbor
20
21
  end
21
22
 
22
23
  # Links a new neighbor, unlinking and returning the old one. Cares about the
23
24
  # argument type (a Yzz descendant or _nil_), and cares not to break the new
24
25
  # neighbor's conflicting connectivity, if any.
25
- #
26
+ #
26
27
  def link new_neighbor
27
28
  return unlink if new_neighbor.nil?
28
29
  fail TypeError, "Yzz object or nil expected!" unless new_neighbor.is_a_zz?
29
30
  conflicter = opposite_side( of: new_neighbor ).neighbor # have concerns
30
31
  return new_neighbor if conflicter == self # no neighbor change
31
32
  fail TypeError, "Suggested new neighbor (#{new_neighbor}) already " +
32
- "has a conflicting #{OPPOSITE[direction]} link along dimension " +
33
+ "has a conflicting #{opposite_direction} link along dimension " +
33
34
  "#{dimension}!" if conflicter.is_a_zz?
34
35
  begin # TODO: Should be an atomic transaction
35
36
  old_neighbor = set_neighbor! new_neighbor
@@ -57,37 +58,14 @@ class Yzz::Side
57
58
  end
58
59
  alias * crossover
59
60
 
60
- # Given a +Yzz+ object, returns its side along the dimension same as the
61
- # receiver's dimension, in the direction opposite to self.
62
- #
63
- def opposite_side( of: zz )
64
- opposite = case direction
65
- when :posward then :negward
66
- when :negward then :posward
67
- else fail "Unknown direction!" end
68
- of.along( dimension ).send( opposite )
69
- end
70
-
71
61
  # Unlinks the neighbor, returning it.
72
- #
62
+ #
73
63
  def unlink
74
64
  unlink!.tap do |neighbor|
75
65
  opposite_side( of: neighbor ).unlink! if neighbor.is_a_zz?
76
66
  end
77
67
  end
78
68
 
79
- # Returns the "side label" string.
80
- #
81
- def label
82
- direction == :posward ? "#{dimension}->" : "<-#{dimension}"
83
- end
84
-
85
- # Returns the string briefly describing the instance.
86
- #
87
- def to_s
88
- "#<Yzz::Side: #{zz} along #{dimension}, #{direction}>"
89
- end
90
-
91
69
  # Inspect string of the instance.
92
70
  #
93
71
  def inspect
@@ -107,4 +85,4 @@ class Yzz::Side
107
85
  def unlink!
108
86
  set_neighbor! nil
109
87
  end
110
- end # class Yzz::Side
88
+ end # module Yzz::Side
@@ -2,32 +2,41 @@
2
2
  # of a Yzz cell along a certain dimension.
3
3
  #
4
4
  class Yzz::SidePair
5
- attr_reader :zz, :dimension, :negward, :posward
5
+ attr_reader :negward, :posward
6
6
  alias p posward
7
7
  alias n negward
8
8
 
9
- def initialize( zz: ( raise ArgumentError, ":zz missing!" ),
10
- dimension: ( raise ArgumentError, ":dimension missing!" ),
11
- negward_neighbor: nil,
12
- posward_neighbor: nil )
13
- @zz, @dimension = zz, dimension
14
- @negward = Yzz::Side.new( zz: zz,
15
- dimension: dimension,
16
- direction: :negward,
17
- neighbor: negward_neighbor )
18
- @posward = Yzz::Side.new( zz: zz,
19
- dimension: dimension,
20
- direction: :posward,
21
- neighbor: posward_neighbor )
9
+ # Reader #zz delegates to the class, relying on parametrized subclassing.
10
+ #
11
+ def zz
12
+ self.class.zz
13
+ end
14
+
15
+ # Reader #dimension delegates to the class, relying on parametrized
16
+ # subclassing.
17
+ #
18
+ def dimension
19
+ self.class.dimension
20
+ end
21
+
22
+ # Takes two optional named parameters, :negward_neighbor and :posward_neigbor.
23
+ # If not given, the sides are constructed not linked to any neigbors.
24
+ #
25
+ def initialize( negward_neighbor: nil, posward_neighbor: nil )
26
+ param_class!( { NegwardSide: ::Yzz::NegwardSide,
27
+ PoswardSide: ::Yzz::PoswardSide },
28
+ with: { zz: zz, dimension: dimension } )
29
+ @negward = NegwardSide().new( neighbor: negward_neighbor )
30
+ @posward = PoswardSide().new( neighbor: posward_neighbor )
22
31
  end
23
32
 
24
- # Links a neighbor posward.
33
+ # Makes the supplied object the posward neighbor of the receiver.
25
34
  #
26
35
  def >> new_neighbor
27
36
  new_neighbor.along( dimension ).tap { posward << new_neighbor }
28
37
  end
29
38
 
30
- # Crossovers a new neighbor posward.
39
+ # Crossovers the supplied zz object posward.
31
40
  #
32
41
  def * new_neighbor
33
42
  posward * new_neighbor
@@ -1,3 +1,3 @@
1
1
  module Yzz
2
- VERSION = "2.0.11"
2
+ VERSION = "2.1.0"
3
3
  end
@@ -41,12 +41,6 @@ describe Yzz do
41
41
  end
42
42
 
43
43
  describe 'more advanced zz object behavior' do
44
- it "has #same_side" do
45
- zz = @ç.new
46
- assert_equal zz.along(:row).p, @a.along(:row).p.same_side( of: zz )
47
- assert_equal zz.along(:row).n, @a.along(:row).n.same_side( of: zz )
48
- end
49
-
50
44
  it "works" do
51
45
  a, b, c = @ç.new, @ç.new, @ç.new
52
46
  assert ( b.along(:row).posward << c ).nil?
@@ -18,6 +18,10 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
+ spec.add_dependency "y_support"
22
+
21
23
  spec.add_development_dependency "bundler", "~> 1.6"
22
24
  spec.add_development_dependency "rake"
25
+
26
+ spec.required_ruby_version = '>= 2.0'
23
27
  end
metadata CHANGED
@@ -1,41 +1,55 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yzz
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.11
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - boris
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-23 00:00:00.000000000 Z
11
+ date: 2014-10-14 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: y_support
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: bundler
15
29
  requirement: !ruby/object:Gem::Requirement
16
30
  requirements:
17
- - - ~>
31
+ - - "~>"
18
32
  - !ruby/object:Gem::Version
19
33
  version: '1.6'
20
34
  type: :development
21
35
  prerelease: false
22
36
  version_requirements: !ruby/object:Gem::Requirement
23
37
  requirements:
24
- - - ~>
38
+ - - "~>"
25
39
  - !ruby/object:Gem::Version
26
40
  version: '1.6'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rake
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
- - - '>='
45
+ - - ">="
32
46
  - !ruby/object:Gem::Version
33
47
  version: '0'
34
48
  type: :development
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
- - - '>='
52
+ - - ">="
39
53
  - !ruby/object:Gem::Version
40
54
  version: '0'
41
55
  description: Mixin Yzz imbues the includer with qualities of a ZZ structure cell.
@@ -45,12 +59,14 @@ executables: []
45
59
  extensions: []
46
60
  extra_rdoc_files: []
47
61
  files:
48
- - .gitignore
62
+ - ".gitignore"
49
63
  - Gemfile
50
64
  - LICENSE.txt
51
65
  - README.md
52
66
  - Rakefile
53
67
  - lib/yzz.rb
68
+ - lib/yzz/negward_side.rb
69
+ - lib/yzz/posward_side.rb
54
70
  - lib/yzz/side.rb
55
71
  - lib/yzz/side_pair.rb
56
72
  - lib/yzz/version.rb
@@ -66,17 +82,17 @@ require_paths:
66
82
  - lib
67
83
  required_ruby_version: !ruby/object:Gem::Requirement
68
84
  requirements:
69
- - - '>='
85
+ - - ">="
70
86
  - !ruby/object:Gem::Version
71
- version: '0'
87
+ version: '2.0'
72
88
  required_rubygems_version: !ruby/object:Gem::Requirement
73
89
  requirements:
74
- - - '>='
90
+ - - ">="
75
91
  - !ruby/object:Gem::Version
76
92
  version: '0'
77
93
  requirements: []
78
94
  rubyforge_project:
79
- rubygems_version: 2.0.14
95
+ rubygems_version: 2.2.2
80
96
  signing_key:
81
97
  specification_version: 4
82
98
  summary: A domain model of Ted Nelson's ZZ structures.