prototype 1.0.0 → 2.0.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 +39 -35
- data/README.tmpl +14 -6
- data/gemspec.rb +2 -2
- data/lib/prototype-2.0.0.rb +213 -0
- data/lib/prototype.rb +153 -144
- data/{prototype-1.0.0.gem → prototype-2.0.0.gem} +0 -0
- data/samples/a.rb +1 -1
- data/samples/b.rb +4 -5
- data/samples/c.rb +6 -7
- data/samples/d.rb +3 -3
- data/samples/e.rb +1 -1
- data/samples/f.rb +1 -1
- data/samples/g.rb +4 -6
- data/samples/h.rb +1 -1
- metadata +7 -8
- data/a.rb +0 -7
- data/lib/prototype-1.0.0.rb +0 -204
data/README
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
NAME
|
2
|
-
|
3
2
|
prototype.rb
|
4
3
|
|
5
|
-
|
4
|
+
INSTALL
|
5
|
+
gem install prototype
|
6
6
|
|
7
|
-
|
7
|
+
URIS
|
8
8
|
http://rubyforge.org/projects/codeforpeople/
|
9
|
+
http://codeforpeople.com/lib/ruby/
|
9
10
|
|
10
11
|
SYNOPSIS
|
11
|
-
|
12
12
|
prototype.rb facilitates a prototype based coding style
|
13
13
|
|
14
14
|
http://en.wikipedia.org/wiki/Prototype-based_programming
|
@@ -16,13 +16,22 @@ SYNOPSIS
|
|
16
16
|
for ruby
|
17
17
|
|
18
18
|
WHY
|
19
|
-
|
20
19
|
prototype based programming looks very nice ;-)
|
21
20
|
|
22
21
|
also, there are many problems that a genuine singleton object with cloning
|
23
22
|
abilities can illuminate clearly
|
24
23
|
|
24
|
+
it's the basis of a new rendering model for rails
|
25
|
+
|
25
26
|
HISTORY
|
27
|
+
2.0.0
|
28
|
+
completely gutted the prototype library and re-implemented with a
|
29
|
+
module/singleton_class/include approach.
|
30
|
+
|
31
|
+
note that this version increases a major number because it is NOT
|
32
|
+
compatible with past releases. the incompatible change is that 'clone'
|
33
|
+
now returns an object that does not reflect changes made to the parent: it
|
34
|
+
is completely independant.
|
26
35
|
|
27
36
|
1.0.0
|
28
37
|
|
@@ -43,7 +52,7 @@ SAMPLES
|
|
43
52
|
def answer() @a + @b end
|
44
53
|
}
|
45
54
|
|
46
|
-
p singleton.answer
|
55
|
+
p singleton.answer #=> 42
|
47
56
|
|
48
57
|
~ > ruby samples/a.rb
|
49
58
|
|
@@ -65,16 +74,14 @@ SAMPLES
|
|
65
74
|
def connect() p [host, port] end
|
66
75
|
}
|
67
76
|
|
68
|
-
p DB
|
69
|
-
p DB.
|
70
|
-
p DB.
|
71
|
-
p DB.conn_string
|
77
|
+
p DB.host #=> "localhost"
|
78
|
+
p DB.port #=> 4242
|
79
|
+
p DB.conn_string #=> "localhost:4242"
|
72
80
|
|
73
|
-
DB.connect
|
81
|
+
DB.connect #=> ["locahost", 4242]
|
74
82
|
|
75
83
|
~ > ruby samples/b.rb
|
76
84
|
|
77
|
-
#<#<Class:0x10f8948>:0x10f7fac @port=4242, @host="localhost", @conn_string="localhost:4242">
|
78
85
|
"localhost"
|
79
86
|
4242
|
80
87
|
"localhost:4242"
|
@@ -93,32 +100,31 @@ SAMPLES
|
|
93
100
|
|
94
101
|
b = a.clone
|
95
102
|
|
96
|
-
p a.method
|
97
|
-
p b.method
|
103
|
+
p a.method #=> 42
|
104
|
+
p b.method #=> 42
|
98
105
|
|
99
106
|
a.extend{
|
100
107
|
def method2() '42' end
|
101
108
|
}
|
102
109
|
|
103
|
-
p a.method2
|
104
|
-
p b.method2
|
110
|
+
p a.respond_to?(:method2) #=> true
|
111
|
+
p b.respond_to?(:method2) #=> false
|
105
112
|
|
106
113
|
b.extend{
|
107
114
|
def method3() 42.0 end
|
108
115
|
}
|
109
116
|
|
110
|
-
p
|
111
|
-
p
|
112
|
-
|
117
|
+
p a.respond_to?(:method3) #=> false
|
118
|
+
p b.respond_to?(:method3) #=> true
|
113
119
|
|
114
120
|
~ > ruby samples/c.rb
|
115
121
|
|
116
122
|
42
|
117
123
|
42
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
124
|
+
true
|
125
|
+
false
|
126
|
+
false
|
127
|
+
true
|
122
128
|
|
123
129
|
|
124
130
|
<========< samples/d.rb >========>
|
@@ -130,13 +136,13 @@ SAMPLES
|
|
130
136
|
proto = prototype{ attributes 'a' => 1, 'b' => 2, 'c' => 3 }
|
131
137
|
proto = prototype{ a 1; b 2; c 3 }
|
132
138
|
|
133
|
-
%w( a b c ).each{|attr| p proto.send(attr)}
|
139
|
+
%w( a b c ).each{|attr| p proto.send(attr)} #=> 1, 2, 3
|
134
140
|
|
135
141
|
clone = proto.clone
|
136
142
|
proto.c = 42
|
137
143
|
|
138
|
-
%w( a b c ).each{|attr| p proto.send(attr)}
|
139
|
-
%w( a b c ).each{|attr| p clone.send(attr)}
|
144
|
+
%w( a b c ).each{|attr| p proto.send(attr)} #=> 1, 2, 42
|
145
|
+
%w( a b c ).each{|attr| p clone.send(attr)} #=> 1, 2, 3
|
140
146
|
|
141
147
|
~ > ruby samples/d.rb
|
142
148
|
|
@@ -162,7 +168,7 @@ SAMPLES
|
|
162
168
|
@b = 2
|
163
169
|
}
|
164
170
|
|
165
|
-
p(proto.a + proto.b)
|
171
|
+
p(proto.a + proto.b) #=> 42
|
166
172
|
|
167
173
|
~ > ruby samples/e.rb
|
168
174
|
|
@@ -181,7 +187,7 @@ SAMPLES
|
|
181
187
|
|
182
188
|
c = Object.prototype{ @a = 4; @b = 10; @c = 2 }
|
183
189
|
|
184
|
-
[a, b, c].each{|obj| p(obj.a * obj.b + obj.c) }
|
190
|
+
[a, b, c].each{|obj| p(obj.a * obj.b + obj.c) } #=> 42, 42, 42
|
185
191
|
|
186
192
|
~ > ruby samples/f.rb
|
187
193
|
|
@@ -194,17 +200,15 @@ SAMPLES
|
|
194
200
|
|
195
201
|
~ > cat samples/g.rb
|
196
202
|
|
197
|
-
|
198
203
|
require 'prototype'
|
199
204
|
|
200
|
-
a = prototype
|
201
|
-
|
202
|
-
b = prototype(a){ @a, @b, @c = 4, 10, 2 }
|
205
|
+
a = prototype{ @a, @b, @c = 4, 10, 2 }
|
203
206
|
|
204
|
-
|
207
|
+
b = a.clone
|
205
208
|
|
206
|
-
|
209
|
+
b.extend{ def answer() a * b + c end }
|
207
210
|
|
211
|
+
p b.answer #=> 42
|
208
212
|
|
209
213
|
~ > ruby samples/g.rb
|
210
214
|
|
@@ -225,7 +229,7 @@ SAMPLES
|
|
225
229
|
sum { a + b + c }
|
226
230
|
}
|
227
231
|
|
228
|
-
p proto.sum
|
232
|
+
p proto.sum #=> 42
|
229
233
|
|
230
234
|
~ > ruby samples/h.rb
|
231
235
|
|
data/README.tmpl
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
NAME
|
2
|
-
|
3
2
|
prototype.rb
|
4
3
|
|
5
|
-
|
4
|
+
INSTALL
|
5
|
+
gem install prototype
|
6
6
|
|
7
|
-
|
7
|
+
URIS
|
8
8
|
http://rubyforge.org/projects/codeforpeople/
|
9
|
+
http://codeforpeople.com/lib/ruby/
|
9
10
|
|
10
11
|
SYNOPSIS
|
11
|
-
|
12
12
|
prototype.rb facilitates a prototype based coding style
|
13
13
|
|
14
14
|
http://en.wikipedia.org/wiki/Prototype-based_programming
|
@@ -16,13 +16,22 @@ SYNOPSIS
|
|
16
16
|
for ruby
|
17
17
|
|
18
18
|
WHY
|
19
|
-
|
20
19
|
prototype based programming looks very nice ;-)
|
21
20
|
|
22
21
|
also, there are many problems that a genuine singleton object with cloning
|
23
22
|
abilities can illuminate clearly
|
24
23
|
|
24
|
+
it's the basis of a new rendering model for rails
|
25
|
+
|
25
26
|
HISTORY
|
27
|
+
2.0.0
|
28
|
+
completely gutted the prototype library and re-implemented with a
|
29
|
+
module/singleton_class/include approach.
|
30
|
+
|
31
|
+
note that this version increases a major number because it is NOT
|
32
|
+
compatible with past releases. the incompatible change is that 'clone'
|
33
|
+
now returns an object that does not reflect changes made to the parent: it
|
34
|
+
is completely independant.
|
26
35
|
|
27
36
|
1.0.0
|
28
37
|
|
@@ -30,5 +39,4 @@ HISTORY
|
|
30
39
|
were silently ignored
|
31
40
|
|
32
41
|
SAMPLES
|
33
|
-
|
34
42
|
@samples
|
data/gemspec.rb
CHANGED
@@ -16,9 +16,9 @@ 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', '
|
19
|
+
spec.add_dependency 'attributes', '>= 3.3'
|
20
20
|
|
21
21
|
spec.author = "Ara T. Howard"
|
22
|
-
spec.email = "ara.t.howard@
|
22
|
+
spec.email = "ara.t.howard@gmail.com"
|
23
23
|
spec.homepage = "http://codeforpeople.com/lib/ruby/#{ lib }/"
|
24
24
|
end
|
@@ -0,0 +1,213 @@
|
|
1
|
+
begin
|
2
|
+
require 'rubygems'
|
3
|
+
rescue LoadError
|
4
|
+
nil
|
5
|
+
end
|
6
|
+
|
7
|
+
begin
|
8
|
+
require 'attributes'
|
9
|
+
rescue LoadError
|
10
|
+
warn <<-msg
|
11
|
+
attributes.rb not found!
|
12
|
+
|
13
|
+
download from:
|
14
|
+
- http://rubyforge.org/projects/codeforpeople/
|
15
|
+
- http://codeforpeople.com/lib/ruby/
|
16
|
+
msg
|
17
|
+
raise
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
# http://en.wikipedia.org/wiki/Prototype-based_programming
|
22
|
+
#
|
23
|
+
|
24
|
+
class Prototype
|
25
|
+
VERSION = '2.0.0'
|
26
|
+
|
27
|
+
module ClassMethods
|
28
|
+
def version() VERSION end
|
29
|
+
|
30
|
+
def inherit c = Object, *a, &b
|
31
|
+
c = c.class unless Class === c
|
32
|
+
c = Class.new c
|
33
|
+
new c, *a, &b
|
34
|
+
end
|
35
|
+
alias_method "exnihilo", "inherit"
|
36
|
+
alias_method "ex_nihilo", "inherit"
|
37
|
+
|
38
|
+
def new c = Object, *a, &b
|
39
|
+
c = c.class unless Class === c
|
40
|
+
obj = c.new *a
|
41
|
+
prototyping obj, &b
|
42
|
+
obj
|
43
|
+
end
|
44
|
+
|
45
|
+
def clone src, *a, &b
|
46
|
+
c = src.class
|
47
|
+
c = Class.new c
|
48
|
+
dst = c.new *a
|
49
|
+
|
50
|
+
sc =
|
51
|
+
class << src
|
52
|
+
self
|
53
|
+
end
|
54
|
+
|
55
|
+
modules = sc.instance_variable_get('@modules') || []
|
56
|
+
modules.each{|mod| extend dst, mod}
|
57
|
+
|
58
|
+
src.instance_variables.each do |ivar|
|
59
|
+
value = src.instance_variable_get ivar
|
60
|
+
dst.instance_variable_set ivar, value
|
61
|
+
end
|
62
|
+
prototyping dst, &b
|
63
|
+
dst
|
64
|
+
end
|
65
|
+
|
66
|
+
def prototyping obj, &b
|
67
|
+
obj.extend InstanceMethods
|
68
|
+
mod = Prototype.context &b
|
69
|
+
ivars = mod.__method__["instance_variables"].call()
|
70
|
+
ivars.each do |ivar|
|
71
|
+
value = mod.__method__["instance_variable_get"].call(ivar)
|
72
|
+
obj.instance_eval{ instance_variable_set ivar, value }
|
73
|
+
end
|
74
|
+
extend obj, mod
|
75
|
+
obj
|
76
|
+
end
|
77
|
+
|
78
|
+
def extend obj, mod
|
79
|
+
sc =
|
80
|
+
class << obj
|
81
|
+
self
|
82
|
+
end
|
83
|
+
sc.module_eval do
|
84
|
+
(@modules ||= []) << mod
|
85
|
+
include mod
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def prototyped? obj
|
90
|
+
sc =
|
91
|
+
class << obj
|
92
|
+
self
|
93
|
+
end
|
94
|
+
sc.module_eval do
|
95
|
+
defined?(@prototyped) and @prototyped
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def prototyped! obj
|
100
|
+
sc =
|
101
|
+
class << obj
|
102
|
+
self
|
103
|
+
end
|
104
|
+
sc.module_eval do
|
105
|
+
@prototyped = true
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def context &b
|
110
|
+
mod = Module.new
|
111
|
+
sc =
|
112
|
+
class << mod
|
113
|
+
self
|
114
|
+
end
|
115
|
+
|
116
|
+
sc.module_eval do
|
117
|
+
__method__ = {} and define_method(:__method__){ __method__ }
|
118
|
+
|
119
|
+
def __call__(m, *a, &b)
|
120
|
+
meth = __method__[m.to_s]
|
121
|
+
raise NoMethodError, m.to_s unless meth
|
122
|
+
meth.call *a, &b
|
123
|
+
end
|
124
|
+
|
125
|
+
alias_method '__define_method__', 'define_method'
|
126
|
+
end
|
127
|
+
|
128
|
+
mod.methods.each{|m| mod.__method__[m] = mod.method(m) unless %w( __call__ __method__ ).include?(m)}
|
129
|
+
|
130
|
+
mod.methods.each do |m|
|
131
|
+
unless m =~ /^__|attribute/
|
132
|
+
sc.module_eval{ undef_method m }
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
sc.module_eval do
|
137
|
+
def method_missing m, *a, &b
|
138
|
+
if b
|
139
|
+
__define_method__ m, *a, &b
|
140
|
+
else
|
141
|
+
ivar = "@#{ m }"
|
142
|
+
case a.size
|
143
|
+
when 0
|
144
|
+
if eval("defined? #{ ivar }")
|
145
|
+
__call__ 'instance_variable_get', ivar
|
146
|
+
else
|
147
|
+
super
|
148
|
+
end
|
149
|
+
when 1
|
150
|
+
value = a.shift
|
151
|
+
__call__ 'instance_variable_set', ivar, value
|
152
|
+
else
|
153
|
+
super
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
mod.__call__ 'module_eval', &b if b
|
160
|
+
|
161
|
+
mod.__call__ 'module_eval' do
|
162
|
+
defined = __call('instance_methods').inject({}){|h,m| h.update m => true}
|
163
|
+
|
164
|
+
__call__('instance_variables').each do |ivar|
|
165
|
+
m = ivar[1..-1]
|
166
|
+
getter, setter, query = defined["#{ m }"], defined["#{ m }="], defined["#{ m }?"]
|
167
|
+
|
168
|
+
if getter.nil? and setter.nil? and query.nil?
|
169
|
+
__call__ 'attribute', m
|
170
|
+
next
|
171
|
+
end
|
172
|
+
if getter.nil?
|
173
|
+
__call__ 'module_eval', "def #{ m }() #{ ivar } end"
|
174
|
+
end
|
175
|
+
if setter.nil?
|
176
|
+
__call__ 'module_eval', "def #{ m }=(v) #{ ivar }=v end"
|
177
|
+
end
|
178
|
+
if query.nil?
|
179
|
+
__call__ 'module_eval', "def #{ m }?() defined?(#{ ivar }) and #{ ivar } end"
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
mod
|
185
|
+
end
|
186
|
+
end
|
187
|
+
extend ClassMethods
|
188
|
+
|
189
|
+
module InstanceMethods
|
190
|
+
def clone *a, &b
|
191
|
+
Prototype.clone self, *a, &b
|
192
|
+
end
|
193
|
+
def dup *a, &b
|
194
|
+
Prototype.clone self, *a, &b
|
195
|
+
end
|
196
|
+
def extend m=nil, &block
|
197
|
+
if block
|
198
|
+
prototyping(self, &block)
|
199
|
+
else
|
200
|
+
super(m)
|
201
|
+
end
|
202
|
+
self
|
203
|
+
end
|
204
|
+
end
|
205
|
+
include InstanceMethods
|
206
|
+
end
|
207
|
+
|
208
|
+
class Object
|
209
|
+
def Prototype(*a, &b) Prototype.inherit *a, &b end
|
210
|
+
def prototype(*a, &b) Prototype.inherit *a, &b end
|
211
|
+
def Prototyping(obj=nil, &b) Prototype.prototyping obj||self, &b end
|
212
|
+
def prototyping(obj=nil, &b) Prototype.prototyping obj||self, &b end
|
213
|
+
end
|
data/lib/prototype.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
begin
|
3
2
|
require 'rubygems'
|
4
3
|
rescue LoadError
|
@@ -11,11 +10,8 @@ rescue LoadError
|
|
11
10
|
warn <<-msg
|
12
11
|
attributes.rb not found!
|
13
12
|
|
14
|
-
download from
|
13
|
+
download from:
|
15
14
|
- http://rubyforge.org/projects/codeforpeople/
|
16
|
-
|
17
|
-
or
|
18
|
-
|
19
15
|
- http://codeforpeople.com/lib/ruby/
|
20
16
|
msg
|
21
17
|
raise
|
@@ -26,179 +22,192 @@ end
|
|
26
22
|
#
|
27
23
|
|
28
24
|
class Prototype
|
29
|
-
VERSION = '
|
30
|
-
def version() VERSION end
|
31
|
-
|
32
|
-
module Prototypical
|
33
|
-
module ClassMethods
|
34
|
-
def __prototype_table__ # uses closure/init to avoid instance-var
|
35
|
-
__prototype_singleton_class__{
|
36
|
-
table = {}
|
37
|
-
define_method('__prototype_table__'){ table }
|
38
|
-
}
|
39
|
-
__prototype_table__ # does not recurse!
|
40
|
-
end
|
25
|
+
VERSION = '2.0.0'
|
41
26
|
|
42
|
-
|
43
|
-
|
44
|
-
other.instance_variable_set ivar, value
|
45
|
-
end
|
46
|
-
__prototype_table__.clear
|
47
|
-
end
|
27
|
+
module ClassMethods
|
28
|
+
def version() VERSION end
|
48
29
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
30
|
+
def inherit c = Object, *a, &b
|
31
|
+
c = c.class unless Class === c
|
32
|
+
c = Class.new c
|
33
|
+
new c, *a, &b
|
34
|
+
end
|
35
|
+
alias_method "exnihilo", "inherit"
|
36
|
+
alias_method "ex_nihilo", "inherit"
|
53
37
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
38
|
+
def new c = Object, *a, &b
|
39
|
+
c = c.class unless Class === c
|
40
|
+
obj = c.new *a
|
41
|
+
prototyping obj, &b
|
42
|
+
obj
|
43
|
+
end
|
59
44
|
|
60
|
-
|
61
|
-
|
62
|
-
|
45
|
+
def clone src, *a, &b
|
46
|
+
c = src.class
|
47
|
+
c = Class.new c
|
48
|
+
dst = c.new *a
|
63
49
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
ivar = "@#{ m }"
|
69
|
-
tid = Thread.current.object_id.abs
|
70
|
-
missing = "__method_missing_#{ tid }__"
|
71
|
-
if a.size == 0
|
72
|
-
eval("defined? #{ ivar }") ? instance_variable_get(ivar) : method(missing).call(m, *a, &b)
|
73
|
-
elsif a.size == 1
|
74
|
-
instance_variable_set ivar, a.shift
|
75
|
-
else
|
76
|
-
method(missing).call(m, *a, &b)
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
}
|
50
|
+
sc =
|
51
|
+
class << src
|
52
|
+
self
|
53
|
+
end
|
81
54
|
|
82
|
-
|
55
|
+
modules = sc.instance_variable_get('@modules') || []
|
56
|
+
modules.each{|mod| extend dst, mod}
|
83
57
|
|
84
|
-
|
85
|
-
|
58
|
+
src.instance_variables.each do |ivar|
|
59
|
+
value = src.instance_variable_get ivar
|
60
|
+
dst.instance_variable_set ivar, value
|
86
61
|
end
|
62
|
+
prototyping dst, &b
|
63
|
+
dst
|
64
|
+
end
|
87
65
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
66
|
+
def prototyping obj, &b
|
67
|
+
obj.extend InstanceMethods
|
68
|
+
mod = Prototype.context &b
|
69
|
+
ivars = mod.__method__["instance_variables"].call()
|
70
|
+
ivars.each do |ivar|
|
71
|
+
value = mod.__method__["instance_variable_get"].call(ivar)
|
72
|
+
obj.instance_eval{ instance_variable_set ivar, value }
|
95
73
|
end
|
74
|
+
extend obj, mod
|
75
|
+
obj
|
76
|
+
end
|
96
77
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
78
|
+
def extend obj, mod
|
79
|
+
sc =
|
80
|
+
class << obj
|
81
|
+
self
|
82
|
+
end
|
83
|
+
sc.module_eval do
|
84
|
+
(@modules ||= []) << mod
|
85
|
+
include mod
|
86
|
+
end
|
87
|
+
end
|
101
88
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
end
|
112
|
-
t.update ivar => value
|
113
|
-
end
|
89
|
+
def prototyped? obj
|
90
|
+
sc =
|
91
|
+
class << obj
|
92
|
+
self
|
93
|
+
end
|
94
|
+
sc.module_eval do
|
95
|
+
defined?(@prototyped) and @prototyped
|
96
|
+
end
|
97
|
+
end
|
114
98
|
|
115
|
-
|
99
|
+
def prototyped! obj
|
100
|
+
sc =
|
101
|
+
class << obj
|
102
|
+
self
|
103
|
+
end
|
104
|
+
sc.module_eval do
|
105
|
+
@prototyped = true
|
116
106
|
end
|
117
107
|
end
|
118
108
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
109
|
+
def context &b
|
110
|
+
mod = Module.new
|
111
|
+
sc =
|
112
|
+
class << mod
|
113
|
+
self
|
114
|
+
end
|
115
|
+
|
116
|
+
sc.module_eval do
|
117
|
+
__method__ = {} and define_method(:__method__){ __method__ }
|
118
|
+
|
119
|
+
def __call__(m, *a, &b)
|
120
|
+
meth = __method__[m.to_s]
|
121
|
+
raise NoMethodError, m.to_s unless meth
|
122
|
+
meth.call *a, &b
|
123
|
+
end
|
124
|
+
|
125
|
+
alias_method '__define_method__', 'define_method'
|
123
126
|
end
|
124
127
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
#end
|
131
|
-
|
132
|
-
a = ivar[%r/\w+/]
|
133
|
-
defined = respond_to? a
|
134
|
-
unless defined
|
135
|
-
self.class.module_eval{ attribute a }
|
136
|
-
end
|
128
|
+
mod.methods.each{|m| mod.__method__[m] = mod.method(m) unless %w( __call__ __method__ ).include?(m)}
|
129
|
+
|
130
|
+
mod.methods.each do |m|
|
131
|
+
unless m =~ /^__|attribute/
|
132
|
+
sc.module_eval{ undef_method m }
|
137
133
|
end
|
138
134
|
end
|
139
135
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
136
|
+
sc.module_eval do
|
137
|
+
def method_missing m, *a, &b
|
138
|
+
if b
|
139
|
+
__define_method__ m, *a, &b
|
140
|
+
else
|
141
|
+
ivar = "@#{ m }"
|
142
|
+
case a.size
|
143
|
+
when 0
|
144
|
+
if eval("defined? #{ ivar }")
|
145
|
+
__call__ 'instance_variable_get', ivar
|
146
|
+
else
|
147
|
+
super
|
148
|
+
end
|
149
|
+
when 1
|
150
|
+
value = a.shift
|
151
|
+
__call__ 'instance_variable_set', ivar, value
|
152
|
+
else
|
153
|
+
super
|
154
|
+
end
|
155
|
+
end
|
147
156
|
end
|
148
157
|
end
|
149
158
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
159
|
+
mod.__call__ 'module_eval', &b if b
|
160
|
+
|
161
|
+
mod.__call__ 'module_eval' do
|
162
|
+
defined = __call('instance_methods').inject({}){|h,m| h.update m => true}
|
163
|
+
|
164
|
+
__call__('instance_variables').each do |ivar|
|
165
|
+
m = ivar[1..-1]
|
166
|
+
getter, setter, query = defined["#{ m }"], defined["#{ m }="], defined["#{ m }?"]
|
167
|
+
|
168
|
+
if getter.nil? and setter.nil? and query.nil?
|
169
|
+
__call__ 'attribute', m
|
170
|
+
next
|
171
|
+
end
|
172
|
+
if getter.nil?
|
173
|
+
__call__ 'module_eval', "def #{ m }() #{ ivar } end"
|
174
|
+
end
|
175
|
+
if setter.nil?
|
176
|
+
__call__ 'module_eval', "def #{ m }=(v) #{ ivar }=v end"
|
177
|
+
end
|
178
|
+
if query.nil?
|
179
|
+
__call__ 'module_eval', "def #{ m }?() defined?(#{ ivar }) and #{ ivar } end"
|
180
|
+
end
|
156
181
|
end
|
157
|
-
obj
|
158
182
|
end
|
159
|
-
end
|
160
183
|
|
161
|
-
|
162
|
-
c.extend ClassMethods
|
163
|
-
c.module_eval{ include InstanceMethods }
|
164
|
-
super
|
184
|
+
mod
|
165
185
|
end
|
166
186
|
end
|
187
|
+
extend ClassMethods
|
167
188
|
|
168
|
-
|
169
|
-
def
|
170
|
-
|
171
|
-
c = Class.new parent
|
172
|
-
c.extend Prototypical
|
173
|
-
c.__prototype_table__.update parent.__prototype_table__ if
|
174
|
-
parent.respond_to? '__prototype_table__'
|
175
|
-
c.__prototype_prototype__ &b
|
176
|
-
obj = c.new *a
|
177
|
-
obj
|
189
|
+
module InstanceMethods
|
190
|
+
def clone *a, &b
|
191
|
+
Prototype.clone self, *a, &b
|
178
192
|
end
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
c.extend Prototypical unless Prototypical === c
|
190
|
-
c.__prototype_table__.update parent.__prototype_table__ if
|
191
|
-
parent.respond_to? '__prototype_table__'
|
192
|
-
c.__prototype_prototype__ &b
|
193
|
-
obj.__prototype_init__ c
|
194
|
-
obj
|
193
|
+
def dup *a, &b
|
194
|
+
Prototype.clone self, *a, &b
|
195
|
+
end
|
196
|
+
def extend m=nil, &block
|
197
|
+
if block
|
198
|
+
prototyping(self, &block)
|
199
|
+
else
|
200
|
+
super(m)
|
201
|
+
end
|
202
|
+
self
|
195
203
|
end
|
196
204
|
end
|
205
|
+
include InstanceMethods
|
197
206
|
end
|
198
207
|
|
199
208
|
class Object
|
200
|
-
def Prototype(*a, &b) Prototype.
|
201
|
-
def prototype(*a, &b) Prototype.
|
202
|
-
def Prototyping(
|
203
|
-
def prototyping(
|
209
|
+
def Prototype(*a, &b) Prototype.inherit *a, &b end
|
210
|
+
def prototype(*a, &b) Prototype.inherit *a, &b end
|
211
|
+
def Prototyping(obj=nil, &b) Prototype.prototyping obj||self, &b end
|
212
|
+
def prototyping(obj=nil, &b) Prototype.prototyping obj||self, &b end
|
204
213
|
end
|
File without changes
|
data/samples/a.rb
CHANGED
data/samples/b.rb
CHANGED
@@ -9,9 +9,8 @@ DB = Prototype.new{
|
|
9
9
|
def connect() p [host, port] end
|
10
10
|
}
|
11
11
|
|
12
|
-
p DB
|
13
|
-
p DB.
|
14
|
-
p DB.
|
15
|
-
p DB.conn_string
|
12
|
+
p DB.host #=> "localhost"
|
13
|
+
p DB.port #=> 4242
|
14
|
+
p DB.conn_string #=> "localhost:4242"
|
16
15
|
|
17
|
-
DB.connect
|
16
|
+
DB.connect #=> ["locahost", 4242]
|
data/samples/c.rb
CHANGED
@@ -6,20 +6,19 @@ a = Prototype.new{
|
|
6
6
|
|
7
7
|
b = a.clone
|
8
8
|
|
9
|
-
p a.method
|
10
|
-
p b.method
|
9
|
+
p a.method #=> 42
|
10
|
+
p b.method #=> 42
|
11
11
|
|
12
12
|
a.extend{
|
13
13
|
def method2() '42' end
|
14
14
|
}
|
15
15
|
|
16
|
-
p a.method2
|
17
|
-
p b.method2
|
16
|
+
p a.respond_to?(:method2) #=> true
|
17
|
+
p b.respond_to?(:method2) #=> false
|
18
18
|
|
19
19
|
b.extend{
|
20
20
|
def method3() 42.0 end
|
21
21
|
}
|
22
22
|
|
23
|
-
p
|
24
|
-
p
|
25
|
-
|
23
|
+
p a.respond_to?(:method3) #=> false
|
24
|
+
p b.respond_to?(:method3) #=> true
|
data/samples/d.rb
CHANGED
@@ -3,10 +3,10 @@ require 'prototype'
|
|
3
3
|
proto = prototype{ attributes 'a' => 1, 'b' => 2, 'c' => 3 }
|
4
4
|
proto = prototype{ a 1; b 2; c 3 }
|
5
5
|
|
6
|
-
%w( a b c ).each{|attr| p proto.send(attr)}
|
6
|
+
%w( a b c ).each{|attr| p proto.send(attr)} #=> 1, 2, 3
|
7
7
|
|
8
8
|
clone = proto.clone
|
9
9
|
proto.c = 42
|
10
10
|
|
11
|
-
%w( a b c ).each{|attr| p proto.send(attr)}
|
12
|
-
%w( a b c ).each{|attr| p clone.send(attr)}
|
11
|
+
%w( a b c ).each{|attr| p proto.send(attr)} #=> 1, 2, 42
|
12
|
+
%w( a b c ).each{|attr| p clone.send(attr)} #=> 1, 2, 3
|
data/samples/e.rb
CHANGED
data/samples/f.rb
CHANGED
data/samples/g.rb
CHANGED
@@ -1,11 +1,9 @@
|
|
1
|
-
|
2
1
|
require 'prototype'
|
3
2
|
|
4
|
-
a = prototype
|
5
|
-
|
6
|
-
b = prototype(a){ @a, @b, @c = 4, 10, 2 }
|
3
|
+
a = prototype{ @a, @b, @c = 4, 10, 2 }
|
7
4
|
|
8
|
-
|
5
|
+
b = a.clone
|
9
6
|
|
10
|
-
|
7
|
+
b.extend{ def answer() a * b + c end }
|
11
8
|
|
9
|
+
p b.answer #=> 42
|
data/samples/h.rb
CHANGED
metadata
CHANGED
@@ -3,12 +3,12 @@ rubygems_version: 0.9.2
|
|
3
3
|
specification_version: 1
|
4
4
|
name: prototype
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version:
|
7
|
-
date: 2007-
|
6
|
+
version: 2.0.0
|
7
|
+
date: 2007-06-04 00:00:00 -06:00
|
8
8
|
summary: prototype
|
9
9
|
require_paths:
|
10
10
|
- lib
|
11
|
-
email: ara.t.howard@
|
11
|
+
email: ara.t.howard@gmail.com
|
12
12
|
homepage: http://codeforpeople.com/lib/ruby/prototype/
|
13
13
|
rubyforge_project:
|
14
14
|
description:
|
@@ -29,14 +29,13 @@ post_install_message:
|
|
29
29
|
authors:
|
30
30
|
- Ara T. Howard
|
31
31
|
files:
|
32
|
-
- a.rb
|
33
32
|
- gemspec.rb
|
34
33
|
- gen_readme.rb
|
35
34
|
- install.rb
|
36
35
|
- lib
|
37
|
-
- lib/prototype-
|
36
|
+
- lib/prototype-2.0.0.rb
|
38
37
|
- lib/prototype.rb
|
39
|
-
- prototype-
|
38
|
+
- prototype-2.0.0.gem
|
40
39
|
- README
|
41
40
|
- README.tmpl
|
42
41
|
- samples
|
@@ -67,7 +66,7 @@ dependencies:
|
|
67
66
|
version_requirement:
|
68
67
|
version_requirements: !ruby/object:Gem::Version::Requirement
|
69
68
|
requirements:
|
70
|
-
- -
|
69
|
+
- - ">="
|
71
70
|
- !ruby/object:Gem::Version
|
72
|
-
version: "3.
|
71
|
+
version: "3.3"
|
73
72
|
version:
|
data/a.rb
DELETED
data/lib/prototype-1.0.0.rb
DELETED
@@ -1,204 +0,0 @@
|
|
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 = '1.0.0'
|
30
|
-
def version() VERSION end
|
31
|
-
|
32
|
-
module Prototypical
|
33
|
-
module ClassMethods
|
34
|
-
def __prototype_table__ # uses closure/init to avoid instance-var
|
35
|
-
__prototype_singleton_class__{
|
36
|
-
table = {}
|
37
|
-
define_method('__prototype_table__'){ table }
|
38
|
-
}
|
39
|
-
__prototype_table__ # does not recurse!
|
40
|
-
end
|
41
|
-
|
42
|
-
def __prototype_table_inject__ other
|
43
|
-
__prototype_table__.each do |ivar, value|
|
44
|
-
other.instance_variable_set ivar, value
|
45
|
-
end
|
46
|
-
__prototype_table__.clear
|
47
|
-
end
|
48
|
-
|
49
|
-
def __prototype_eval__ &b
|
50
|
-
tid = Thread.current.object_id.abs
|
51
|
-
src, dst = "method_missing", "__method_missing_#{ tid }__"
|
52
|
-
aliased = false
|
53
|
-
|
54
|
-
__prototype_singleton_class__{
|
55
|
-
unless respond_to? dst
|
56
|
-
alias_method dst, src
|
57
|
-
aliased = true
|
58
|
-
end
|
59
|
-
|
60
|
-
def method_missing m, *a, &b
|
61
|
-
__prototype_barewords_can_set_and_get_ivars_and_define_methods__ m, *a, &b
|
62
|
-
end
|
63
|
-
|
64
|
-
def __prototype_barewords_can_set_and_get_ivars_and_define_methods__ m, *a, &b
|
65
|
-
if b
|
66
|
-
define_method m, *a, &b
|
67
|
-
else
|
68
|
-
ivar = "@#{ m }"
|
69
|
-
tid = Thread.current.object_id.abs
|
70
|
-
missing = "__method_missing_#{ tid }__"
|
71
|
-
if a.size == 0
|
72
|
-
eval("defined? #{ ivar }") ? instance_variable_get(ivar) : method(missing).call(m, *a, &b)
|
73
|
-
elsif a.size == 1
|
74
|
-
instance_variable_set ivar, a.shift
|
75
|
-
else
|
76
|
-
method(missing).call(m, *a, &b)
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
}
|
81
|
-
|
82
|
-
module_eval &b
|
83
|
-
|
84
|
-
ensure
|
85
|
-
__prototype_singleton_class__{ alias_method src, dst } if aliased
|
86
|
-
end
|
87
|
-
|
88
|
-
def __prototype_singleton_class__ &b
|
89
|
-
sc =
|
90
|
-
class << self
|
91
|
-
self
|
92
|
-
end
|
93
|
-
sc.module_eval &b if b
|
94
|
-
sc
|
95
|
-
end
|
96
|
-
|
97
|
-
def __prototype_prototype__ &b
|
98
|
-
return unless b
|
99
|
-
|
100
|
-
__prototype_eval__ &b
|
101
|
-
|
102
|
-
table =
|
103
|
-
instance_variables.inject({}) do |t,ivar|
|
104
|
-
value =
|
105
|
-
instance_eval do
|
106
|
-
begin
|
107
|
-
instance_variable_get ivar
|
108
|
-
ensure
|
109
|
-
remove_instance_variable ivar
|
110
|
-
end
|
111
|
-
end
|
112
|
-
t.update ivar => value
|
113
|
-
end
|
114
|
-
|
115
|
-
__prototype_table__.update table
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
module InstanceMethods
|
120
|
-
def initialize *a, &b
|
121
|
-
__prototype_init__
|
122
|
-
super
|
123
|
-
end
|
124
|
-
|
125
|
-
def __prototype_init__ c = self.class
|
126
|
-
c.__prototype_table__.each do |ivar, value|
|
127
|
-
#defined = instance_eval "defined? #{ ivar }"
|
128
|
-
#unless defined
|
129
|
-
instance_variable_set ivar, value
|
130
|
-
#end
|
131
|
-
|
132
|
-
a = ivar[%r/\w+/]
|
133
|
-
defined = respond_to? a
|
134
|
-
unless defined
|
135
|
-
self.class.module_eval{ attribute a }
|
136
|
-
end
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
def extend *a, &b
|
141
|
-
unless a.empty?
|
142
|
-
super
|
143
|
-
else
|
144
|
-
self.class.__prototype_prototype__ &b
|
145
|
-
__prototype_init__
|
146
|
-
self
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
def clone *a, &b
|
151
|
-
obj = prototype(self.class, *a, &b)
|
152
|
-
instance_variables.each do |ivar|
|
153
|
-
next if obj.instance_eval("defined? #{ ivar }")
|
154
|
-
value = instance_variable_get ivar
|
155
|
-
obj.instance_variable_set ivar, value
|
156
|
-
end
|
157
|
-
obj
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
def self.extend_object c
|
162
|
-
c.extend ClassMethods
|
163
|
-
c.module_eval{ include InstanceMethods }
|
164
|
-
super
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
class << self
|
169
|
-
def new parent = Object, *a, &b
|
170
|
-
parent = parent.class unless Class === parent
|
171
|
-
c = Class.new parent
|
172
|
-
c.extend Prototypical
|
173
|
-
c.__prototype_table__.update parent.__prototype_table__ if
|
174
|
-
parent.respond_to? '__prototype_table__'
|
175
|
-
c.__prototype_prototype__ &b
|
176
|
-
obj = c.new *a
|
177
|
-
obj
|
178
|
-
end
|
179
|
-
|
180
|
-
alias_method "exnihilo", "new"
|
181
|
-
alias_method "ex_nihilo", "new"
|
182
|
-
|
183
|
-
def prototyping obj, *a, &b
|
184
|
-
c =
|
185
|
-
class << obj
|
186
|
-
self
|
187
|
-
end
|
188
|
-
parent = c.class
|
189
|
-
c.extend Prototypical unless Prototypical === c
|
190
|
-
c.__prototype_table__.update parent.__prototype_table__ if
|
191
|
-
parent.respond_to? '__prototype_table__'
|
192
|
-
c.__prototype_prototype__ &b
|
193
|
-
obj.__prototype_init__ c
|
194
|
-
obj
|
195
|
-
end
|
196
|
-
end
|
197
|
-
end
|
198
|
-
|
199
|
-
class Object
|
200
|
-
def Prototype(*a, &b) Prototype.new *a, &b end
|
201
|
-
def prototype(*a, &b) Prototype.new *a, &b end
|
202
|
-
def Prototyping(*a, &b) Prototype.prototyping self, *a, &b end
|
203
|
-
def prototyping(*a, &b) Prototype.prototyping self, *a, &b end
|
204
|
-
end
|