custom_boolean 0.1.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/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
+