custom_boolean 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
@@ -0,0 +1,2 @@
1
+ 27/0/10 version 0.1.0
2
+ * release!
data/README.markdown ADDED
@@ -0,0 +1,46 @@
1
+ Custom Boolean
2
+ ==============
3
+
4
+ Cute hack to have if/else_if/else conditions with user-defined truthiness
5
+
6
+ Normal conditionals:
7
+ --------------------
8
+ if!(0) {
9
+ puts 'true'
10
+ }.
11
+ else {
12
+ puts 'false'
13
+ }
14
+
15
+ #=> 'true'
16
+
17
+ A Pythonic truthiness:
18
+ ----------------------
19
+
20
+ # redefine truthiness with the `truth_test` method
21
+ CustomBoolean.truth_test = proc { |b| b && b != 0 && b != [] }
22
+
23
+ if!(0) {
24
+ puts 'true'
25
+ }.
26
+ else {
27
+ puts 'false'
28
+ }
29
+
30
+ #=> false
31
+
32
+ A full example:
33
+ ------------------------
34
+
35
+ x = 5
36
+ if!(x == 4) {
37
+ puts 'x is 4'
38
+ }.
39
+ else_if(x == 5) {
40
+ puts 'x is 5'
41
+ }.
42
+ else {
43
+ puts 'x is neither 4 nor 5'
44
+ }
45
+
46
+ #=> "x is 5"
data/Rakefile ADDED
@@ -0,0 +1,27 @@
1
+ require 'rake/gempackagetask'
2
+ require './lib/custom_boolean/version'
3
+
4
+ $dlext = Config::CONFIG['DLEXT']
5
+
6
+ specification = Gem::Specification.new do |s|
7
+ s.name = "custom_boolean"
8
+ s.summary = "Handrolled if/else expressions with customizable truthiness"
9
+ s.version = CustomBoolean::VERSION
10
+ s.date = Time.now.strftime '%Y-%m-%d'
11
+ s.author = "John Mair (banisterfiend)"
12
+ s.email = 'jrmair@gmail.com'
13
+ s.description = s.summary
14
+ s.require_path = 'lib'
15
+ s.platform = Gem::Platform::RUBY
16
+ s.homepage = "http://banisterfiend.wordpress.com"
17
+ s.has_rdoc = false
18
+ s.files = ["Rakefile", "README.markdown", "CHANGELOG",
19
+ "lib/custom_boolean.rb", "lib/custom_boolean/version.rb"] +
20
+ FileList["examples/*.rb", "test/*.rb"].to_a
21
+ end
22
+
23
+ Rake::GemPackageTask.new(specification) do |package|
24
+ package.need_zip = false
25
+ package.need_tar = false
26
+ end
27
+
@@ -0,0 +1,18 @@
1
+ require './lib/custom_boolean'
2
+
3
+ x = 7
4
+ if!(x == 4) {
5
+ puts 'x is 4'
6
+ }.
7
+ else_if(x == 5) {
8
+ puts "x is #{x} (first else_if)"
9
+ }.
10
+ else_if(x == 7) {
11
+ puts "x is #{x} (second else_if)"
12
+ }.
13
+ else_if(x == 10) {
14
+ puts 'x is #{x} (third else_if)'
15
+ }.
16
+ else {
17
+ puts 'reached else'
18
+ }
@@ -0,0 +1,3 @@
1
+ class CustomBoolean
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,102 @@
1
+ # CustomBoolean by John Mair (banisterfiend)
2
+ # MIT license
3
+
4
+ module CustomBooleanOperators
5
+ def &(other)
6
+ CustomBoolean.truthy?(self) && CustomBoolean.truthy?(other)
7
+ end
8
+ alias and &
9
+
10
+ def |(other)
11
+ CustomBoolean.truthy?(self) || CustomBoolean.truthy?(other)
12
+ end
13
+ alias or |
14
+ end
15
+
16
+ true.extend(CustomBooleanOperators)
17
+ false.extend(CustomBooleanOperators)
18
+ Object.send(:include, CustomBooleanOperators)
19
+
20
+ def negate(other)
21
+ !CustomBoolean.truthy?(self)
22
+ end
23
+
24
+ def if_(condition, &block)
25
+ truth = !!CustomBoolean.truthy?(condition)
26
+ bvalue = block.call if truth
27
+ CustomBoolean.new(truth, bvalue)
28
+ end
29
+
30
+ # bunch of aliases for if_
31
+ alias if! if_
32
+ alias _if if_
33
+ alias if? if_
34
+
35
+ class CustomBoolean
36
+ attr_accessor :truth_value, :value
37
+
38
+ class << self
39
+ attr_accessor :truth_test
40
+
41
+ def truthy?(condition)
42
+ self.truth_test.call(condition)
43
+ end
44
+ end
45
+
46
+ # exception raised when conditionals invoked after an else
47
+ InvalidConditional = Class.new(StandardError)
48
+
49
+ # various ideas of truth
50
+ RUBY_TRUTH = proc { |expr| expr }
51
+ PYTHON_TRUTH = proc { |expr| expr && !(expr.respond_to?(:empty?) && expr.empty?) && expr != 0 }
52
+ STRICT_TRUTH = proc { |expr| raise "Expression must be strictly true or false." if expr != true && expr != false; expr }
53
+ PERL_TRUTH = proc { |expr| expr && expr != 0 && expr != "" && expr != "0" }
54
+ C_TRUTH = proc { |expr| expr && expr != 0 }
55
+
56
+ # default truth test is Ruby's
57
+ self.truth_test = RUBY_TRUTH
58
+
59
+ def initialize(truth_value, block_value)
60
+ self.truth_value = truth_value
61
+ self.value = block_value
62
+ end
63
+
64
+ def +@
65
+ self.value
66
+ end
67
+
68
+ def else_if(condition, &block)
69
+ raise InvalidConditional, "No further conditionals allowed after an else." if self.truth_value == :else_reached
70
+
71
+ if self.truth_value
72
+ CustomBoolean.new(true, self.value)
73
+ else
74
+ truth = !!CustomBoolean.truthy?(condition)
75
+ bvalue = block.call if truth
76
+ CustomBoolean.new(truth, bvalue)
77
+ end
78
+ end
79
+
80
+ # a bunch of aliases for else_if
81
+ alias else_if? else_if
82
+ alias else_if! else_if
83
+ alias elsif else_if
84
+ alias elsif? else_if
85
+ alias elsif! else_if
86
+
87
+ def else(&block)
88
+ raise InvalidConditional, "No further conditionals allowed after an else." if self.truth_value == :else_reached
89
+
90
+ if self.truth_value
91
+ CustomBoolean.new(:else_reached, self.value)
92
+ else
93
+ bvalue = block.call
94
+ CustomBoolean.new(:else_reached, bvalue)
95
+ end
96
+ end
97
+
98
+ # a bunch of aliases for else
99
+ alias else? else
100
+ alias else! else
101
+ end
102
+
data/test/test.rb ADDED
@@ -0,0 +1,324 @@
1
+
2
+ require '../lib/custom_boolean'
3
+ require 'test/unit'
4
+
5
+ class CustomBooleanTest < Test::Unit::TestCase
6
+ def test_if_true
7
+ result = if?(5 == 5) { :is_equal }
8
+
9
+ assert_equal(true, result.truth_value)
10
+ end
11
+
12
+ def test_if_false
13
+ result = if?(5 == 6) { :is_equal }
14
+
15
+ assert_equal(false, result.truth_value)
16
+ end
17
+
18
+ def test_else_if_true
19
+ result = (if?(5 == 5) { :is_equal }.
20
+ else_if?(6 == 6) { :is_equal })
21
+
22
+ assert_equal(true, result.truth_value)
23
+ end
24
+
25
+ def test_else_if_false
26
+ result = (if?(5 == 6) { :is_equal }.
27
+ else_if?(6 == 7) { :is_equal })
28
+
29
+ assert_equal(false, result.truth_value)
30
+ end
31
+
32
+ def test_else_true
33
+ result = (if?(5 == 5) { :is_equal }.
34
+ else? { :is_equal })
35
+
36
+ assert_equal(:is_equal, result.value)
37
+ assert_equal(:else_reached, result.truth_value)
38
+ end
39
+
40
+ def test_else_false
41
+ result = (if?(5 == 6) { :is_equal }.
42
+ else? { :is_equal })
43
+
44
+ assert_equal(:is_equal, result.value)
45
+ end
46
+
47
+ def test_else_if_else_false
48
+ result = if?(5 == 6) { :is_equal }.
49
+ else_if?(5 == 7) { :is_equal }.
50
+ else? { :is_equal }
51
+
52
+ assert_equal(:is_equal, result.value)
53
+ assert_equal(:else_reached, result.truth_value)
54
+ end
55
+
56
+ def test_else_if_true
57
+ result = if?(5 == 5) { :is_equal_if }.
58
+ else_if?(5 == 7) { :is_equal_else_if }.
59
+ else? { :is_equal }
60
+
61
+ assert_equal(:is_equal_if, result.value)
62
+ end
63
+
64
+ def test_else
65
+ result = if?(5 == 0) { :is_equal }.
66
+ else? { :in_else }
67
+
68
+ assert_equal(:in_else, result.value)
69
+
70
+ result = if?(5 == 5) { :is_equal }.
71
+ else? { :in_else }
72
+
73
+ assert_equal(:else_reached, result.truth_value)
74
+ end
75
+
76
+ def test_custom_truth
77
+ CustomBoolean.truth_test = proc { |b| b && b != 0 }
78
+
79
+ result = if?(0) { :is_equal }
80
+
81
+ assert_equal(false, result.truth_value)
82
+
83
+ # reset truth test
84
+ CustomBoolean.truth_test = CustomBoolean::RUBY_TRUTH
85
+ end
86
+
87
+ def test_custom_truth_else
88
+ CustomBoolean.truth_test = proc { |b| b && b != 0 }
89
+
90
+ result = if?(0) { :is_equal }.
91
+ else? { :in_else }
92
+
93
+ assert_equal(:in_else, result.value)
94
+
95
+ # reset truth test
96
+ CustomBoolean.truth_test = CustomBoolean::RUBY_TRUTH
97
+ end
98
+
99
+ def test_nested_if
100
+ CustomBoolean.truth_test = proc { |b| b && b != 0 }
101
+
102
+ y = :blah
103
+ result = if?(1) {
104
+ if?(0) { }.
105
+ else_if?(1) {
106
+ y = :nested
107
+ }
108
+
109
+ }.
110
+ else_if?(1) {
111
+ y = :else_if
112
+ }
113
+
114
+ assert_equal(:nested, y)
115
+
116
+ CustomBoolean.truth_test = CustomBoolean::RUBY_TRUTH
117
+ end
118
+
119
+ def test_values
120
+ val = :outside_if
121
+ val = if?(true) {
122
+ :in_if
123
+ }
124
+ assert_equal(:in_if, val.value)
125
+
126
+ val = if?(true) {
127
+ :in_if
128
+ }.
129
+ else_if?(true) {
130
+ :in_
131
+ }
132
+
133
+ assert_equal(:in_if, val.value)
134
+ end
135
+
136
+ def test_values_else_if_chain
137
+ val = if?(true) {
138
+ :hello
139
+ }.
140
+ elsif?(true) {
141
+ }.
142
+ else_if?(true) {
143
+ }
144
+
145
+ assert_equal(:hello, val.value)
146
+
147
+ val = if?(false) {
148
+ }.
149
+ elsif?(true) {
150
+ :goodbye
151
+ }.
152
+ else_if?(true) {
153
+ }
154
+
155
+ assert_equal(:goodbye, val.value)
156
+
157
+ val = if?(false) {
158
+ }.
159
+ elsif?(false) {
160
+ }.
161
+ else_if?(true) {
162
+ :tiger
163
+ }
164
+
165
+ assert_equal(:tiger, val.value)
166
+ end
167
+
168
+ def test_conditional_after_else_exception
169
+
170
+ assert_raises(CustomBoolean::InvalidConditional) do
171
+ if?(true) {}.
172
+ else? {}.
173
+ else? {}
174
+ end
175
+
176
+ assert_raises(CustomBoolean::InvalidConditional) do
177
+ if?(false) {}.
178
+ else_if?(true) {}.
179
+ else? {}.
180
+ else_if?(false) {}
181
+ end
182
+ end
183
+
184
+ def test_else_if_aliases
185
+ assert_nothing_thrown do
186
+ if?(false) {}.
187
+ else_if(false) {}.
188
+ else_if!(false) {}.
189
+ else_if?(false) {}.
190
+ elsif?(true) {}.
191
+ elsif!(true) {}.
192
+ elsif(true) {}.
193
+ else {}
194
+ end
195
+ end
196
+
197
+ def test_perl_truth
198
+ CustomBoolean.truth_test = CustomBoolean::PERL_TRUTH
199
+
200
+ ["0", "", 0].each do |v|
201
+ val = if?(v) {
202
+ true
203
+ }.
204
+ else? {
205
+ false
206
+ }
207
+ assert_equal(false, val.value)
208
+ end
209
+
210
+ val = if?("hello") {
211
+ true
212
+ }.
213
+ else? {
214
+ false
215
+ }
216
+ assert_equal(true, val.value)
217
+
218
+ CustomBoolean.truth_test = CustomBoolean::RUBY_TRUTH
219
+ end
220
+
221
+ def test_python_truth
222
+ CustomBoolean.truth_test = CustomBoolean::PYTHON_TRUTH
223
+
224
+ [{}, [], "", 0].each do |v|
225
+ val = if?(v) {
226
+ true
227
+ }.
228
+ else? {
229
+ false
230
+ }
231
+ assert_equal(false, val.value)
232
+ end
233
+
234
+ val = if?("hello") {
235
+ true
236
+ }.
237
+ else? {
238
+ false
239
+ }
240
+ assert_equal(true, val.value)
241
+
242
+ CustomBoolean.truth_test = CustomBoolean::RUBY_TRUTH
243
+ end
244
+
245
+ def test_strict_truth
246
+ CustomBoolean.truth_test = CustomBoolean::STRICT_TRUTH
247
+
248
+ assert_nothing_thrown do
249
+ val = if?(true) {
250
+ true
251
+ }.
252
+ else? {
253
+ false
254
+ }
255
+
256
+ assert_equal(true, val.value)
257
+
258
+ val = if?(false) {
259
+ true
260
+ }.
261
+ else? {
262
+ false
263
+ }
264
+
265
+ assert_equal(false, val.value)
266
+ end
267
+
268
+ [nil, 0, "", "hello", [], {}].each do |v|
269
+ assert_raises(RuntimeError) do
270
+ if?(v) {}
271
+ end
272
+ end
273
+ CustomBoolean.truth_test = CustomBoolean::RUBY_TRUTH
274
+ end
275
+
276
+ def test_c_truth
277
+ CustomBoolean.truth_test = CustomBoolean::C_TRUTH
278
+
279
+ [nil, false, 0].each do |v|
280
+ val = if?(v) {
281
+ true
282
+ }.
283
+ else? {
284
+ false
285
+ }
286
+ assert_equal(false, val.value)
287
+ end
288
+
289
+ [true, "hello", []].each do |v|
290
+ val = if?(v) {
291
+ true
292
+ }.
293
+ else? {
294
+ false
295
+ }
296
+ assert_equal(true, val.value)
297
+ end
298
+ end
299
+
300
+ def test_ruby_truth
301
+ [nil, false].each do |v|
302
+ val = if?(v) {
303
+ true
304
+ }.
305
+ else? {
306
+ false
307
+ }
308
+ assert_equal(false, val.value)
309
+ end
310
+
311
+ [true, "hello", []].each do |v|
312
+ val = if?(v) {
313
+ true
314
+ }.
315
+ else? {
316
+ false
317
+ }
318
+ assert_equal(true, val.value)
319
+ end
320
+ CustomBoolean.truth_test = CustomBoolean::RUBY_TRUTH
321
+ end
322
+ end
323
+
324
+
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: custom_boolean
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - John Mair (banisterfiend)
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-09-27 00:00:00 +13:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: Handrolled if/else expressions with customizable truthiness
23
+ email: jrmair@gmail.com
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - Rakefile
32
+ - README.markdown
33
+ - CHANGELOG
34
+ - lib/custom_boolean.rb
35
+ - lib/custom_boolean/version.rb
36
+ - examples/example.rb
37
+ - test/test.rb
38
+ has_rdoc: true
39
+ homepage: http://banisterfiend.wordpress.com
40
+ licenses: []
41
+
42
+ post_install_message:
43
+ rdoc_options: []
44
+
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ none: false
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ hash: 3
53
+ segments:
54
+ - 0
55
+ version: "0"
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 3
62
+ segments:
63
+ - 0
64
+ version: "0"
65
+ requirements: []
66
+
67
+ rubyforge_project:
68
+ rubygems_version: 1.3.7
69
+ signing_key:
70
+ specification_version: 3
71
+ summary: Handrolled if/else expressions with customizable truthiness
72
+ test_files: []
73
+