-
Notifications
You must be signed in to change notification settings - Fork 27
/
withnames.rb
148 lines (146 loc) · 3.17 KB
/
withnames.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
module Rserve
# Provides names to elements on an Array
module WithNames
attr_reader :names
def names=(v)
raise ArgumentError, "#{self}: names size #{v.size} should be equal to object size #{self.size}" if !v.nil? and v.size!=self.size
raise ArgumentError, "element must be String or nil" unless v.nil? or v.all? {|v1| v1.nil? or v1.is_a? String}
@names=v
end
def push(v,name=nil)
@names||=Array.new(self.size)
(@names.size-self.size).times { @names.push(nil)}
@names.push(name)
super(v)
end
def pretty_print(q)
q.group(1,'[|WN|',']') {
q.seplist(self,nil,:each_with_index) {|v,i|
if (@names.nil? or @names[i].nil?)
q.pp v
else
q.group {
q.pp @names[i]
q.text '='
q.group(1) { q.pp v }
}
end
}
}
end
def to_s
out=[]
self.each_with_index { |v,i|
if !@names.nil? and !@names[i].nil?
out.push("#{@names[i]}=#{v}")
else
out.push("#{v}")
end
}
"[#{out.join(", ")}]"
end
def inspect
"#<#{self.class}:#{self.object_id} #{to_s}>"
end
def clear
@names=nil
super()
end
def delete_at(i)
unless @names.nil?
@names.delete_at(i)
end
super(i)
end
def pop
unless @names.nil?
@names.pop
end
super
end
def reverse!
unless @names.nil?
@names.reverse!
end
super
end
def shift
unless @names.nil?
@names.shift
end
super
end
def slice(*args)
sliced=super(*args)
unless @names.nil?
sliced.extend Rserve::WithNames
sliced.names=@names.slice(*args)
end
sliced
end
def has_name?(v)
named? and @names.include? v
end
def named?
!@names.nil?
end
def to_a
Array.new(self)
end
def key_at(v)
@names.nil? ? nil : @names[v]
end
# Put a value on specific key
# If key exists, replaces element of apropiate index
# If key doesn't exists, works as push(value,key)
def put(key,value)
if key.nil?
add(value)
return nil
end
if !@names.nil?
pos=@names.index(key)
if !pos.nil?
return self[pos]=value
end
end
push(value,key)
end
def __add(a,b=nil)
if b.nil?
@data.push(a)
@names=Array.new(@data.size-1) if @names.nil?
@names.push(nil)
else
@data.insert(a,b)
@names.insert(a,nil)
end
end
def []=(i,v)
case i
when Integer
super(i,v)
when String
put(i,v)
else
raise "Should be Integer or String"
end
end
def [](v)
case v
when Integer
at(v)
when Array
raise "You must use something like v[[1]]" if v.size!=1 or !v[0].is_a? Integer
at(v[0]-1)
when String
if !@names.nil?
i=@names.index(v)
i.nil? ? nil : at(i)
else
nil
end
end
end
end
end