custom_boolean 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +129 -2
- data/lib/custom_boolean.rb +36 -36
- data/lib/custom_boolean/version.rb +1 -1
- metadata +5 -2
data/README.markdown
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
Custom Boolean
|
2
2
|
==============
|
3
3
|
|
4
|
-
Cute hack to have if/else_if/else conditions with user-defined
|
4
|
+
Cute hack to have if/else_if/else conditions with user-defined
|
5
|
+
truthiness.
|
6
|
+
|
7
|
+
* Implements various preset truth tests: Ruby, Python, Perl, C, Strict Boolean.
|
8
|
+
* Provides ability to completely customize truthiness.
|
9
|
+
* Provides common Boolean Operators (and, or, not) compatible with CustomBoolean
|
5
10
|
|
6
11
|
Normal conditionals:
|
7
12
|
--------------------
|
@@ -18,7 +23,7 @@ A Pythonic truthiness:
|
|
18
23
|
----------------------
|
19
24
|
|
20
25
|
# redefine truthiness with the `truth_test` method
|
21
|
-
CustomBoolean.truth_test =
|
26
|
+
CustomBoolean.truth_test = CustomBoolean::PYTHON_TRUTH
|
22
27
|
|
23
28
|
if!(0) {
|
24
29
|
puts 'true'
|
@@ -44,3 +49,125 @@ A full example:
|
|
44
49
|
}
|
45
50
|
|
46
51
|
#=> "x is 5"
|
52
|
+
|
53
|
+
|
54
|
+
Nested ifs work fine:
|
55
|
+
-------------------------
|
56
|
+
|
57
|
+
x = :delighted
|
58
|
+
y = :aroused
|
59
|
+
|
60
|
+
if?(x == :sad) {
|
61
|
+
puts 'evaluates to true'
|
62
|
+
}.
|
63
|
+
else_if(x == :delighted) {
|
64
|
+
if?(y == :happy) {
|
65
|
+
puts 'delighted and happy'
|
66
|
+
}.
|
67
|
+
else_if(y == :aroused) {
|
68
|
+
puts 'delighted and aroused'
|
69
|
+
}.
|
70
|
+
else { puts 'just delighted' }
|
71
|
+
}.
|
72
|
+
else {
|
73
|
+
puts 'not delighted'
|
74
|
+
}
|
75
|
+
|
76
|
+
|
77
|
+
If expressions
|
78
|
+
----------------
|
79
|
+
|
80
|
+
# prefixing `if!` with `+` invokes if-expression behaviour
|
81
|
+
+if!(false) {
|
82
|
+
:hello
|
83
|
+
}.
|
84
|
+
else {
|
85
|
+
:goodbye
|
86
|
+
}
|
87
|
+
#=> :goodbye
|
88
|
+
|
89
|
+
Full list of preset CustomBoolean truth tests
|
90
|
+
----------------------------------------------
|
91
|
+
|
92
|
+
CustomBoolean::RUBY_TRUTH # the default
|
93
|
+
CustomBoolean::PYTHON_TRUTH
|
94
|
+
CustomBoolean::PERL_TRUTH
|
95
|
+
CustomBoolean::C_TRUTH
|
96
|
+
CustomBoolean::STRICT_TRUTH # (`true` or `false` only)
|
97
|
+
|
98
|
+
Use as follows:
|
99
|
+
|
100
|
+
CustomBoolean.truth_test = CustomBoolean::C_TRUTH
|
101
|
+
|
102
|
+
+if!(0) {
|
103
|
+
true
|
104
|
+
}.
|
105
|
+
else {
|
106
|
+
false
|
107
|
+
}
|
108
|
+
#=> false
|
109
|
+
|
110
|
+
|
111
|
+
Customizable truthiness
|
112
|
+
-------------------------
|
113
|
+
|
114
|
+
`CustomBoolean.truth_test` can be set to an arbitrary Proc:
|
115
|
+
|
116
|
+
# only :horse is true
|
117
|
+
CustomBoolean.truth_test = proc { |b| b == :horse }
|
118
|
+
|
119
|
+
if!(true) {
|
120
|
+
puts 'evaluates to true'
|
121
|
+
}.
|
122
|
+
else {
|
123
|
+
puts 'reached else'
|
124
|
+
}
|
125
|
+
|
126
|
+
if!(:horse) {
|
127
|
+
puts 'evaluates to true'
|
128
|
+
}.
|
129
|
+
else {
|
130
|
+
puts 'reached else'
|
131
|
+
}
|
132
|
+
|
133
|
+
|
134
|
+
Boolean operators
|
135
|
+
-----------------
|
136
|
+
|
137
|
+
The ordinary `&&` and `||` and `!` operators do not implement
|
138
|
+
CustomBoolean truthiness. Instead use `Object#and`, `Object#or`, and
|
139
|
+
`Object#negate` (or `Object#&` and `Object#|` and `true.&` and `false.|`, etc)
|
140
|
+
|
141
|
+
# use perl truthiness where "0" is false
|
142
|
+
CustomBoolean.truth_test = CustomBoolean::PERL_TRUTH
|
143
|
+
|
144
|
+
+if!(true & "0") {
|
145
|
+
true
|
146
|
+
}.
|
147
|
+
else {
|
148
|
+
false
|
149
|
+
}
|
150
|
+
#=> false
|
151
|
+
|
152
|
+
# Or use Object#and
|
153
|
+
+if!(true.and "0") {...}
|
154
|
+
|
155
|
+
# Use negate (rather than not)
|
156
|
+
+if!(negate("0")) { true } ##=> true
|
157
|
+
|
158
|
+
Testing truthiness of expressions
|
159
|
+
----------------------------------
|
160
|
+
|
161
|
+
You can test the truthiness of an expression without using the
|
162
|
+
full machinery of if!/else_if/else. Just use the
|
163
|
+
`CustomBoolean.truthy?()` function:
|
164
|
+
|
165
|
+
CustomBoolean.truth_test = CustomBoolean::PERL_TRUTH
|
166
|
+
CustomBoolean.truthy?("0") #=> false
|
167
|
+
|
168
|
+
Feedback
|
169
|
+
-----------
|
170
|
+
|
171
|
+
Problems or bugs, file an issue!
|
172
|
+
|
173
|
+
Have fun!
|
data/lib/custom_boolean.rb
CHANGED
@@ -8,13 +8,13 @@ require "#{direc}/custom_boolean/version"
|
|
8
8
|
class CustomBoolean
|
9
9
|
module Operators
|
10
10
|
|
11
|
-
# Equivalent of
|
12
|
-
# Differs from regular
|
11
|
+
# Equivalent of *&&* for CustomBoolean truthiness.
|
12
|
+
# Differs from regular *&&* as it uses CustomBoolean truthiness
|
13
13
|
#
|
14
|
-
#
|
14
|
+
# *NOTE:* It is usually better to use the {#and} alias, as fewer objects override this
|
15
15
|
# method)
|
16
16
|
#
|
17
|
-
# @param The rhs of the boolean *and* operator
|
17
|
+
# @param other The rhs of the boolean *and* operator
|
18
18
|
# @return [Boolean]
|
19
19
|
# @example
|
20
20
|
# obj1 & obj2
|
@@ -24,13 +24,13 @@ class CustomBoolean
|
|
24
24
|
end
|
25
25
|
alias_method :and, :"&"
|
26
26
|
|
27
|
-
# Equivalent of
|
28
|
-
# Differs from regular
|
27
|
+
# Equivalent of *||* for CustomBoolean truthiness.
|
28
|
+
# Differs from regular *||* as it uses CustomBoolean truthiness
|
29
29
|
#
|
30
|
-
#
|
30
|
+
# *NOTE:* It is usually better to use the {#or} alias, as fewer objects override this
|
31
31
|
# method)
|
32
32
|
#
|
33
|
-
# @param The rhs of the boolean *or* operator
|
33
|
+
# @param other The rhs of the boolean *or* operator
|
34
34
|
# @return [Boolean]
|
35
35
|
# @example
|
36
36
|
# obj1 | obj2
|
@@ -47,10 +47,10 @@ true.extend(CustomBoolean::Operators)
|
|
47
47
|
false.extend(CustomBoolean::Operators)
|
48
48
|
Object.send(:include, CustomBoolean::Operators)
|
49
49
|
|
50
|
-
# Equivalent of
|
51
|
-
# Differs from regular
|
50
|
+
# Equivalent of *!* for CustomBoolean truthiness.
|
51
|
+
# Differs from regular *!* as it uses CustomBoolean truthiness
|
52
52
|
#
|
53
|
-
# @param The expression to be negated
|
53
|
+
# @param expr The expression to be negated
|
54
54
|
# @return [Boolean]
|
55
55
|
# @example
|
56
56
|
# negate(obj)
|
@@ -58,20 +58,21 @@ def negate(expr)
|
|
58
58
|
!CustomBoolean.truthy?(expr)
|
59
59
|
end
|
60
60
|
|
61
|
-
# Equivalent of
|
62
|
-
# Differs from regular
|
61
|
+
# Equivalent of *if* for CustomBoolean truthiness.
|
62
|
+
# Differs from regular *if* as it uses CustomBoolean truthiness
|
63
63
|
#
|
64
64
|
# @example basic usage
|
65
|
-
# Use as follows:
|
66
|
-
#
|
65
|
+
# # Use as follows:
|
66
|
+
# if_(condition) { ... }
|
67
67
|
#
|
68
|
-
#
|
68
|
+
# # Other conditionals chain on to the end of if_() as follows:
|
69
|
+
# if_(condition) { ... }
|
70
|
+
# .else { ... }
|
69
71
|
# @example if-expression form
|
70
|
-
# Can turn if_() statement into if-expression by prefixing with a `+`
|
71
|
-
#
|
72
|
+
# # Can turn if_() statement into if-expression by prefixing with a `+`
|
72
73
|
# value = +if_(true) { :hello }
|
73
74
|
# value #=> :hello
|
74
|
-
# @param an expression to evaluate
|
75
|
+
# @param condition an expression to evaluate
|
75
76
|
# @return [CustomBoolean]
|
76
77
|
# @yield the block will be executed if the condition evalues to true
|
77
78
|
def if_(condition, &block)
|
@@ -91,7 +92,7 @@ class CustomBoolean
|
|
91
92
|
attr_accessor :truth_value
|
92
93
|
|
93
94
|
# @return [Object] The value of the block that was executed in the
|
94
|
-
#
|
95
|
+
# if/else_if/else
|
95
96
|
attr_accessor :value
|
96
97
|
|
97
98
|
class << self
|
@@ -105,32 +106,31 @@ class CustomBoolean
|
|
105
106
|
# by CustomBoolean.truth_test.
|
106
107
|
#
|
107
108
|
# Built in Truth tests include:
|
108
|
-
# CustomBoolean::RUBY_TRUTH
|
109
109
|
#
|
110
|
-
# CustomBoolean::
|
110
|
+
# *CustomBoolean::RUBY_TRUTH*
|
111
|
+
#
|
112
|
+
# *CustomBoolean::PYTHON_TRUTH*
|
111
113
|
#
|
112
|
-
# CustomBoolean::PERL_TRUTH
|
114
|
+
# *CustomBoolean::PERL_TRUTH*
|
113
115
|
#
|
114
|
-
# CustomBoolean::C_TRUTH
|
116
|
+
# *CustomBoolean::C_TRUTH*
|
115
117
|
#
|
116
|
-
# CustomBoolean::STRICT_TRUTH
|
118
|
+
# *CustomBoolean::STRICT_TRUTH*
|
117
119
|
#
|
118
120
|
# @example changing truthiness to a preset
|
119
121
|
# CustomBoolean.truth_test = CustomBoolean::PYTHON_TRUTH
|
120
122
|
# @example user-defined truthiness
|
121
123
|
# # only :horse is true:
|
122
124
|
# CustomBoolean.truth_test = proc { |expr| expr == :horse }
|
123
|
-
# @param an expression to evaluate
|
125
|
+
# @param condition an expression to evaluate
|
124
126
|
# @return [Boolean]
|
125
127
|
def truthy?(condition)
|
126
128
|
self.truth_test.call(condition)
|
127
129
|
end
|
128
130
|
end
|
129
131
|
|
130
|
-
# exception raised when conditionals invoked after an else
|
131
132
|
InvalidConditional = Class.new(StandardError)
|
132
133
|
|
133
|
-
# various ideas of truth
|
134
134
|
RUBY_TRUTH = proc { |expr| expr }
|
135
135
|
PYTHON_TRUTH = proc { |expr| expr && !(expr.respond_to?(:empty?) && expr.empty?) && expr != 0 }
|
136
136
|
STRICT_TRUTH = proc { |expr| raise "Expression must be strictly true or false." if expr != true && expr != false; expr }
|
@@ -140,18 +140,20 @@ class CustomBoolean
|
|
140
140
|
# default truth test is Ruby's
|
141
141
|
self.truth_test = RUBY_TRUTH
|
142
142
|
|
143
|
+
# @param [Boolean, Symbol] truth_value
|
144
|
+
# @param block_value
|
143
145
|
def initialize(truth_value, block_value)
|
144
146
|
self.truth_value = truth_value
|
145
147
|
self.value = block_value
|
146
148
|
end
|
147
149
|
|
148
|
-
# Prefixing +if_+ with
|
150
|
+
# Prefixing +if_+ with *+* turns if-statement into if-expression
|
149
151
|
# by invoking #value on CustomBoolean object.
|
150
152
|
# @return [Object] extracts the value of the if, transforming it
|
151
|
-
#
|
153
|
+
# into an if-expression
|
152
154
|
# @example single if-expression example
|
153
155
|
# +if(true) { :hello } #=> :hello
|
154
|
-
# +if(
|
156
|
+
# +if(false) { :hello } #=> nil
|
155
157
|
# @example if-else-expression example
|
156
158
|
# +if(false) {
|
157
159
|
# :hello
|
@@ -176,11 +178,10 @@ class CustomBoolean
|
|
176
178
|
# else_if(cond2) {
|
177
179
|
# :goodbye
|
178
180
|
# }
|
179
|
-
# @param
|
181
|
+
# @param condition an expression to evaluate
|
180
182
|
# @return [CustomBoolean]
|
181
183
|
# @yield the block will be executed if the condition evalues to true
|
182
|
-
#
|
183
|
-
# up the chain)
|
184
|
+
# (so long as no prior *else_if* or *if* has evaluated to true further up the chain)
|
184
185
|
def else_if(condition, &block)
|
185
186
|
raise InvalidConditional, "No further conditionals allowed after an else." if self.truth_value == :else_reached
|
186
187
|
|
@@ -218,8 +219,7 @@ class CustomBoolean
|
|
218
219
|
# }
|
219
220
|
# @return [CustomBoolean]
|
220
221
|
# @yield the block will be executed if the condition evalues to true
|
221
|
-
#
|
222
|
-
# up the chain)
|
222
|
+
# (so long as no prior *else_if* or *if* has evaluated to true further up the chain)
|
223
223
|
def else(&block)
|
224
224
|
raise InvalidConditional, "No further conditionals allowed after an else." if self.truth_value == :else_reached
|
225
225
|
|
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: custom_boolean
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
4
5
|
prerelease: false
|
5
6
|
segments:
|
6
7
|
- 0
|
7
8
|
- 1
|
8
|
-
-
|
9
|
-
version: 0.1.
|
9
|
+
- 3
|
10
|
+
version: 0.1.3
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- John Mair (banisterfiend)
|
@@ -52,6 +53,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
52
53
|
requirements:
|
53
54
|
- - ">="
|
54
55
|
- !ruby/object:Gem::Version
|
56
|
+
hash: 3
|
55
57
|
segments:
|
56
58
|
- 0
|
57
59
|
version: "0"
|
@@ -60,6 +62,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
60
62
|
requirements:
|
61
63
|
- - ">="
|
62
64
|
- !ruby/object:Gem::Version
|
65
|
+
hash: 3
|
63
66
|
segments:
|
64
67
|
- 0
|
65
68
|
version: "0"
|