custom_boolean 0.1.2 → 0.1.3
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.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"
|