Class: Yzz::Side

Inherits:
Object show all
Defined in:
lib/yzz/side.rb

Overview

Ted Nelson calls objects in a ZZ structure ‘cells’ and defines that each cell has exactly two sides, posward side and negward side, along each dimension. This is represented by Yzz::Side class here.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(zz: ( fail ArgumentError, ":zz missing!" ), dimension: ( fail ArgumentError, ":dimension missing!" ), direction: ( fail ArgumentError, ":direction missing!" ), neighbor: nil) ⇒ Side

The constructor expects 3 arguments: :zz, :dimension, :direction, plus 1 optional argument, :neighbor.



11
12
13
14
15
16
17
18
19
20
# File 'lib/yzz/side.rb', line 11

def initialize( zz: ( fail ArgumentError, ":zz missing!" ),
                dimension: ( fail ArgumentError, ":dimension missing!" ),
                direction: ( fail ArgumentError, ":direction missing!" ),
                neighbor: nil )
  fail TypeError, "Wrong :zz type!" unless zz.is_a_zz?
  @zz, @dimension, @direction = zz, dimension, direction.to_sym
  fail TypeError, "Direction must be either :posward or :negward!" unless
    [ :posward, :negward ].include? direction.to_sym
  set_neighbor! neighbor
end

Instance Attribute Details

#dimensionObject (readonly)

Returns the value of attribute dimension.



6
7
8
# File 'lib/yzz/side.rb', line 6

def dimension
  @dimension
end

#directionObject (readonly)

Returns the value of attribute direction.



6
7
8
# File 'lib/yzz/side.rb', line 6

def direction
  @direction
end

#neighborObject (readonly)

Returns the value of attribute neighbor.



6
7
8
# File 'lib/yzz/side.rb', line 6

def neighbor
  @neighbor
end

#zzObject (readonly)

Returns the value of attribute zz.



6
7
8
# File 'lib/yzz/side.rb', line 6

def zz
  @zz
end

Instance Method Details

#crossover(new_neighbor) ⇒ Object Also known as: *

Sets a new neighboor, crossing over the conflicting link, if present, with the old neighbor.



45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/yzz/side.rb', line 45

def crossover new_neighbor
  return unlink if new_neighbor.nil?
  fail TypeError, "Zz object or nil expected!" unless new_neighbor.is_a_zz?
  conflicter = opposite_side( of: new_neighbor ).neighbor
  return new_neighbor if conflicter == self # no neighbor change
  begin # TODO: Should be an atomic transaction
    old_neighbor = set_neighbor! new_neighbor
    opposite_side( of: new_neighbor ).set_neighbor! zz
    same_side( of: conflicter ).set_neighbor! old_neighbor # cross over
    opposite_side( of: old_neighbor ).set_neighbor! conflicter # cross over
  end
  return old_neighbor
end

#inspectObject

Inspect string of the instance.



93
94
95
# File 'lib/yzz/side.rb', line 93

def inspect
  to_s
end

#labelObject

Returns the “side label” string.



81
82
83
# File 'lib/yzz/side.rb', line 81

def label
  direction == :posward ? "#{dimension}->" : "<-#{dimension}"
end

Links a new neighbor, unlinking and returning the old one. Cares about the argument type (a Yzz descendant or nil), and cares not to break the new neighbor’s conflicting connectivity, if any.



26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/yzz/side.rb', line 26

def link new_neighbor
  return unlink if new_neighbor.nil?
  fail TypeError, "Yzz object or nil expected!" unless new_neighbor.is_a_zz?
  conflicter = opposite_side( of: new_neighbor ).neighbor # have concerns
  return new_neighbor if conflicter == self               # no neighbor change
  fail TypeError, "Suggested new neighbor (#{new_neighbor}) already " +
    "has a conflicting #{OPPOSITE[direction]} link along dimension " +
    "#{dimension}!" if conflicter.is_a_zz?
  begin # TODO: Should be an atomic transaction
    old_neighbor = set_neighbor! new_neighbor
    opposite_side( of: new_neighbor ).set_neighbor! zz
  end
  return old_neighbor
end

#opposite_side(of: zz) ⇒ Object

Given a Yzz object, returns its side along the dimension same as the receiver’s dimension, in the direction opposite to self.



63
64
65
66
67
68
69
# File 'lib/yzz/side.rb', line 63

def opposite_side( of: zz )
  opposite = case direction
             when :posward then :negward
             when :negward then :posward
             else fail "Unknown direction!" end
  of.along( dimension ).send( opposite )
end

#to_sObject

Returns the string briefly describing the instance.



87
88
89
# File 'lib/yzz/side.rb', line 87

def to_s
  "#<Yzz::Side: #{zz} along #{dimension}, #{direction}>"
end

Unlinks the neighbor, returning it.



73
74
75
76
77
# File 'lib/yzz/side.rb', line 73

def unlink
  unlink!.tap do |neighbor|
    opposite_side( of: neighbor ).unlink! if neighbor.is_a_zz?
  end
end