null 0.1
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.tar.gz.sig +2 -0
- data/lib/null.rb +181 -0
- data/test/null.rb +119 -0
- metadata +89 -0
- metadata.gz.sig +0 -0
data.tar.gz.sig
ADDED
data/lib/null.rb
ADDED
@@ -0,0 +1,181 @@
|
|
1
|
+
class Object
|
2
|
+
# +truthy?+ is +false+ iff we are +nil+, +false+, or an instance of NullClass.
|
3
|
+
def truthy?
|
4
|
+
true
|
5
|
+
end
|
6
|
+
|
7
|
+
# +falsy?+ is +true+ iff we are +nil+, +false+, or an instance of NullClass.
|
8
|
+
def falsy?
|
9
|
+
false
|
10
|
+
end
|
11
|
+
|
12
|
+
# This is an alias for +falsy?+.
|
13
|
+
def !()
|
14
|
+
falsy?
|
15
|
+
end
|
16
|
+
|
17
|
+
# Are we +null+?
|
18
|
+
def null?
|
19
|
+
false
|
20
|
+
end
|
21
|
+
|
22
|
+
# +null.to_nil?+ returns +nil+; everything else returns +self+.
|
23
|
+
def to_nil?()
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
# +obj.tap?()+ is equivalent to +obj.tap()+ unless +obj+ is an instance of
|
28
|
+
# NullClass, in which case a block must still be given, but will not be
|
29
|
+
# executed.
|
30
|
+
def tap? # yield: self
|
31
|
+
yield(self)
|
32
|
+
self
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Make falsy things tell you so.
|
37
|
+
module Falsiness
|
38
|
+
def truthy? # :nodoc:
|
39
|
+
false
|
40
|
+
end
|
41
|
+
|
42
|
+
def falsy? # :nodoc:
|
43
|
+
true
|
44
|
+
end
|
45
|
+
|
46
|
+
def !() # :nodoc:
|
47
|
+
true
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Make boolean logic work with truthiness. Note that this makes these operators
|
52
|
+
# asymmetric in that calling boolean operators on +null+ will return +null+.
|
53
|
+
|
54
|
+
class NilClass
|
55
|
+
include Falsiness
|
56
|
+
def &(obj) false end
|
57
|
+
def |(obj) !!obj end
|
58
|
+
def ^(obj) !!obj end
|
59
|
+
end
|
60
|
+
|
61
|
+
class FalseClass
|
62
|
+
include Falsiness
|
63
|
+
def &(obj) false end
|
64
|
+
def |(obj) !!obj end
|
65
|
+
def ^(obj) !!obj end
|
66
|
+
end
|
67
|
+
|
68
|
+
class TrueClass
|
69
|
+
def &(obj) !!obj end
|
70
|
+
def |(obj) true end
|
71
|
+
def ^(obj) !obj end
|
72
|
+
end
|
73
|
+
|
74
|
+
# An object including us will convert like +nil+.
|
75
|
+
module NillishConversions
|
76
|
+
# +[]+
|
77
|
+
def to_a() [] end
|
78
|
+
alias to_ary to_a
|
79
|
+
|
80
|
+
# +(0+0i)+
|
81
|
+
def to_c() to_i.to_c end
|
82
|
+
|
83
|
+
# +0.0+
|
84
|
+
def to_f() to_i.to_f end
|
85
|
+
|
86
|
+
# +0+
|
87
|
+
def to_i() 0 end
|
88
|
+
|
89
|
+
# +"null"+
|
90
|
+
def to_json() 'null' end
|
91
|
+
|
92
|
+
# +nil+
|
93
|
+
def to_nil?() nil end
|
94
|
+
|
95
|
+
# +nil+
|
96
|
+
def to_param() nil end
|
97
|
+
|
98
|
+
# +(0/1)+
|
99
|
+
def to_r() to_i.to_r end
|
100
|
+
alias rationalize to_r
|
101
|
+
|
102
|
+
# +""+
|
103
|
+
def to_s() '' end
|
104
|
+
alias to_str to_s
|
105
|
+
|
106
|
+
# +nil+
|
107
|
+
def =~(obj) nil end
|
108
|
+
end
|
109
|
+
|
110
|
+
# Define boolean operators based on truthiness.
|
111
|
+
module TruthyBooleanOperators
|
112
|
+
def &(obj) truthy? & obj end
|
113
|
+
def |(obj) truthy? | obj end
|
114
|
+
def ^(obj) truthy? ^ obj end
|
115
|
+
end
|
116
|
+
|
117
|
+
# Define +method_missing+ to return +self+.
|
118
|
+
module RecursiveMethodMissing
|
119
|
+
# We always return +self+.
|
120
|
+
def method_missing(meth, *args)
|
121
|
+
self
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# We implement the Null Object Pattern, i.e. most methods called on us will
|
126
|
+
# return +self+. Also, boolean logical operators for +true+, +false+, and +nil+
|
127
|
+
# have been redefined so that they depend on the +falsy?+
|
128
|
+
class NullClass
|
129
|
+
include Falsiness
|
130
|
+
include TruthyBooleanOperators
|
131
|
+
include RecursiveMethodMissing
|
132
|
+
|
133
|
+
def to_s() nil end # +""+
|
134
|
+
def nil?() true end # :nodoc:
|
135
|
+
def null?() true end # :nodoc:
|
136
|
+
def empty?() true end # :nodoc:
|
137
|
+
def to_nil?() nil end # :nodoc:
|
138
|
+
def inspect() 'null' end # +"null"+
|
139
|
+
def present?() false end # :nodoc:
|
140
|
+
|
141
|
+
# Require a block, but don't use it; then return +self+.
|
142
|
+
def tap? # :nodoc:
|
143
|
+
raise(LocalJumpError, 'no block given') unless block_given?
|
144
|
+
self
|
145
|
+
end
|
146
|
+
|
147
|
+
# Make Numeric operations involving +null+ return +null+.
|
148
|
+
def coerce(x)
|
149
|
+
[null, null]
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# VoidClass instances act like NullClass instances except
|
154
|
+
class VoidClass < NullClass
|
155
|
+
include NillishConversions
|
156
|
+
|
157
|
+
# Become 0 in mathematical operations.
|
158
|
+
def coerce(x) to_i.coerce(x) end
|
159
|
+
def +(x) x end
|
160
|
+
def -(x) -x end
|
161
|
+
def *(x) x*self end
|
162
|
+
def /(x) to_i/x end
|
163
|
+
|
164
|
+
# +"void"+
|
165
|
+
def inspect
|
166
|
+
'void'
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
NULL = NullClass.new
|
171
|
+
# This is an alias for +NULL+, which is an instance of NullObject.
|
172
|
+
def null
|
173
|
+
NULL
|
174
|
+
end
|
175
|
+
|
176
|
+
VOID = VoidClass.new
|
177
|
+
# +void+ is an alias for +VOID+, which is like +null+, except that its +to_*+
|
178
|
+
# methods are like +nil+'s.
|
179
|
+
def void
|
180
|
+
VOID
|
181
|
+
end
|
data/test/null.rb
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require_relative '../lib/null'
|
3
|
+
require 'test/unit'
|
4
|
+
|
5
|
+
class NullTest < Test::Unit::TestCase
|
6
|
+
TRUTHY_TEST_OBJECTS = [1024, 4.20, 4, :twenty, Class.new, Object.new, true,
|
7
|
+
method(:method), Array.new, {}, 0, 0.0]
|
8
|
+
NULL_TEST_OBJECTS = [null, void, NullClass.new, VoidClass.new]
|
9
|
+
|
10
|
+
TRUTHY_BOOLEAN_OBJECTS = [true]
|
11
|
+
GENERATED_FALSIES = [false, nil]
|
12
|
+
RECURSOR_TEST_OBJECTS = []
|
13
|
+
|
14
|
+
[
|
15
|
+
[TruthyBooleanOperators, TRUTHY_BOOLEAN_OBJECTS],
|
16
|
+
[Falsiness, GENERATED_FALSIES],
|
17
|
+
[RecursiveMethodMissing, RECURSOR_TEST_OBJECTS]
|
18
|
+
].each do |mod, array|
|
19
|
+
array << Object.new.extend(mod)
|
20
|
+
end
|
21
|
+
|
22
|
+
ALL_FALSIES = GENERATED_FALSIES + NULL_TEST_OBJECTS
|
23
|
+
NON_NULL = TRUTHY_TEST_OBJECTS + TRUTHY_BOOLEAN_OBJECTS + GENERATED_FALSIES +
|
24
|
+
RECURSOR_TEST_OBJECTS + [false, nil]
|
25
|
+
|
26
|
+
def test_truthiness
|
27
|
+
TRUTHY_TEST_OBJECTS.each do |truthy|
|
28
|
+
msg = "#{truthy} is false"
|
29
|
+
assert truthy.truthy?, msg
|
30
|
+
assert !truthy.falsy?, msg
|
31
|
+
assert !!truthy, msg
|
32
|
+
end
|
33
|
+
|
34
|
+
ALL_FALSIES.each do |falsy|
|
35
|
+
msg = "#{falsy} is false"
|
36
|
+
assert !falsy.truthy?, msg
|
37
|
+
assert falsy.falsy?, msg
|
38
|
+
assert !falsy, msg
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_boolean_logic
|
43
|
+
TRUTHY_BOOLEAN_OBJECTS.product(ALL_FALSIES).each do |truthy, falsy|
|
44
|
+
if truthy.singleton_class.include?(TruthyBooleanOperators)
|
45
|
+
assert_equal(true, truthy ^ falsy, "#{truthy} ^ #{falsy} is true")
|
46
|
+
assert_equal(true, truthy | falsy, "#{truthy} | #{falsy} is false")
|
47
|
+
assert_equal(false, truthy & falsy, "#{truthy} & #{falsy} is false")
|
48
|
+
end
|
49
|
+
|
50
|
+
if falsy.singleton_class.include?(TruthyBooleanOperators)
|
51
|
+
assert_equal(true, falsy ^ truthy, "#{falsy} ^ #{truthy} is true")
|
52
|
+
assert_equal(true, falsy | truthy, "#{falsy} | #{truthy} is true")
|
53
|
+
assert_equal(false, falsy & truthy, "#{falsy} & #{truthy} is false")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_nil_checks
|
59
|
+
assert !nil.null?
|
60
|
+
assert nil.nil?
|
61
|
+
assert_equal nil, nil.to_nil?()
|
62
|
+
|
63
|
+
NON_NULL.each do |truthy|
|
64
|
+
assert !truthy.null?
|
65
|
+
|
66
|
+
tap_ran = false
|
67
|
+
truthy.tap? do |t|
|
68
|
+
tap_ran = true
|
69
|
+
assert_equal(truthy, t)
|
70
|
+
end
|
71
|
+
assert tap_ran
|
72
|
+
|
73
|
+
assert_equal truthy, truthy.to_nil?()
|
74
|
+
end
|
75
|
+
|
76
|
+
NULL_TEST_OBJECTS.each do |nto|
|
77
|
+
assert nto.nil?
|
78
|
+
assert nto.null?
|
79
|
+
nto.tap? { flunk }
|
80
|
+
assert_equal nil, nto.to_nil?()
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_sink
|
85
|
+
NULL_TEST_OBJECTS.each do |nto|
|
86
|
+
%w{ijfdn edfksliwsauli rdwjsnxs vdsjkg_njdc3ese objectifd kill! doom? fcs
|
87
|
+
noki i n self}.each do |func|
|
88
|
+
[[5], [1,2], [], Array.new(50, :o), {a: null}].each do |msg|
|
89
|
+
assert_equal(nto, nto.send(func, *msg))
|
90
|
+
assert_equal(nto, nto.send(func, *msg){flunk})
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
assert_equal null, (5*8+1/1.7)**null
|
96
|
+
assert_equal null, null + 5
|
97
|
+
assert_equal null, null/0
|
98
|
+
assert_equal null, (0 * null) + 5
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_voidness
|
102
|
+
assert_equal 48, (void+8)*6
|
103
|
+
assert_equal 0, void + 0
|
104
|
+
|
105
|
+
{
|
106
|
+
void.to_a => [],
|
107
|
+
void.to_ary => [],
|
108
|
+
Array.new(void) => [],
|
109
|
+
void.to_c => 0,
|
110
|
+
void.to_param => nil,
|
111
|
+
void.to_nil? => nil,
|
112
|
+
(void =~ '') => nil,
|
113
|
+
"#{void}" => '',
|
114
|
+
void.rationalize => Rational(0, 1)
|
115
|
+
}.each do |real, expected|
|
116
|
+
assert_equal(expected, real)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
metadata
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: 'null'
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.1'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- katmagic
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain:
|
12
|
+
- ! '-----BEGIN CERTIFICATE-----
|
13
|
+
|
14
|
+
MIIDQDCCAiigAwIBAgIBADANBgkqhkiG9w0BAQUFADBGMRgwFgYDVQQDDA90aGUu
|
15
|
+
|
16
|
+
bWFnaWNhbC5rYXQxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixk
|
17
|
+
|
18
|
+
ARkWA2NvbTAeFw0xMTA4MjEyMjMyMDFaFw0xMjA4MjAyMjMyMDFaMEYxGDAWBgNV
|
19
|
+
|
20
|
+
BAMMD3RoZS5tYWdpY2FsLmthdDEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYK
|
21
|
+
|
22
|
+
CZImiZPyLGQBGRYDY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
|
23
|
+
|
24
|
+
pBt20nwjs5W03djpRN6FAbpiio286NHMTk6HhmjV6GZKOi5ZUX5onTnKUg2Vc35z
|
25
|
+
|
26
|
+
/nK+aIPReyRfBgIcfSjhoXh1A1Dp+2laNgTtU/3eMupruatgORAPCSaG9Ns+HSyR
|
27
|
+
|
28
|
+
vySbz1QUrwvlvF0qkhhApNQ6dsLl2LMOV3QcluY+Y3CVccOWOSHdQcnAbPuzM9Hf
|
29
|
+
|
30
|
+
4ChI4OGL7+DwLA5OK2S5uewRAa2iLkJSN0WugnQlJqMT59GRaqTDOtnYQpiyKEBy
|
31
|
+
|
32
|
+
QjVPO4LNk7iDsJP22YBrveIzm8/YYRBTU4LTHMEMOyCszrYqD2S1Lwp2rtCJzQCl
|
33
|
+
|
34
|
+
BA0LtBKrZl5mwZm7qyj+TwIDAQABozkwNzAJBgNVHRMEAjAAMB0GA1UdDgQWBBSm
|
35
|
+
|
36
|
+
s5arhjp61kmGl6wsmLYkqerdqDALBgNVHQ8EBAMCBLAwDQYJKoZIhvcNAQEFBQAD
|
37
|
+
|
38
|
+
ggEBAA6cQNQMOPRy4yrj7Nh5Mb9qq8t/8ho/JQvjzVof9qRd+kfKrOoOhXfEO+Rm
|
39
|
+
|
40
|
+
sWcaOnBCVC4DnZuNDSLygVhCDtMnHjg/JsfO/GBF/QlNTJOO1jkoQiS6w0KARlBm
|
41
|
+
|
42
|
+
cpXaWg/oMtXJ2PaUga6WkNeXYf9Mad36P4yuGQScjs+WkUUy7DNZvTGReIcCWOR8
|
43
|
+
|
44
|
+
jteSvvCMobQKGr2DfFOU9Jiddh2FPpz/KOM2ijzwsVNUMUr7R58LoCnQZrZ/YaRW
|
45
|
+
|
46
|
+
ob6QnVgwqu5SUAKQxlFJ/aKlPMj735z8EogaZC1ZHgg3vkgGGyu57N/8BDDG0TzC
|
47
|
+
|
48
|
+
Zn3u2leVae/fJ03zYGArhuJKPgc=
|
49
|
+
|
50
|
+
-----END CERTIFICATE-----
|
51
|
+
|
52
|
+
'
|
53
|
+
date: 2012-02-01 00:00:00.000000000 Z
|
54
|
+
dependencies: []
|
55
|
+
description: null is null.
|
56
|
+
email: the.magical.kat@gmail.com
|
57
|
+
executables: []
|
58
|
+
extensions: []
|
59
|
+
extra_rdoc_files: []
|
60
|
+
files:
|
61
|
+
- lib/null.rb
|
62
|
+
- test/null.rb
|
63
|
+
homepage: https://github.com/katmagic/null
|
64
|
+
licenses: []
|
65
|
+
post_install_message:
|
66
|
+
rdoc_options: []
|
67
|
+
require_paths:
|
68
|
+
- lib
|
69
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
none: false
|
71
|
+
requirements:
|
72
|
+
- - ! '>='
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
77
|
+
requirements:
|
78
|
+
- - ! '>='
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
requirements: []
|
82
|
+
rubyforge_project:
|
83
|
+
rubygems_version: 1.8.10
|
84
|
+
signing_key:
|
85
|
+
specification_version: 3
|
86
|
+
summary: null is a Null Object.
|
87
|
+
test_files:
|
88
|
+
- test/null.rb
|
89
|
+
has_rdoc:
|
metadata.gz.sig
ADDED
Binary file
|