prototype 0.0.0 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +67 -1
- data/lib/prototype-0.0.0.rb +144 -41
- data/lib/prototype.rb +144 -41
- data/samples/c.rb +16 -1
- data/samples/d.rb +12 -0
- data/samples/e.rb +8 -0
- data/samples/f.rb +9 -0
- data/samples/g.rb +11 -0
- metadata +5 -2
- data/prototype.rb +0 -74
data/README
CHANGED
@@ -21,7 +21,9 @@ WHY
|
|
21
21
|
|
22
22
|
EXAMPLES
|
23
23
|
|
24
|
+
__________________________________________
|
24
25
|
~ > cat samples/a.rb
|
26
|
+
__________________________________________
|
25
27
|
require 'prototype'
|
26
28
|
|
27
29
|
singleton = Prototype.new{
|
@@ -33,13 +35,16 @@ EXAMPLES
|
|
33
35
|
p singleton.answer
|
34
36
|
|
35
37
|
|
38
|
+
__________________________________________
|
36
39
|
~ > ruby samples/a.rb
|
40
|
+
__________________________________________
|
37
41
|
42
|
38
42
|
|
39
43
|
|
40
44
|
|
41
|
-
|
45
|
+
__________________________________________
|
42
46
|
~ > cat samples/b.rb
|
47
|
+
__________________________________________
|
43
48
|
require 'prototype'
|
44
49
|
|
45
50
|
DB = Prototype.new{
|
@@ -55,10 +60,71 @@ EXAMPLES
|
|
55
60
|
DB.connect
|
56
61
|
|
57
62
|
|
63
|
+
__________________________________________
|
58
64
|
~ > ruby samples/b.rb
|
65
|
+
__________________________________________
|
59
66
|
"localhost"
|
60
67
|
4242
|
61
68
|
["localhost", 4242]
|
69
|
+
|
70
|
+
|
71
|
+
|
72
|
+
__________________________________________
|
73
|
+
~ > cat samples/e.rb
|
74
|
+
__________________________________________
|
75
|
+
require 'prototype'
|
76
|
+
|
77
|
+
proto = prototype{
|
78
|
+
@a = 40
|
79
|
+
@b = 2
|
80
|
+
}
|
81
|
+
|
82
|
+
p(proto.a + proto.b)
|
83
|
+
|
84
|
+
|
85
|
+
~ > ruby -Ilib samples/e.rb
|
86
|
+
42
|
87
|
+
|
88
|
+
|
89
|
+
|
90
|
+
__________________________________________
|
91
|
+
~ > 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
|
+
|
101
|
+
[a, b, c].each{|obj| p(obj.a * obj.b + obj.c) }
|
102
|
+
|
103
|
+
|
104
|
+
~ > ruby -Ilib samples/f.rb
|
105
|
+
42
|
106
|
+
42
|
107
|
+
42
|
108
|
+
|
109
|
+
|
110
|
+
|
111
|
+
__________________________________________
|
112
|
+
~ > cat samples/g.rb
|
113
|
+
__________________________________________
|
114
|
+
require 'prototype'
|
115
|
+
|
116
|
+
a = prototype
|
117
|
+
|
118
|
+
b = prototype(a){ @a, @b, @c = 4, 10, 2 }
|
119
|
+
|
120
|
+
a.extend{ def answer() a * b + c end }
|
121
|
+
|
122
|
+
p b.answer
|
123
|
+
|
124
|
+
|
125
|
+
~ > ruby -Ilib samples/g.rb
|
126
|
+
42
|
127
|
+
|
62
128
|
|
63
129
|
|
64
130
|
DOCS
|
data/lib/prototype-0.0.0.rb
CHANGED
@@ -4,75 +4,178 @@
|
|
4
4
|
#
|
5
5
|
|
6
6
|
class Prototype
|
7
|
-
VERSION = '0.
|
7
|
+
VERSION = '0.1.0'
|
8
8
|
|
9
|
-
|
10
|
-
|
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}
|
11
16
|
|
12
|
-
|
13
|
-
|
17
|
+
names_and_defaults = {}
|
18
|
+
hashes.each{|h| names_and_defaults.update h}
|
19
|
+
names.each{|name| names_and_defaults.update name => nil}
|
14
20
|
|
15
|
-
|
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 }?"
|
16
27
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
end
|
21
|
-
end
|
28
|
+
define_method(setter) do |value|
|
29
|
+
instance_variable_set ivar, value
|
30
|
+
end
|
22
31
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
ivar = "@%s" % m
|
27
|
-
if a.size == 0
|
28
|
-
if defined? ivar
|
29
|
-
instance_variable_get ivar
|
30
|
-
else
|
31
|
-
super
|
32
|
-
end
|
33
|
-
elsif a.size == 1
|
34
|
-
instance_variable_set ivar, a.shift
|
35
|
-
attr_accessor m
|
32
|
+
define_method(getter) do |*value|
|
33
|
+
unless value.empty?
|
34
|
+
send setter, value.shift
|
36
35
|
else
|
37
|
-
|
36
|
+
defined = instance_eval "defined? #{ ivar }"
|
37
|
+
unless defined
|
38
|
+
send setter, instance_eval(&init)
|
39
|
+
end
|
40
|
+
instance_variable_get ivar
|
38
41
|
end
|
39
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
|
40
69
|
end
|
41
|
-
|
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
|
42
83
|
|
43
|
-
|
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
|
44
133
|
|
45
134
|
table =
|
46
|
-
|
135
|
+
instance_variables.inject({}) do |t,ivar|
|
47
136
|
value =
|
48
|
-
|
137
|
+
instance_eval do
|
49
138
|
begin
|
50
139
|
instance_variable_get ivar
|
51
140
|
ensure
|
52
141
|
remove_instance_variable ivar
|
53
142
|
end
|
54
143
|
end
|
55
|
-
|
144
|
+
t.update ivar => value
|
56
145
|
end
|
57
146
|
|
58
|
-
|
147
|
+
__prototable__.update table
|
148
|
+
end
|
59
149
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
end
|
67
|
-
code
|
150
|
+
def self.extend_object other
|
151
|
+
other.extend ClassMethods
|
152
|
+
other.module_eval{ include InstanceMethods }
|
153
|
+
super
|
154
|
+
end
|
155
|
+
end
|
68
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
|
69
165
|
obj = c.new *a
|
70
|
-
|
71
166
|
obj
|
72
167
|
end
|
73
168
|
|
74
169
|
alias_method "exnihilo", "new"
|
75
170
|
alias_method "ex_nihilo", "new"
|
76
|
-
|
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
|
77
180
|
end
|
78
181
|
end
|
data/lib/prototype.rb
CHANGED
@@ -4,75 +4,178 @@
|
|
4
4
|
#
|
5
5
|
|
6
6
|
class Prototype
|
7
|
-
VERSION = '0.
|
7
|
+
VERSION = '0.1.0'
|
8
8
|
|
9
|
-
|
10
|
-
|
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}
|
11
16
|
|
12
|
-
|
13
|
-
|
17
|
+
names_and_defaults = {}
|
18
|
+
hashes.each{|h| names_and_defaults.update h}
|
19
|
+
names.each{|name| names_and_defaults.update name => nil}
|
14
20
|
|
15
|
-
|
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 }?"
|
16
27
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
end
|
21
|
-
end
|
28
|
+
define_method(setter) do |value|
|
29
|
+
instance_variable_set ivar, value
|
30
|
+
end
|
22
31
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
ivar = "@%s" % m
|
27
|
-
if a.size == 0
|
28
|
-
if defined? ivar
|
29
|
-
instance_variable_get ivar
|
30
|
-
else
|
31
|
-
super
|
32
|
-
end
|
33
|
-
elsif a.size == 1
|
34
|
-
instance_variable_set ivar, a.shift
|
35
|
-
attr_accessor m
|
32
|
+
define_method(getter) do |*value|
|
33
|
+
unless value.empty?
|
34
|
+
send setter, value.shift
|
36
35
|
else
|
37
|
-
|
36
|
+
defined = instance_eval "defined? #{ ivar }"
|
37
|
+
unless defined
|
38
|
+
send setter, instance_eval(&init)
|
39
|
+
end
|
40
|
+
instance_variable_get ivar
|
38
41
|
end
|
39
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
|
40
69
|
end
|
41
|
-
|
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
|
42
83
|
|
43
|
-
|
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
|
44
133
|
|
45
134
|
table =
|
46
|
-
|
135
|
+
instance_variables.inject({}) do |t,ivar|
|
47
136
|
value =
|
48
|
-
|
137
|
+
instance_eval do
|
49
138
|
begin
|
50
139
|
instance_variable_get ivar
|
51
140
|
ensure
|
52
141
|
remove_instance_variable ivar
|
53
142
|
end
|
54
143
|
end
|
55
|
-
|
144
|
+
t.update ivar => value
|
56
145
|
end
|
57
146
|
|
58
|
-
|
147
|
+
__prototable__.update table
|
148
|
+
end
|
59
149
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
end
|
67
|
-
code
|
150
|
+
def self.extend_object other
|
151
|
+
other.extend ClassMethods
|
152
|
+
other.module_eval{ include InstanceMethods }
|
153
|
+
super
|
154
|
+
end
|
155
|
+
end
|
68
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
|
69
165
|
obj = c.new *a
|
70
|
-
|
71
166
|
obj
|
72
167
|
end
|
73
168
|
|
74
169
|
alias_method "exnihilo", "new"
|
75
170
|
alias_method "ex_nihilo", "new"
|
76
|
-
|
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
|
77
180
|
end
|
78
181
|
end
|
data/samples/c.rb
CHANGED
@@ -4,7 +4,22 @@ a = Prototype.new{
|
|
4
4
|
def method() 42 end
|
5
5
|
}
|
6
6
|
|
7
|
-
b =
|
7
|
+
b = a.clone
|
8
8
|
|
9
|
+
p a.method
|
9
10
|
p b.method
|
10
11
|
|
12
|
+
a.extend{
|
13
|
+
def method2() '42' end
|
14
|
+
}
|
15
|
+
|
16
|
+
p a.method2
|
17
|
+
p b.method2
|
18
|
+
|
19
|
+
b.extend{
|
20
|
+
def method3() 42.0 end
|
21
|
+
}
|
22
|
+
|
23
|
+
p b.method3
|
24
|
+
p a.method3 # throws error!
|
25
|
+
|
data/samples/d.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'prototype'
|
2
|
+
|
3
|
+
proto = prototype{ attributes 'a' => 1, 'b' => 2, 'c' => 3 }
|
4
|
+
proto = prototype{ a 1; b 2; c 3 }
|
5
|
+
|
6
|
+
%w( a b c ).each{|attr| p proto.send(attr)}
|
7
|
+
|
8
|
+
clone = proto.clone
|
9
|
+
proto.c = 42
|
10
|
+
|
11
|
+
%w( a b c ).each{|attr| p proto.send(attr)}
|
12
|
+
%w( a b c ).each{|attr| p clone.send(attr)}
|
data/samples/e.rb
ADDED
data/samples/f.rb
ADDED
data/samples/g.rb
ADDED
metadata
CHANGED
@@ -3,7 +3,7 @@ rubygems_version: 0.8.11
|
|
3
3
|
specification_version: 1
|
4
4
|
name: prototype
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
6
|
+
version: 0.1.0
|
7
7
|
date: 2006-07-12 00:00:00.000000 -06:00
|
8
8
|
summary: prototype
|
9
9
|
require_paths:
|
@@ -30,7 +30,6 @@ authors:
|
|
30
30
|
- Ara T. Howard
|
31
31
|
files:
|
32
32
|
- lib
|
33
|
-
- prototype.rb
|
34
33
|
- install.rb
|
35
34
|
- gemspec.rb
|
36
35
|
- samples
|
@@ -40,6 +39,10 @@ files:
|
|
40
39
|
- samples/c.rb
|
41
40
|
- samples/a.rb
|
42
41
|
- samples/b.rb
|
42
|
+
- samples/d.rb
|
43
|
+
- samples/e.rb
|
44
|
+
- samples/f.rb
|
45
|
+
- samples/g.rb
|
43
46
|
test_files: []
|
44
47
|
rdoc_options: []
|
45
48
|
extra_rdoc_files: []
|
data/prototype.rb
DELETED
@@ -1,74 +0,0 @@
|
|
1
|
-
|
2
|
-
#
|
3
|
-
# http://en.wikipedia.org/wiki/Prototype-based_programming
|
4
|
-
#
|
5
|
-
|
6
|
-
class Prototype
|
7
|
-
class << self
|
8
|
-
def new proto = Object, *a, &b
|
9
|
-
proto = proto.protoclass unless Class === proto
|
10
|
-
|
11
|
-
c = Class.new proto
|
12
|
-
|
13
|
-
c.module_eval do
|
14
|
-
define_method(:protoclass) do
|
15
|
-
c
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
c.module_eval <<-code
|
20
|
-
class << self
|
21
|
-
def method_missing m, *a, &b
|
22
|
-
ivar = "@%s" % m
|
23
|
-
if a.size == 0
|
24
|
-
if defined? ivar
|
25
|
-
instance_variable_get ivar
|
26
|
-
else
|
27
|
-
super
|
28
|
-
end
|
29
|
-
elsif a.size == 1
|
30
|
-
instance_variable_set ivar, a.shift
|
31
|
-
attr_accessor m
|
32
|
-
else
|
33
|
-
super
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
code
|
38
|
-
|
39
|
-
c.module_eval &b if b
|
40
|
-
|
41
|
-
table =
|
42
|
-
c.instance_variables.inject({}) do |t,ivar|
|
43
|
-
value =
|
44
|
-
c.instance_eval do
|
45
|
-
begin
|
46
|
-
instance_variable_get ivar
|
47
|
-
ensure
|
48
|
-
remove_instance_variable ivar
|
49
|
-
end
|
50
|
-
end
|
51
|
-
t.update ivar => value
|
52
|
-
end
|
53
|
-
|
54
|
-
c.const_set 'PROTOTABLE', table
|
55
|
-
|
56
|
-
c.module_eval <<-code
|
57
|
-
def initialize(*a, &b)
|
58
|
-
PROTOTABLE.each do |ivar, value|
|
59
|
-
instance_variable_set ivar, value
|
60
|
-
end
|
61
|
-
super
|
62
|
-
end
|
63
|
-
code
|
64
|
-
|
65
|
-
obj = c.new *a
|
66
|
-
|
67
|
-
obj
|
68
|
-
end
|
69
|
-
|
70
|
-
alias_method "exnihilo", "new"
|
71
|
-
alias_method "ex_nihilo", "new"
|
72
|
-
alias_method "clone", "new"
|
73
|
-
end
|
74
|
-
end
|