striuct 0.0.11.1 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -6,56 +6,63 @@
6
6
 
7
7
  == DESCRIPTION
8
8
 
9
- Striuct means Strict Struct.
10
- Handy and safty than Ruby's Standard Struct.
9
+ Striuct = (YetAnotherStruct << safety << useful)
11
10
 
12
11
  == FEATURES
13
- * Provides automated checking for your setters.
14
12
  * When you link a object, Striuct checks "They are valid objects?".
15
- These checkers are not only Type Checker. They judge under your expressions.
16
- * when use "inference", member will be fixed first passed object's class
17
- * After check, you can add one-step before link a object (call "flavor" at here).
18
- * You will be set default-value, and we have different meanings between nil and default-value.
19
- * without undesirable naming for conflict, no-identifier, and more cases
20
- * Base API looks like Ruby's standard Struct
21
- * not taint your name-space(exclude striuct/import)
22
- * pure-ruby
13
+ These checkers don't depend only types(class).
14
+
15
+ The safety is made from your expressions.
16
+ * When use "inference", member will be fixed under class of first passed object.
17
+ * It is without undesirable naming of conflict, no-identifier and some cases.
18
+ * You can add a step just before link a object. (named "flavor" at here)
19
+ * You can use default-value, and we have different meanings between nil and default-value.
20
+ * It is easy to alias member name.
21
+ * You can use inherite of structual class.
22
+ * Base API looks like Struct.
23
+ * No taint your name-space.
24
+ * Pure Ruby
23
25
 
24
26
  == SYNOPSIS
25
27
 
26
28
  * setup
27
29
  require 'striuct'
28
30
 
29
- * Macro "member" provides one of Struct+ interface.
30
- It checks under conditions when change to link other.
31
+ * use two namespace (same meanings)
32
+ Striuct
33
+ StrictStruct
34
+
35
+ === Struct+ "Safety"
36
+
37
+ ==== "member" macro
38
+
39
+ * Use "member" and you get a accessor, it looks Struct with tester(validator)s.
31
40
  class User < Striuct.new
32
- member :id, Integer
33
- member :address, /\A((\w+) ?)+\z/
34
- member :age, (20..140)
35
- member :name, /\A\w+\z/, /\A\w+ \w+\z/
41
+ member :id, Integer
42
+ member :age, (20..140)
43
+ member :name, OR(/\A\w+\z/, /\A\w+ \w+\z/)
36
44
  end
37
45
 
38
46
  # pass
39
- user = User.new 128381, 'Tokyo Japan', 20
47
+ user = User.new 128381, 20
40
48
 
41
49
  # pass
42
50
  user.age = 30
43
- user.name = 'taro yamada'
51
+ user[2] = 'foo bar'
44
52
 
45
53
  # fail
46
54
  user[:id] = 10.0
47
- user[1] = 'Tokyo-to'
48
55
  user.age = 19
49
- user.name = nil
56
+ user[2] = nil
50
57
 
51
- * more detail checker do you need, you can use functional object here.
58
+ * Use functional object and you get a tester on upstairs.
52
59
  module Game
53
60
  class Character
54
61
  end
55
62
 
56
63
  class DB < Striuct.new
57
- member :monsters, ->monsters{(monsters - characters).empty?}
58
- member :characters, ->characters{characters.all?{|c|c.kind_of? Character}}
64
+ member :monsters, ->list{(list - characters).empty?}
65
+ member :characters, GENERICS(Character)
59
66
  end
60
67
 
61
68
  monster = Character.new
@@ -68,16 +75,16 @@ Handy and safty than Ruby's Standard Struct.
68
75
  db.characters = [monster, Character.new]
69
76
 
70
77
  # fail
71
- db.monsters = [:dummy]
78
+ db.monsters = [Character.new]
72
79
 
73
80
  # pass
74
81
  db.monsters = [monster]
75
82
  end
76
83
 
77
- * "inference", check under first passed object's class
84
+ * Use "inference" and all instance test under class of first passed object.
78
85
  class FlexibleContainer < Striuct.new
79
86
  member :anything, inference
80
- member :number, inference, Numeric
87
+ member :number, Numeric, inference
81
88
  end
82
89
 
83
90
  fc1, fc2 = FlexibleContainer.new, FlexibleContainer.new
@@ -100,7 +107,50 @@ Handy and safty than Ruby's Standard Struct.
100
107
  # fail
101
108
  fc2.number = 1
102
109
 
103
- * with flavor for type cast
110
+ ==== Protect from risks in naming members
111
+
112
+ * Standard Struct dosen't check member-name.
113
+ NoGuard = Struct.new :object_id, :'? !'
114
+ noguard = NoGuard.new false
115
+ noguard.object_id #=> false
116
+ noguard.methods.include?(:'? !') #=> false(lost!!)
117
+
118
+ * Striuct provides safety levels for this. (default: :prevent)
119
+ class SafetyNaming < Striuct.new
120
+ begin
121
+ member :object_id
122
+ rescue
123
+ p $!
124
+ end
125
+
126
+ begin
127
+ member :'? !'
128
+ rescue
129
+ p $!
130
+ end
131
+
132
+ # set lower
133
+ protect_level :struct
134
+
135
+ member :object_id, :'? !'
136
+ end
137
+
138
+ ==== Support utils
139
+
140
+ * valid? / acccept? / sufficient? # can set a argument to a member
141
+ * conditionable? # can set a condition for any members
142
+ * inference? # inference member and no passed any object
143
+ * restrict? # has any conditions for a member
144
+ * strict? # now, all members are passed any conditions
145
+ * secure? # instance and class are fixed and strict
146
+ * cname? # can use member name under protect level
147
+
148
+ === Struct+ "Handy"
149
+
150
+ ==== Flavor
151
+
152
+ * Block with member macro, it is called "flavor" at here.
153
+ Below cases for type cast.
104
154
  class User2 < Striuct.new
105
155
  member :age, /\A\d+\z/, Numeric do |arg|
106
156
  Integer arg
@@ -117,13 +167,11 @@ Handy and safty than Ruby's Standard Struct.
117
167
  user2.age = '10' #=> 10(Fixnum)
118
168
 
119
169
  user2.name = 10 #=> :10(Symbol)
170
+ user2.name = Class #=> :Class(Symbol)
120
171
 
121
- * but, linked objects are able to clash
122
- user.strict? #=> true
123
- user.address.clear
124
- user.strict? #=> false
172
+ ==== Default
125
173
 
126
- * use default value
174
+ * provides default value
127
175
  class User3 < Striuct.new
128
176
  member :lank, Fixnum
129
177
  default :lank, 3
@@ -133,62 +181,71 @@ Handy and safty than Ruby's Standard Struct.
133
181
  user3 = User3.new
134
182
  user3.lank #=> 3
135
183
 
136
- * Standard Struct always define "nil is default". ...realy?
137
- user3.name #=> nil
138
- user3.assign? :name #=> false
139
- user3.name = nil
140
- user3.assign? :name #=> true
141
-
142
- * Standard Struct no check member name.
143
- NoGuard = Struct.new :__send__, :'? !'
144
- noguard = NoGuard.new false
145
- p noguard.__send__
146
- p noguard.methods.include?(:'? !') # lost!!
184
+ * Standard Struct always define "nil is default". Realy?
185
+ user3.name #=> nil
186
+ user3.assign? :name #=> false
187
+ user3.name = nil
188
+ user3.assign? :name #=> true
147
189
 
148
- * Striuct provides safety levels for naming.
149
- class SafetyNaming < Striuct.new
150
- begin
151
- member :__send__
152
- rescue
153
- p $!
154
- end
155
-
156
- begin
157
- member :'? !'
158
- rescue
159
- p $!
160
- end
161
-
162
- protect_level :struct
163
-
164
- member :__send__, :'? !'
190
+ ==== Alias
191
+
192
+ * alias member name
193
+ class User3
194
+ alias_member :position, :lank
165
195
  end
196
+
197
+ user3.lank.equal? user3.position #=> true
198
+ user3[:lank].equal? user3[:position] #=> true
199
+ user3[:position] = 4
200
+ user3.lank #=> 4
201
+
202
+ ==== Inherit
203
+
204
+ * (writing...)
205
+
206
+ ==== Lock
166
207
 
208
+ * (writing...)
167
209
 
168
- * Of course, keeping Struct's good interface
169
- Sth1 = Striuct.new :id, :last_name, :family_name, :address, :age
210
+ ==== New Constructors
170
211
 
171
- Sth2 = Striuct.new do
212
+ * Subclass.define reject floating object.
213
+ * block parameter is new instance
214
+ * except if no finished to assign each member
215
+ * returning object is tested strict(optional)
216
+ * returning object is locked(optional)
217
+ user3 = User3.define do |r|
218
+ r.lank = 10
219
+ r.name = 'foo'
220
+ end
221
+
222
+ * Subclass.[](load_pairs) make from Hash and like Hash
223
+ user3 = User3[lank: 10, name: 'foo']
224
+
225
+ === Almost interfaces are keeping Struct has.
226
+
227
+ Sth1 = Striuct.new do
172
228
  def my_special_method
173
229
  end
174
230
  end
175
231
 
176
- Sth2.new.respond_to?(:my_special_method) #=> true
232
+ Sth1.new.respond_to?(:my_special_method) #=> true
233
+
234
+ === HashLike
235
+
236
+ * some interfaces import from Hash
177
237
 
178
- * Here, not taint your name-space. but enhancers are too, you can choose it.
179
- require 'striuct/import'
238
+ * easy cast to Hash
239
+ user3.to_h #=> {:lank=>3, :name=>nil}
180
240
 
181
- * run example.rb
182
241
 
183
- * EasyGuide (in Japanese)
184
- https://github.com/kachick/striuct/wiki/EasyGuide
242
+ == Note
185
243
 
244
+ * Documents are poor
186
245
 
187
246
  == REQUIREMENTS
188
247
 
189
- === Ruby
190
- * 1.9.3
191
- * 1.9.2
248
+ * Ruby 1.9.2 and later (tested 1.9.2, 1.9.3)
192
249
 
193
250
  == INSTALL
194
251
 
data/Rakefile CHANGED
@@ -1,5 +1,5 @@
1
1
  require 'rubygems'
2
- gem 'hoe', '>= 2.12.4'
2
+ gem 'hoe', '~> 2.13.0'
3
3
  require 'hoe'
4
4
  require 'fileutils'
5
5
 
@@ -10,8 +10,10 @@ Hoe.plugin :newgem
10
10
  # Generate all the Rake tasks
11
11
  # Run 'rake -T' to see list of generated tasks (from gem root directory)
12
12
  $hoe = Hoe.spec 'striuct' do
13
- self.developer 'Kenichi Kamiya', 'kachick1+ruby@gmail.com'
14
- self.rubyforge_name = self.name # TODO this is default value
13
+ developer 'Kenichi Kamiya', 'kachick1+ruby@gmail.com'
14
+ self.rubyforge_name = self.name
15
+ require_ruby_version '>= 1.9.2'
16
+ dependency 'yard', '~> 0.7.4', :development
15
17
  end
16
18
 
17
19
  require 'newgem/tasks'
@@ -0,0 +1,56 @@
1
+ #/usr/bin/ruby -w
2
+
3
+ require 'benchmark'
4
+ require_relative '../lib/striuct'
5
+
6
+ XStruct = Struct.new :any, :no_use1, :no_use2
7
+
8
+ XStriuct = Striuct.define do
9
+ member :any
10
+ member :int, Integer
11
+ member :truthy, ->v{v}
12
+ end
13
+
14
+ xstruct = XStruct.new
15
+ xstriuct = XStriuct.new
16
+
17
+ TIMES = 100000
18
+ OBJ = 123
19
+
20
+ Benchmark.bm do |bm|
21
+ bm.report 'Struct(equal Noguard): Setter' do
22
+ TIMES.times do
23
+ xstruct.any = OBJ
24
+ end
25
+ end
26
+
27
+ bm.report 'Struct: Reader' do
28
+ TIMES.times do
29
+ xstruct.any
30
+ end
31
+ end
32
+
33
+ bm.report 'Striuct(when Noguard): Setter' do
34
+ TIMES.times do
35
+ xstriuct.any = OBJ
36
+ end
37
+ end
38
+
39
+ bm.report 'Striuct(guard under class): Setter' do
40
+ TIMES.times do
41
+ xstriuct.int = OBJ
42
+ end
43
+ end
44
+
45
+ bm.report 'Striuct(guard under function)' do
46
+ TIMES.times do
47
+ xstriuct.truthy = OBJ
48
+ end
49
+ end
50
+
51
+ bm.report 'Striuct: Reader' do
52
+ TIMES.times do
53
+ xstriuct.any
54
+ end
55
+ end
56
+ end
@@ -1,27 +1,27 @@
1
1
  #/usr/bin/ruby -w
2
2
 
3
- require_relative 'lib/striuct'
3
+ require_relative '../lib/striuct'
4
4
 
5
5
  def debug(message)
6
- puts "line: #{caller[0].slice(/:(\w+)/, 1)}"
6
+ puts "line: #{caller.first.slice(/:(\w+)/, 1)}"
7
7
  puts message.inspect, '-' * 80
8
8
  end
9
9
 
10
- #* Macro "member" provides one of Struct+ interfaces for condtions and a flavor.
10
+
11
+ # 1. Struct+ "Secure"
12
+
13
+ # macro "member" provides to use condtions
11
14
  class User < Striuct.new
12
- member :id, Integer
13
- member :address, /\A((\w+) ?)+\z/
14
- member :age, (20..140)
15
- member :name, /\A\w+\z/, /\A\w+ \w+\z/
15
+ member :id, Integer
16
+ member :age, (20..140)
17
+ member :name, OR(/\A\w+\z/, /\A\w+ \w+\z/)
16
18
  end
17
19
 
18
- # pass
19
- user = User.new 128381, 'Tokyo Japan', 20
20
+ user = User.new 128381, 20
20
21
  debug user
21
22
 
22
- # pass
23
23
  user.age = 30
24
- user.name = 'taro yamada'
24
+ user[2] = 'taro yamada'
25
25
  debug user
26
26
 
27
27
  # fail (Exception Striuct::ConditionError)
@@ -31,12 +31,6 @@ rescue
31
31
  debug $!
32
32
  end
33
33
 
34
- begin
35
- user[1] = 'Tokyo-to'
36
- rescue
37
- debug $!
38
- end
39
-
40
34
  begin
41
35
  user.age = 19
42
36
  rescue
@@ -44,25 +38,19 @@ rescue
44
38
  end
45
39
 
46
40
  begin
47
- user.name = nil
41
+ user[2] = 'typo! name'
48
42
  rescue
49
43
  debug $!
50
44
  end
51
45
 
52
- #* but, linked objects are able to clash
53
- debug user
54
- debug user.strict?
55
- debug user
56
- debug user.strict?
57
-
58
- # more detail checker do you need, you can use functional object.
46
+ # more detail checker do you need, use functional object
59
47
  module Game
60
48
  class Character
61
49
  end
62
50
 
63
51
  class DB < Striuct.new
64
- member :monsters, ->monsters{(monsters - characters).empty?}
65
- member :characters, ->characters{characters.all?{|c|c.kind_of? Character}}
52
+ member :monsters, ->list{(list - characters).empty?}
53
+ member :characters, GENERICS(Character)
66
54
  end
67
55
 
68
56
  monster = Character.new
@@ -78,7 +66,7 @@ module Game
78
66
  debug db
79
67
 
80
68
  begin
81
- db.monsters = [:dummy]
69
+ db.monsters = [Character.new]
82
70
  rescue
83
71
  debug $!
84
72
  end
@@ -87,10 +75,10 @@ module Game
87
75
  debug db
88
76
  end
89
77
 
90
- # "inference", check under first passed object's class
78
+ # through "inference", and check under first passed object class
91
79
  class FlexibleContainer < Striuct.new
92
80
  member :anything, inference
93
- member :number, inference, Numeric
81
+ member :number, Numeric, inference
94
82
  end
95
83
 
96
84
  fc1, fc2 = FlexibleContainer.new, FlexibleContainer.new
@@ -127,15 +115,43 @@ rescue
127
115
  debug $!
128
116
  end
129
117
 
130
-
131
- # with flavor for type cast
118
+ # Standard Struct not check member name.
119
+ NoGuard = Struct.new :__send__, :'? !'
120
+ noguard = NoGuard.new false
121
+ debug noguard.__send__
122
+ debug noguard.methods.include?(:'? !') # lost!!
123
+
124
+ # Striuct provides safety levels for naming.
125
+ class SafetyNaming < Striuct.new
126
+ begin
127
+ member :__send__
128
+ rescue
129
+ debug $!
130
+ end
131
+
132
+ begin
133
+ member :'? !'
134
+ rescue
135
+ debug $!
136
+ end
137
+
138
+ # set lower
139
+ protect_level :struct
140
+
141
+ member :__send__, :'? !'
142
+ end
143
+
144
+ # 2. Struct+ "Handy"
145
+
146
+ # to through block called "flavor"
147
+ # below case for type cast
132
148
  class User2 < Striuct.new
133
149
  member :age, /\A\d+\z/, Numeric do |arg|
134
150
  Integer arg
135
151
  end
136
152
 
137
- member :name, ->v{v.respond_to? :to_str} do |v|
138
- v.to_str.to_sym
153
+ member :name, ->v{v.respond_to? :to_s} do |v|
154
+ v.to_s.to_sym
139
155
  end
140
156
  end
141
157
 
@@ -149,16 +165,13 @@ debug user2
149
165
  user2.age = '10'
150
166
  debug user2
151
167
 
152
- begin
153
- user2.name = 10
154
- rescue
155
- debug $!
156
- end
168
+ user2.name = 10
169
+ debug user2
170
+ user2.name = Class
171
+ debug user2
157
172
 
158
- user2.name = 's'
159
- debug user2.class
173
+ # Default value
160
174
 
161
- # use default value
162
175
  class User3 < Striuct.new
163
176
  member :lank, Fixnum
164
177
  default :lank, 3
@@ -174,41 +187,39 @@ debug user3.assign?(:name)
174
187
  user3.name = nil
175
188
  debug user3.assign?(:name)
176
189
 
177
- # Standard Struct no check member name.
178
- NoGuard = Struct.new :__send__, :'? !'
179
- noguard = NoGuard.new false
180
- debug noguard.__send__
181
- debug noguard.methods.include?(:'? !') # lost!!
190
+ # Alias
182
191
 
183
- # Striuct provides safety levels for naming.
184
- class SafetyNaming < Striuct.new
185
- begin
186
- member :__send__
187
- rescue
188
- debug $!
189
- end
190
-
191
- begin
192
- member :'? !'
193
- rescue
194
- debug $!
195
- end
196
-
197
- # set lower
198
- protect_level :struct
199
-
200
- member :__send__, :'? !'
192
+ class User3
193
+ alias_member :position, :lank
194
+ end
195
+
196
+ debug user3.lank.equal?(user3.position)
197
+ debug user3[:lank].equal?(user3[:position])
198
+ user3[:position] = 4
199
+ debug user3.lank
200
+
201
+ # New Constructors
202
+
203
+ # Subclass.define reject floating object
204
+ # * except if no finished assign each members
205
+ # * return object is frozen
206
+ user3 = User3.define do |r|
207
+ r.lank = 10
208
+ r.name = 'foo'
201
209
  end
202
210
 
211
+ debug user3
212
+
213
+ # Subclass.load_pairs easy make from Hash and like Hash
214
+ user3 = User3[lank:10, name: 'foo']
203
215
 
204
- # and keeping Struct's good interface
205
- Sth1 = Striuct.new :id, :last_name, :family_name, :address, :age
216
+ debug user3
206
217
 
207
- debug Sth1.new
218
+ # 3. Keeping Struct's good interface
208
219
 
209
- Sth2 = Striuct.new do
220
+ Sth1 = Striuct.new do
210
221
  def my_special_method
211
222
  end
212
223
  end
213
224
 
214
- debug Sth2.new.respond_to?(:my_special_method)
225
+ debug Sth1.new.respond_to?(:my_special_method)
@@ -0,0 +1,28 @@
1
+ #/usr/bin/ruby -w
2
+
3
+ require_relative '../lib/striuct'
4
+
5
+ class User < Striuct.new
6
+ member :id, Integer
7
+ member :age, (20..140)
8
+ end
9
+
10
+ user = User.new
11
+
12
+ begin
13
+ user[:id] = 10.0
14
+ rescue
15
+ puts $!.backtrace
16
+ end
17
+
18
+ begin
19
+ user.age = 19
20
+ rescue
21
+ puts $!.backtrace
22
+ end
23
+
24
+ puts '-' * 80
25
+
26
+ $stdout.flush
27
+
28
+ user.age = 19