prototype 0.1.0 → 0.2.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.
- data/README +164 -76
- data/README.tmpl +24 -0
- data/gemspec.rb +1 -0
- data/gen_readme.rb +32 -0
- data/lib/prototype-0.2.0.rb +177 -0
- data/lib/prototype.rb +125 -129
- data/prototype-0.2.0.gem +0 -0
- data/samples/h.rb +11 -0
- metadata +18 -4
- data/lib/prototype-0.0.0.rb +0 -181
data/README
CHANGED
@@ -9,7 +9,7 @@ URIS
|
|
9
9
|
|
10
10
|
SYNOPSIS
|
11
11
|
|
12
|
-
prototype.rb
|
12
|
+
prototype.rb facilitates a prototype based coding style
|
13
13
|
|
14
14
|
http://en.wikipedia.org/wiki/Prototype-based_programming
|
15
15
|
|
@@ -19,117 +19,205 @@ WHY
|
|
19
19
|
|
20
20
|
prototype based programming can look very nice ;-)
|
21
21
|
|
22
|
-
|
22
|
+
SAMPLES
|
23
23
|
|
24
|
-
|
25
|
-
~ > cat samples/a.rb
|
26
|
-
__________________________________________
|
27
|
-
require 'prototype'
|
28
|
-
|
29
|
-
singleton = Prototype.new{
|
30
|
-
@a, @b = 40, 2
|
24
|
+
<========< samples/a.rb >========>
|
31
25
|
|
32
|
-
|
33
|
-
}
|
34
|
-
|
35
|
-
p singleton.answer
|
26
|
+
~ > cat samples/a.rb
|
36
27
|
|
28
|
+
require 'prototype'
|
29
|
+
|
30
|
+
singleton = Prototype.new{
|
31
|
+
@a, @b = 40, 2
|
32
|
+
|
33
|
+
def answer() @a + @b end
|
34
|
+
}
|
35
|
+
|
36
|
+
p singleton.answer
|
37
37
|
|
38
|
-
__________________________________________
|
39
38
|
~ > ruby samples/a.rb
|
40
|
-
__________________________________________
|
41
|
-
42
|
42
39
|
|
40
|
+
42
|
43
41
|
|
44
42
|
|
45
|
-
|
46
|
-
~ > cat samples/b.rb
|
47
|
-
__________________________________________
|
48
|
-
require 'prototype'
|
49
|
-
|
50
|
-
DB = Prototype.new{
|
51
|
-
host 'localhost'
|
52
|
-
port 4242
|
53
|
-
|
54
|
-
def connect() p [host, port] end
|
55
|
-
}
|
43
|
+
<========< samples/b.rb >========>
|
56
44
|
|
57
|
-
|
58
|
-
p DB.host
|
59
|
-
p DB.port
|
60
|
-
DB.connect
|
45
|
+
~ > cat samples/b.rb
|
61
46
|
|
47
|
+
require 'prototype'
|
48
|
+
|
49
|
+
DB = Prototype.new{
|
50
|
+
host 'localhost'
|
51
|
+
port 4242
|
52
|
+
|
53
|
+
conn_string [host, port].join(':')
|
54
|
+
|
55
|
+
def connect() p [host, port] end
|
56
|
+
}
|
57
|
+
|
58
|
+
p DB
|
59
|
+
p DB.host
|
60
|
+
p DB.port
|
61
|
+
p DB.conn_string
|
62
|
+
|
63
|
+
DB.connect
|
62
64
|
|
63
|
-
__________________________________________
|
64
65
|
~ > ruby samples/b.rb
|
65
|
-
__________________________________________
|
66
|
-
"localhost"
|
67
|
-
4242
|
68
|
-
["localhost", 4242]
|
69
|
-
|
70
66
|
|
67
|
+
#<#<Class:0xb7595348>:0xb7595438 @conn_string="localhost:4242", @port=4242, @host="localhost">
|
68
|
+
"localhost"
|
69
|
+
4242
|
70
|
+
"localhost:4242"
|
71
|
+
["localhost", 4242]
|
72
|
+
|
73
|
+
|
74
|
+
<========< samples/c.rb >========>
|
75
|
+
|
76
|
+
~ > cat samples/c.rb
|
77
|
+
|
78
|
+
require 'prototype'
|
79
|
+
|
80
|
+
a = Prototype.new{
|
81
|
+
def method() 42 end
|
82
|
+
}
|
83
|
+
|
84
|
+
b = a.clone
|
85
|
+
|
86
|
+
p a.method
|
87
|
+
p b.method
|
88
|
+
|
89
|
+
a.extend{
|
90
|
+
def method2() '42' end
|
91
|
+
}
|
92
|
+
|
93
|
+
p a.method2
|
94
|
+
p b.method2
|
95
|
+
|
96
|
+
b.extend{
|
97
|
+
def method3() 42.0 end
|
98
|
+
}
|
99
|
+
|
100
|
+
p b.method3
|
101
|
+
p a.method3 # throws error!
|
102
|
+
|
103
|
+
|
104
|
+
~ > ruby samples/c.rb
|
105
|
+
|
106
|
+
42
|
107
|
+
42
|
108
|
+
"42"
|
109
|
+
"42"
|
110
|
+
42.0
|
111
|
+
samples/c.rb:24: undefined method `method3' for #<#<Class:0xb7595860>:0xb75953c4> (NoMethodError)
|
112
|
+
|
113
|
+
|
114
|
+
<========< samples/d.rb >========>
|
115
|
+
|
116
|
+
~ > cat samples/d.rb
|
117
|
+
|
118
|
+
require 'prototype'
|
119
|
+
|
120
|
+
proto = prototype{ attributes 'a' => 1, 'b' => 2, 'c' => 3 }
|
121
|
+
proto = prototype{ a 1; b 2; c 3 }
|
122
|
+
|
123
|
+
%w( a b c ).each{|attr| p proto.send(attr)}
|
124
|
+
|
125
|
+
clone = proto.clone
|
126
|
+
proto.c = 42
|
127
|
+
|
128
|
+
%w( a b c ).each{|attr| p proto.send(attr)}
|
129
|
+
%w( a b c ).each{|attr| p clone.send(attr)}
|
130
|
+
|
131
|
+
~ > ruby samples/d.rb
|
132
|
+
|
133
|
+
1
|
134
|
+
2
|
135
|
+
3
|
136
|
+
1
|
137
|
+
2
|
138
|
+
42
|
139
|
+
1
|
140
|
+
2
|
141
|
+
3
|
142
|
+
|
143
|
+
|
144
|
+
<========< samples/e.rb >========>
|
71
145
|
|
72
|
-
__________________________________________
|
73
146
|
~ > cat samples/e.rb
|
74
|
-
__________________________________________
|
75
|
-
require 'prototype'
|
76
|
-
|
77
|
-
proto = prototype{
|
78
|
-
@a = 40
|
79
|
-
@b = 2
|
80
|
-
}
|
81
147
|
|
82
|
-
|
148
|
+
require 'prototype'
|
149
|
+
|
150
|
+
proto = prototype{
|
151
|
+
@a = 40
|
152
|
+
@b = 2
|
153
|
+
}
|
154
|
+
|
155
|
+
p(proto.a + proto.b)
|
83
156
|
|
157
|
+
~ > ruby samples/e.rb
|
84
158
|
|
85
|
-
|
86
|
-
42
|
159
|
+
42
|
87
160
|
|
88
161
|
|
162
|
+
<========< samples/f.rb >========>
|
89
163
|
|
90
|
-
__________________________________________
|
91
164
|
~ > cat samples/f.rb
|
92
|
-
__________________________________________
|
93
|
-
require 'prototype'
|
94
|
-
|
95
|
-
a = prototype{ attributes 'a' => 4, 'b' => 10, 'c' => 2 }
|
96
|
-
|
97
|
-
b = prototype{ a 4; b 10; c 2 }
|
98
|
-
|
99
|
-
c = prototype{ @a, @b, @c = 4, 10, 2 }
|
100
165
|
|
101
|
-
|
166
|
+
require 'prototype'
|
167
|
+
|
168
|
+
a = prototype{ attributes 'a' => 4, 'b' => 10, 'c' => 2}
|
169
|
+
|
170
|
+
b = prototype{ a 4; b 10; c 2 }
|
171
|
+
|
172
|
+
c = prototype{ @a = 4; @b = 10; @c = 2 }
|
173
|
+
|
174
|
+
[a, b, c].each{|obj| p(obj.a * obj.b + obj.c) }
|
102
175
|
|
176
|
+
~ > ruby samples/f.rb
|
103
177
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
42
|
178
|
+
42
|
179
|
+
42
|
180
|
+
42
|
108
181
|
|
109
182
|
|
183
|
+
<========< samples/g.rb >========>
|
110
184
|
|
111
|
-
__________________________________________
|
112
185
|
~ > cat samples/g.rb
|
113
|
-
__________________________________________
|
114
|
-
require 'prototype'
|
115
186
|
|
116
|
-
|
187
|
+
|
188
|
+
require 'prototype'
|
189
|
+
|
190
|
+
a = prototype
|
191
|
+
|
192
|
+
b = prototype(a){ @a, @b, @c = 4, 10, 2 }
|
193
|
+
|
194
|
+
a.extend{ def answer() a * b + c end }
|
195
|
+
|
196
|
+
p b.answer
|
197
|
+
|
117
198
|
|
118
|
-
|
199
|
+
~ > ruby samples/g.rb
|
119
200
|
|
120
|
-
|
201
|
+
42
|
121
202
|
|
122
|
-
p b.answer
|
123
203
|
|
204
|
+
<========< samples/h.rb >========>
|
124
205
|
|
125
|
-
~ >
|
126
|
-
42
|
206
|
+
~ > cat samples/h.rb
|
127
207
|
|
128
|
-
|
208
|
+
require 'prototype'
|
209
|
+
|
210
|
+
proto = prototype{
|
211
|
+
a 1
|
212
|
+
b 1
|
213
|
+
c 40
|
214
|
+
|
215
|
+
sum { a + b + c }
|
216
|
+
}
|
217
|
+
|
218
|
+
p proto.sum
|
129
219
|
|
130
|
-
|
220
|
+
~ > ruby samples/h.rb
|
131
221
|
|
132
|
-
|
222
|
+
42
|
133
223
|
|
134
|
-
lib/*rb
|
135
|
-
samples/*rb
|
data/README.tmpl
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
NAME
|
2
|
+
|
3
|
+
prototype.rb
|
4
|
+
|
5
|
+
URIS
|
6
|
+
|
7
|
+
http://codeforpeople.com/lib/ruby/
|
8
|
+
http://rubyforge.org/projects/codeforpeople/
|
9
|
+
|
10
|
+
SYNOPSIS
|
11
|
+
|
12
|
+
prototype.rb facilitates a prototype based coding style
|
13
|
+
|
14
|
+
http://en.wikipedia.org/wiki/Prototype-based_programming
|
15
|
+
|
16
|
+
for ruby
|
17
|
+
|
18
|
+
WHY
|
19
|
+
|
20
|
+
prototype based programming can look very nice ;-)
|
21
|
+
|
22
|
+
SAMPLES
|
23
|
+
|
24
|
+
@samples
|
data/gemspec.rb
CHANGED
@@ -16,6 +16,7 @@ Gem::Specification::new do |spec|
|
|
16
16
|
|
17
17
|
spec.has_rdoc = File::exist? "doc"
|
18
18
|
spec.test_suite_file = "test/#{ lib }.rb" if File::directory? "test"
|
19
|
+
spec.add_dependency 'attributes', '~> 3.0'
|
19
20
|
|
20
21
|
spec.author = "Ara T. Howard"
|
21
22
|
spec.email = "ara.t.howard@noaa.gov"
|
data/gen_readme.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
$VERBOSE=nil
|
4
|
+
|
5
|
+
def indent s, n = 2
|
6
|
+
ws = ' ' * n
|
7
|
+
s.gsub %r/^/, ws
|
8
|
+
end
|
9
|
+
|
10
|
+
template = IO::read 'README.tmpl'
|
11
|
+
|
12
|
+
samples = ''
|
13
|
+
prompt = '~ > '
|
14
|
+
|
15
|
+
Dir['sample*/*'].sort.each do |sample|
|
16
|
+
samples << "\n" << " <========< #{ sample } >========>" << "\n\n"
|
17
|
+
|
18
|
+
cmd = "cat #{ sample }"
|
19
|
+
samples << indent(prompt + cmd, 2) << "\n\n"
|
20
|
+
samples << indent(`#{ cmd }`, 4) << "\n"
|
21
|
+
|
22
|
+
cmd = "ruby #{ sample }"
|
23
|
+
samples << indent(prompt + cmd, 2) << "\n\n"
|
24
|
+
|
25
|
+
cmd = "ruby -Ilib #{ sample }"
|
26
|
+
samples << indent(`#{ cmd } 2>&1`, 4) << "\n"
|
27
|
+
end
|
28
|
+
|
29
|
+
#samples.gsub! %r/^/, ' '
|
30
|
+
|
31
|
+
readme = template.gsub %r/^\s*@samples\s*$/, samples
|
32
|
+
print readme
|
@@ -0,0 +1,177 @@
|
|
1
|
+
|
2
|
+
begin
|
3
|
+
require 'rubygems'
|
4
|
+
rescue LoadError
|
5
|
+
nil
|
6
|
+
end
|
7
|
+
|
8
|
+
begin
|
9
|
+
require 'attributes'
|
10
|
+
rescue LoadError
|
11
|
+
warn <<-msg
|
12
|
+
attributes.rb not found!
|
13
|
+
|
14
|
+
download from
|
15
|
+
- http://rubyforge.org/projects/codeforpeople/
|
16
|
+
|
17
|
+
or
|
18
|
+
|
19
|
+
- http://codeforpeople.com/lib/ruby/
|
20
|
+
msg
|
21
|
+
raise
|
22
|
+
end
|
23
|
+
|
24
|
+
#
|
25
|
+
# http://en.wikipedia.org/wiki/Prototype-based_programming
|
26
|
+
#
|
27
|
+
|
28
|
+
class Prototype
|
29
|
+
VERSION = '0.2.0'
|
30
|
+
|
31
|
+
module Prototypical
|
32
|
+
module ClassMethods
|
33
|
+
def __prototype_table__ # uses closure/init to avoid instance-var
|
34
|
+
__prototype_singleton_class__{
|
35
|
+
table = {}
|
36
|
+
define_method('__prototype_table__'){ table }
|
37
|
+
}
|
38
|
+
__prototype_table__
|
39
|
+
end
|
40
|
+
|
41
|
+
def __prototype_eval__ &b
|
42
|
+
tid = Thread.current.object_id.abs
|
43
|
+
src, dst = "method_missing", "__method_missing_#{ tid }__"
|
44
|
+
aliased = false
|
45
|
+
|
46
|
+
__prototype_singleton_class__{
|
47
|
+
unless respond_to? dst
|
48
|
+
alias_method dst, src
|
49
|
+
aliased = true
|
50
|
+
end
|
51
|
+
|
52
|
+
def method_missing m, *a, &b
|
53
|
+
__prototype_barewords_can_set_and_get_ivars_and_define_methods__ m, *a, &b
|
54
|
+
end
|
55
|
+
|
56
|
+
def __prototype_barewords_can_set_and_get_ivars_and_define_methods__ m, *a, &b
|
57
|
+
if b
|
58
|
+
define_method m, *a, &b
|
59
|
+
else
|
60
|
+
ivar = "@#{ m }"
|
61
|
+
if a.size == 0
|
62
|
+
defined?(ivar) ? instance_variable_get(ivar) : super
|
63
|
+
elsif a.size == 1
|
64
|
+
instance_variable_set ivar, a.shift
|
65
|
+
else
|
66
|
+
__method_missing__(m, *a, &b)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
}
|
71
|
+
|
72
|
+
module_eval &b
|
73
|
+
|
74
|
+
ensure
|
75
|
+
__prototype_singleton_class__{ alias_method src, dst } if aliased
|
76
|
+
end
|
77
|
+
|
78
|
+
def __prototype_singleton_class__ &b
|
79
|
+
sc =
|
80
|
+
class << self
|
81
|
+
self
|
82
|
+
end
|
83
|
+
sc.module_eval &b if b
|
84
|
+
sc
|
85
|
+
end
|
86
|
+
|
87
|
+
def __prototype_prototype__ &b
|
88
|
+
return unless b
|
89
|
+
|
90
|
+
__prototype_eval__ &b
|
91
|
+
|
92
|
+
table =
|
93
|
+
instance_variables.inject({}) do |t,ivar|
|
94
|
+
value =
|
95
|
+
instance_eval do
|
96
|
+
begin
|
97
|
+
instance_variable_get ivar
|
98
|
+
ensure
|
99
|
+
remove_instance_variable ivar
|
100
|
+
end
|
101
|
+
end
|
102
|
+
t.update ivar => value
|
103
|
+
end
|
104
|
+
|
105
|
+
__prototype_table__.update table
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
module InstanceMethods
|
110
|
+
def initialize *a, &b
|
111
|
+
__prototype_init__
|
112
|
+
super
|
113
|
+
end
|
114
|
+
|
115
|
+
def __prototype_init__
|
116
|
+
self.class.__prototype_table__.each do |ivar, value|
|
117
|
+
defined = instance_eval "defined? #{ ivar }"
|
118
|
+
unless defined
|
119
|
+
instance_variable_set ivar, value
|
120
|
+
end
|
121
|
+
|
122
|
+
a = ivar[%r/\w+/]
|
123
|
+
defined = respond_to? a
|
124
|
+
unless defined
|
125
|
+
self.class.module_eval{ attribute a => value }
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def extend *a, &b
|
131
|
+
unless a.empty?
|
132
|
+
super
|
133
|
+
else
|
134
|
+
self.class.__prototype_prototype__ &b
|
135
|
+
__prototype_init__
|
136
|
+
self
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def clone *a, &b
|
141
|
+
obj = prototype(self.class, *a, &b)
|
142
|
+
instance_variables.each do |ivar|
|
143
|
+
value = instance_variable_get ivar
|
144
|
+
obj.instance_variable_set ivar, value
|
145
|
+
end
|
146
|
+
obj
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def self.extend_object c
|
151
|
+
c.extend ClassMethods
|
152
|
+
c.module_eval{ include InstanceMethods }
|
153
|
+
super
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
class << self
|
158
|
+
def new parent = Object, *a, &b
|
159
|
+
parent = parent.class unless Class === parent
|
160
|
+
c = Class.new parent
|
161
|
+
c.extend Prototypical
|
162
|
+
c.__prototype_table__.update parent.__prototype_table__ if
|
163
|
+
parent.respond_to? '__prototype_table__'
|
164
|
+
c.__prototype_prototype__ &b
|
165
|
+
obj = c.new *a
|
166
|
+
obj
|
167
|
+
end
|
168
|
+
|
169
|
+
alias_method "exnihilo", "new"
|
170
|
+
alias_method "ex_nihilo", "new"
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
class Object
|
175
|
+
def Prototype(*a, &b) Prototype.new *a, &b end
|
176
|
+
def prototype(*a, &b) Prototype.new *a, &b end
|
177
|
+
end
|
data/lib/prototype.rb
CHANGED
@@ -1,155 +1,155 @@
|
|
1
1
|
|
2
|
+
begin
|
3
|
+
require 'rubygems'
|
4
|
+
rescue LoadError
|
5
|
+
nil
|
6
|
+
end
|
7
|
+
|
8
|
+
begin
|
9
|
+
require 'attributes'
|
10
|
+
rescue LoadError
|
11
|
+
warn <<-msg
|
12
|
+
attributes.rb not found!
|
13
|
+
|
14
|
+
download from
|
15
|
+
- http://rubyforge.org/projects/codeforpeople/
|
16
|
+
|
17
|
+
or
|
18
|
+
|
19
|
+
- http://codeforpeople.com/lib/ruby/
|
20
|
+
msg
|
21
|
+
raise
|
22
|
+
end
|
23
|
+
|
2
24
|
#
|
3
25
|
# http://en.wikipedia.org/wiki/Prototype-based_programming
|
4
26
|
#
|
5
27
|
|
6
28
|
class Prototype
|
7
|
-
VERSION = '0.
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
#
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
define_method(setter) do |value|
|
29
|
-
instance_variable_set ivar, value
|
29
|
+
VERSION = '0.2.0'
|
30
|
+
|
31
|
+
module Prototypical
|
32
|
+
module ClassMethods
|
33
|
+
def __prototype_table__ # uses closure/init to avoid instance-var
|
34
|
+
__prototype_singleton_class__{
|
35
|
+
table = {}
|
36
|
+
define_method('__prototype_table__'){ table }
|
37
|
+
}
|
38
|
+
__prototype_table__
|
39
|
+
end
|
40
|
+
|
41
|
+
def __prototype_eval__ &b
|
42
|
+
tid = Thread.current.object_id.abs
|
43
|
+
src, dst = "method_missing", "__method_missing_#{ tid }__"
|
44
|
+
aliased = false
|
45
|
+
|
46
|
+
__prototype_singleton_class__{
|
47
|
+
unless respond_to? dst
|
48
|
+
alias_method dst, src
|
49
|
+
aliased = true
|
30
50
|
end
|
31
51
|
|
32
|
-
|
33
|
-
|
34
|
-
|
52
|
+
def method_missing m, *a, &b
|
53
|
+
__prototype_barewords_can_set_and_get_ivars_and_define_methods__ m, *a, &b
|
54
|
+
end
|
55
|
+
|
56
|
+
def __prototype_barewords_can_set_and_get_ivars_and_define_methods__ m, *a, &b
|
57
|
+
if b
|
58
|
+
define_method m, *a, &b
|
35
59
|
else
|
36
|
-
|
37
|
-
|
38
|
-
|
60
|
+
ivar = "@#{ m }"
|
61
|
+
if a.size == 0
|
62
|
+
defined?(ivar) ? instance_variable_get(ivar) : super
|
63
|
+
elsif a.size == 1
|
64
|
+
instance_variable_set ivar, a.shift
|
65
|
+
else
|
66
|
+
__method_missing__(m, *a, &b)
|
39
67
|
end
|
40
|
-
instance_variable_get ivar
|
41
68
|
end
|
42
69
|
end
|
70
|
+
}
|
43
71
|
|
44
|
-
|
72
|
+
module_eval &b
|
45
73
|
|
46
|
-
|
47
|
-
|
48
|
-
end
|
49
|
-
else
|
50
|
-
@attributes ||= []
|
74
|
+
ensure
|
75
|
+
__prototype_singleton_class__{ alias_method src, dst } if aliased
|
51
76
|
end
|
52
|
-
end
|
53
77
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
def method_missing m, *a, &b
|
63
|
-
ivar = "@#{ m }"
|
64
|
-
if a.size == 0
|
65
|
-
if defined? ivar
|
66
|
-
instance_variable_get ivar
|
67
|
-
else
|
68
|
-
super
|
69
|
-
end
|
70
|
-
elsif a.size == 1
|
71
|
-
instance_variable_set ivar, a.shift
|
72
|
-
else
|
73
|
-
super
|
78
|
+
def __prototype_singleton_class__ &b
|
79
|
+
sc =
|
80
|
+
class << self
|
81
|
+
self
|
82
|
+
end
|
83
|
+
sc.module_eval &b if b
|
84
|
+
sc
|
74
85
|
end
|
75
|
-
end
|
76
|
-
end
|
77
86
|
|
78
|
-
|
79
|
-
|
80
|
-
__protoinit__
|
81
|
-
super
|
82
|
-
end
|
87
|
+
def __prototype_prototype__ &b
|
88
|
+
return unless b
|
83
89
|
|
84
|
-
|
85
|
-
self.class.__prototable__.each do |ivar, value|
|
86
|
-
defined = instance_eval "defined? #{ ivar }"
|
87
|
-
unless defined
|
88
|
-
instance_variable_set ivar, value
|
89
|
-
end
|
90
|
+
__prototype_eval__ &b
|
90
91
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
92
|
+
table =
|
93
|
+
instance_variables.inject({}) do |t,ivar|
|
94
|
+
value =
|
95
|
+
instance_eval do
|
96
|
+
begin
|
97
|
+
instance_variable_get ivar
|
98
|
+
ensure
|
99
|
+
remove_instance_variable ivar
|
100
|
+
end
|
101
|
+
end
|
102
|
+
t.update ivar => value
|
103
|
+
end
|
104
|
+
|
105
|
+
__prototype_table__.update table
|
97
106
|
end
|
98
107
|
end
|
99
108
|
|
100
|
-
|
101
|
-
|
109
|
+
module InstanceMethods
|
110
|
+
def initialize *a, &b
|
111
|
+
__prototype_init__
|
102
112
|
super
|
103
|
-
else
|
104
|
-
self.class.__prototype__ &b
|
105
|
-
__protoinit__
|
106
|
-
self
|
107
113
|
end
|
108
|
-
end
|
109
114
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
obj
|
117
|
-
end
|
118
|
-
end
|
115
|
+
def __prototype_init__
|
116
|
+
self.class.__prototype_table__.each do |ivar, value|
|
117
|
+
defined = instance_eval "defined? #{ ivar }"
|
118
|
+
unless defined
|
119
|
+
instance_variable_set ivar, value
|
120
|
+
end
|
119
121
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
122
|
+
a = ivar[%r/\w+/]
|
123
|
+
defined = respond_to? a
|
124
|
+
unless defined
|
125
|
+
self.class.module_eval{ attribute a => value }
|
126
|
+
end
|
127
|
+
end
|
126
128
|
end
|
127
|
-
end
|
128
|
-
|
129
|
-
def __prototype__ &b
|
130
|
-
return unless b
|
131
|
-
|
132
|
-
module_eval &b
|
133
129
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
remove_instance_variable ivar
|
142
|
-
end
|
143
|
-
end
|
144
|
-
t.update ivar => value
|
130
|
+
def extend *a, &b
|
131
|
+
unless a.empty?
|
132
|
+
super
|
133
|
+
else
|
134
|
+
self.class.__prototype_prototype__ &b
|
135
|
+
__prototype_init__
|
136
|
+
self
|
145
137
|
end
|
138
|
+
end
|
146
139
|
|
147
|
-
|
140
|
+
def clone *a, &b
|
141
|
+
obj = prototype(self.class, *a, &b)
|
142
|
+
instance_variables.each do |ivar|
|
143
|
+
value = instance_variable_get ivar
|
144
|
+
obj.instance_variable_set ivar, value
|
145
|
+
end
|
146
|
+
obj
|
147
|
+
end
|
148
148
|
end
|
149
149
|
|
150
|
-
def self.extend_object
|
151
|
-
|
152
|
-
|
150
|
+
def self.extend_object c
|
151
|
+
c.extend ClassMethods
|
152
|
+
c.module_eval{ include InstanceMethods }
|
153
153
|
super
|
154
154
|
end
|
155
155
|
end
|
@@ -158,10 +158,10 @@ class Prototype
|
|
158
158
|
def new parent = Object, *a, &b
|
159
159
|
parent = parent.class unless Class === parent
|
160
160
|
c = Class.new parent
|
161
|
-
c.extend
|
162
|
-
|
163
|
-
|
164
|
-
c.
|
161
|
+
c.extend Prototypical
|
162
|
+
c.__prototype_table__.update parent.__prototype_table__ if
|
163
|
+
parent.respond_to? '__prototype_table__'
|
164
|
+
c.__prototype_prototype__ &b
|
165
165
|
obj = c.new *a
|
166
166
|
obj
|
167
167
|
end
|
@@ -172,10 +172,6 @@ class Prototype
|
|
172
172
|
end
|
173
173
|
|
174
174
|
class Object
|
175
|
-
def Prototype *a, &b
|
176
|
-
|
177
|
-
end
|
178
|
-
def prototype *a, &b
|
179
|
-
Prototype.new *a, &b
|
180
|
-
end
|
175
|
+
def Prototype(*a, &b) Prototype.new *a, &b end
|
176
|
+
def prototype(*a, &b) Prototype.new *a, &b end
|
181
177
|
end
|
data/prototype-0.2.0.gem
ADDED
File without changes
|
data/samples/h.rb
ADDED
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
|
|
3
3
|
specification_version: 1
|
4
4
|
name: prototype
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2006-07-
|
6
|
+
version: 0.2.0
|
7
|
+
date: 2006-07-13 00:00:00.000000 -06:00
|
8
8
|
summary: prototype
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -34,8 +34,11 @@ files:
|
|
34
34
|
- gemspec.rb
|
35
35
|
- samples
|
36
36
|
- README
|
37
|
-
-
|
37
|
+
- README.tmpl
|
38
|
+
- gen_readme.rb
|
39
|
+
- prototype-0.2.0.gem
|
38
40
|
- lib/prototype.rb
|
41
|
+
- lib/prototype-0.2.0.rb
|
39
42
|
- samples/c.rb
|
40
43
|
- samples/a.rb
|
41
44
|
- samples/b.rb
|
@@ -43,10 +46,21 @@ files:
|
|
43
46
|
- samples/e.rb
|
44
47
|
- samples/f.rb
|
45
48
|
- samples/g.rb
|
49
|
+
- samples/h.rb
|
46
50
|
test_files: []
|
47
51
|
rdoc_options: []
|
48
52
|
extra_rdoc_files: []
|
49
53
|
executables: []
|
50
54
|
extensions: []
|
51
55
|
requirements: []
|
52
|
-
dependencies:
|
56
|
+
dependencies:
|
57
|
+
- !ruby/object:Gem::Dependency
|
58
|
+
name: attributes
|
59
|
+
version_requirement:
|
60
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
61
|
+
requirements:
|
62
|
+
-
|
63
|
+
- "~>"
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: "3.0"
|
66
|
+
version:
|
data/lib/prototype-0.0.0.rb
DELETED
@@ -1,181 +0,0 @@
|
|
1
|
-
|
2
|
-
#
|
3
|
-
# http://en.wikipedia.org/wiki/Prototype-based_programming
|
4
|
-
#
|
5
|
-
|
6
|
-
class Prototype
|
7
|
-
VERSION = '0.1.0'
|
8
|
-
|
9
|
-
#
|
10
|
-
# inline my attribute.rb file here
|
11
|
-
#
|
12
|
-
module Attrbiutes
|
13
|
-
def attributes *a, &b
|
14
|
-
unless a.empty?
|
15
|
-
hashes, names = a.partition{|x| Hash === x}
|
16
|
-
|
17
|
-
names_and_defaults = {}
|
18
|
-
hashes.each{|h| names_and_defaults.update h}
|
19
|
-
names.each{|name| names_and_defaults.update name => nil}
|
20
|
-
|
21
|
-
names_and_defaults.each do |name, default|
|
22
|
-
init = b || lambda { default }
|
23
|
-
ivar = "@#{ name }"
|
24
|
-
getter = "#{ name }"
|
25
|
-
setter = "#{ name }="
|
26
|
-
query = "#{ name }?"
|
27
|
-
|
28
|
-
define_method(setter) do |value|
|
29
|
-
instance_variable_set ivar, value
|
30
|
-
end
|
31
|
-
|
32
|
-
define_method(getter) do |*value|
|
33
|
-
unless value.empty?
|
34
|
-
send setter, value.shift
|
35
|
-
else
|
36
|
-
defined = instance_eval "defined? #{ ivar }"
|
37
|
-
unless defined
|
38
|
-
send setter, instance_eval(&init)
|
39
|
-
end
|
40
|
-
instance_variable_get ivar
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
alias_method query, getter
|
45
|
-
|
46
|
-
(attributes << name).uniq!
|
47
|
-
attributes
|
48
|
-
end
|
49
|
-
else
|
50
|
-
@attributes ||= []
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def attribute *a, &b
|
55
|
-
attributes *a, &b
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
module ClassMethods
|
60
|
-
include Attrbiutes
|
61
|
-
|
62
|
-
def method_missing m, *a, &b
|
63
|
-
ivar = "@#{ m }"
|
64
|
-
if a.size == 0
|
65
|
-
if defined? ivar
|
66
|
-
instance_variable_get ivar
|
67
|
-
else
|
68
|
-
super
|
69
|
-
end
|
70
|
-
elsif a.size == 1
|
71
|
-
instance_variable_set ivar, a.shift
|
72
|
-
else
|
73
|
-
super
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
module InstanceMethods
|
79
|
-
def initialize(*a, &b)
|
80
|
-
__protoinit__
|
81
|
-
super
|
82
|
-
end
|
83
|
-
|
84
|
-
def __protoinit__
|
85
|
-
self.class.__prototable__.each do |ivar, value|
|
86
|
-
defined = instance_eval "defined? #{ ivar }"
|
87
|
-
unless defined
|
88
|
-
instance_variable_set ivar, value
|
89
|
-
end
|
90
|
-
|
91
|
-
a = ivar[%r/\w+/]
|
92
|
-
#defined = respond_to? a
|
93
|
-
defined = self.class.module_eval{ attributes }.include? a
|
94
|
-
unless defined
|
95
|
-
self.class.module_eval{ attribute a }
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
def extend *a, &b
|
101
|
-
unless a.empty?
|
102
|
-
super
|
103
|
-
else
|
104
|
-
self.class.__prototype__ &b
|
105
|
-
__protoinit__
|
106
|
-
self
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
def clone *a, &b
|
111
|
-
obj = prototype(self.class, *a, &b)
|
112
|
-
instance_variables.each do |ivar|
|
113
|
-
value = instance_variable_get ivar
|
114
|
-
obj.instance_variable_set ivar, value
|
115
|
-
end
|
116
|
-
obj
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
module Prototype
|
121
|
-
def __prototable__ # uses const to avoid copying instance var
|
122
|
-
if const_defined? 'PROTOTABLE'
|
123
|
-
const_get 'PROTOTABLE'
|
124
|
-
else
|
125
|
-
const_set 'PROTOTABLE', {}
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
def __prototype__ &b
|
130
|
-
return unless b
|
131
|
-
|
132
|
-
module_eval &b
|
133
|
-
|
134
|
-
table =
|
135
|
-
instance_variables.inject({}) do |t,ivar|
|
136
|
-
value =
|
137
|
-
instance_eval do
|
138
|
-
begin
|
139
|
-
instance_variable_get ivar
|
140
|
-
ensure
|
141
|
-
remove_instance_variable ivar
|
142
|
-
end
|
143
|
-
end
|
144
|
-
t.update ivar => value
|
145
|
-
end
|
146
|
-
|
147
|
-
__prototable__.update table
|
148
|
-
end
|
149
|
-
|
150
|
-
def self.extend_object other
|
151
|
-
other.extend ClassMethods
|
152
|
-
other.module_eval{ include InstanceMethods }
|
153
|
-
super
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
class << self
|
158
|
-
def new parent = Object, *a, &b
|
159
|
-
parent = parent.class unless Class === parent
|
160
|
-
c = Class.new parent
|
161
|
-
c.extend Prototype
|
162
|
-
prototable = parent.const_get 'PROTOTABLE' rescue nil
|
163
|
-
c.__prototable__.update prototable if prototable
|
164
|
-
c.__prototype__ &b
|
165
|
-
obj = c.new *a
|
166
|
-
obj
|
167
|
-
end
|
168
|
-
|
169
|
-
alias_method "exnihilo", "new"
|
170
|
-
alias_method "ex_nihilo", "new"
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
|
-
class Object
|
175
|
-
def Prototype *a, &b
|
176
|
-
Prototype.new *a, &b
|
177
|
-
end
|
178
|
-
def prototype *a, &b
|
179
|
-
Prototype.new *a, &b
|
180
|
-
end
|
181
|
-
end
|