striuct 0.0.11.1 → 0.1.7

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.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