Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 529893b

Browse files
committedAug 27, 2014
Add a parametric Nullable{T} type
1 parent 5999f53 commit 529893b

File tree

4 files changed

+313
-4
lines changed

4 files changed

+313
-4
lines changed
 

‎base/exports.jl

+12-4
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ export
6161
MathConst,
6262
Matrix,
6363
MergeSort,
64+
Nullable,
6465
ObjectIdDict,
6566
OrdinalRange,
6667
PollingFileWatcher,
@@ -143,6 +144,7 @@ export
143144
KeyError,
144145
LoadError,
145146
MethodError,
147+
NullException,
146148
ParseError,
147149
ProcessExitedException,
148150
SystemError,
@@ -195,7 +197,7 @@ export
195197
,
196198
!==,
197199
,
198-
,
200+
,
199201
$,
200202
%,
201203
&,
@@ -962,7 +964,7 @@ export
962964
rfft,
963965
xcorr,
964966

965-
# numerical integration
967+
# numerical integration
966968
quadgk,
967969

968970
# iteration
@@ -1008,7 +1010,7 @@ export
10081010
toc,
10091011
toq,
10101012

1011-
#dates
1013+
# dates
10121014
Date,
10131015
DateTime,
10141016
now,
@@ -1226,7 +1228,7 @@ export
12261228
# shared arrays
12271229
sdata,
12281230
indexpids,
1229-
1231+
12301232
# paths and file names
12311233
abspath,
12321234
basename,
@@ -1320,6 +1322,12 @@ export
13201322
unsafe_pointer_to_objref,
13211323
unsafe_store!,
13221324

1325+
# nullable types
1326+
isnull,
1327+
NotNull,
1328+
Null,
1329+
unsafe_get,
1330+
13231331
# Macros
13241332
@__FILE__,
13251333
@b_str,

‎base/nullable.jl

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
immutable Nullable{T}
2+
isnull::Bool
3+
value::T
4+
5+
Nullable() = new(true)
6+
Nullable(value::T) = new(false, value)
7+
end
8+
9+
immutable NullException <: Exception
10+
end
11+
12+
Null{T}(::Type{T}) = Nullable{T}()
13+
14+
NotNull{T}(value::T) = Nullable{T}(value)
15+
16+
function show{T}(io::IO, x::Nullable{T})
17+
if x.isnull
18+
@printf(io, "Null(%s)", repr(T))
19+
else
20+
@printf(io, "NotNull(%s)", repr(x.value))
21+
end
22+
end
23+
24+
get(x::Nullable) = x.isnull ? throw(NullException()) : x.value
25+
26+
get{S, T}(x::Nullable{S}, y::T) = x.isnull ? convert(S, y) : x.value
27+
28+
unsafe_get(x::Nullable) = x.value
29+
30+
isnull(x::Nullable) = x.isnull
31+
32+
function isequal{S, T}(x::Nullable{S}, y::Nullable{T})
33+
if x.isnull && y.isnull
34+
return true
35+
elseif x.isnull || y.isnull
36+
return false
37+
else
38+
return isequal(x.value, y.value)
39+
end
40+
end
41+
42+
=={S, T}(x::Nullable{S}, y::Nullable{T}) = throw(NullException())
43+
44+
function hash(x::Nullable, h::Uint)
45+
if x.isnull
46+
return h + uint(0x932e0143e51d0171)
47+
else
48+
return hash(x.value, h + uint(0x932e0143e51d0171))
49+
end
50+
end

‎base/sysimg.jl

+3
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,9 @@ importall .Profile
271271
include("Dates.jl")
272272
import .Dates: Date, DateTime, now
273273

274+
# nullable types
275+
include("nullable.jl")
276+
274277
function __init__()
275278
# Base library init
276279
reinit_stdio()

‎test/nullable.jl

+248
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
types = [
2+
Bool,
3+
Char,
4+
Float16,
5+
Float32,
6+
Float64,
7+
Int128,
8+
Int16,
9+
Int32,
10+
Int64,
11+
Int8,
12+
Uint16,
13+
Uint32,
14+
Uint64,
15+
Uint8,
16+
]
17+
18+
# Nullable{T}() = new(true)
19+
for T in types
20+
x = Nullable{T}()
21+
@test x.isnull === true
22+
@test isa(x.value, T)
23+
end
24+
25+
# Nullable{T}(value::T) = new(false, value)
26+
for T in types
27+
x = Nullable{T}(zero(T))
28+
@test x.isnull === false
29+
@test isa(x.value, T)
30+
@test x.value === zero(T)
31+
32+
x = Nullable{T}(one(T))
33+
@test x.isnull === false
34+
@test isa(x.value, T)
35+
@test x.value === one(T)
36+
end
37+
38+
# immutable NullException <: Exception
39+
@test isa(NullException(), NullException)
40+
@test_throws NullException throw(NullException())
41+
42+
# Null{T}(::Type{T}) = Nullable{T}()
43+
for T in types
44+
x = Null(T)
45+
@test x.isnull === true
46+
@test isa(x.value, T)
47+
end
48+
49+
# NotNull{T}(value::T) = Nullable{T}(value)
50+
for T in types
51+
v = zero(T)
52+
x = NotNull(v)
53+
@test x.isnull === false
54+
@test isa(x.value, T)
55+
@test x.value === v
56+
57+
v = one(T)
58+
x = NotNull(v)
59+
@test x.isnull === false
60+
@test isa(x.value, T)
61+
@test x.value === v
62+
end
63+
64+
p1s = [
65+
"Null(Bool)",
66+
"Null(Char)",
67+
"Null(Float16)",
68+
"Null(Float32)",
69+
"Null(Float64)",
70+
"Null(Int128)",
71+
"Null(Int16)",
72+
"Null(Int32)",
73+
"Null(Int64)",
74+
"Null(Int8)",
75+
"Null(Uint16)",
76+
"Null(Uint32)",
77+
"Null(Uint64)",
78+
"Null(Uint8)",
79+
]
80+
81+
p2s = [
82+
"NotNull(false)",
83+
"NotNull('\0')",
84+
"NotNull(float16(0.0))",
85+
"NotNull(0.0f0)",
86+
"NotNull(0.0)",
87+
"NotNull(0)",
88+
"NotNull(0)",
89+
"NotNull(0)",
90+
"NotNull(0)",
91+
"NotNull(0)",
92+
"NotNull(0x0000)",
93+
"NotNull(0x00000000)",
94+
"NotNull(0x0000000000000000)",
95+
"NotNull(0x00)",
96+
]
97+
98+
p3s = [
99+
"NotNull(true)",
100+
"NotNull('\x01')",
101+
"NotNull(float16(1.0))",
102+
"NotNull(1.0f0)",
103+
"NotNull(1.0)",
104+
"NotNull(1)",
105+
"NotNull(1)",
106+
"NotNull(1)",
107+
"NotNull(1)",
108+
"NotNull(1)",
109+
"NotNull(0x0001)",
110+
"NotNull(0x00000001)",
111+
"NotNull(0x0000000000000001)",
112+
"NotNull(0x01)",
113+
]
114+
115+
# show{T}(io::IO, x::Nullable{T})
116+
io = IOBuffer()
117+
for (i, T) in enumerate(types)
118+
x1 = Null(T)
119+
x2 = NotNull(zero(T))
120+
x3 = NotNull(one(T))
121+
show(io, x1)
122+
takebuf_string(io) == p1s[i]
123+
show(io, x2)
124+
takebuf_string(io) == p2s[i]
125+
show(io, x3)
126+
takebuf_string(io) == p3s[i]
127+
end
128+
129+
# get(x::Nullable)
130+
for T in types
131+
x1 = Null(T)
132+
x2 = NotNull(zero(T))
133+
x3 = NotNull(one(T))
134+
135+
@test_throws NullException get(x1)
136+
@test get(x2) === zero(T)
137+
@test get(x3) === one(T)
138+
end
139+
140+
# get{S, T}(x::Nullable{S}, y::T)
141+
for T in types
142+
x1 = Null(T)
143+
x2 = NotNull(zero(T))
144+
x3 = NotNull(one(T))
145+
146+
@test get(x1, zero(T)) === zero(T)
147+
@test get(x1, one(T)) === one(T)
148+
@test get(x2, one(T)) === zero(T)
149+
@test get(x3, zero(T)) === one(T)
150+
end
151+
152+
# unsafe_get(x::Nullable)
153+
for T in types
154+
x1 = Null(T)
155+
x2 = NotNull(zero(T))
156+
x3 = NotNull(one(T))
157+
158+
@test isa(unsafe_get(x1), T)
159+
@test isa(unsafe_get(x2), T)
160+
@test isa(unsafe_get(x3), T)
161+
end
162+
163+
# isnull(x::Nullable)
164+
for T in types
165+
x1 = Null(T)
166+
x2 = NotNull(zero(T))
167+
x3 = NotNull(one(T))
168+
169+
@test isnull(x1) === true
170+
@test isnull(x2) === false
171+
@test isnull(x3) === false
172+
end
173+
174+
# function isequal{S, T}(x::Nullable{S}, y::Nullable{T})
175+
for T in types
176+
x1 = Null(T)
177+
x2 = Null(T)
178+
x3 = NotNull(zero(T))
179+
x4 = NotNull(one(T))
180+
181+
@test isequal(x1, x1) === true
182+
@test isequal(x1, x2) === true
183+
@test isequal(x1, x3) === false
184+
@test isequal(x1, x4) === false
185+
186+
@test isequal(x2, x1) === true
187+
@test isequal(x2, x2) === true
188+
@test isequal(x2, x3) === false
189+
@test isequal(x2, x4) === false
190+
191+
@test isequal(x3, x1) === false
192+
@test isequal(x3, x2) === false
193+
@test isequal(x3, x3) === true
194+
@test isequal(x3, x4) === false
195+
196+
@test isequal(x4, x1) === false
197+
@test isequal(x4, x2) === false
198+
@test isequal(x4, x3) === false
199+
@test isequal(x4, x4) === true
200+
end
201+
202+
# function =={S, T}(x::Nullable{S}, y::Nullable{T})
203+
for T in types
204+
x1 = Null(T)
205+
x2 = Null(T)
206+
x3 = NotNull(zero(T))
207+
x4 = NotNull(one(T))
208+
209+
@test_throws NullException (x1 == x1)
210+
@test_throws NullException (x1 == x2)
211+
@test_throws NullException (x1 == x3)
212+
@test_throws NullException (x1 == x4)
213+
214+
@test_throws NullException (x2 == x1)
215+
@test_throws NullException (x2 == x2)
216+
@test_throws NullException (x2 == x3)
217+
@test_throws NullException (x2 == x4)
218+
219+
@test_throws NullException (x3 == x1)
220+
@test_throws NullException (x3 == x2)
221+
@test_throws NullException (x3 == x3)
222+
@test_throws NullException (x3 == x4)
223+
224+
@test_throws NullException (x4 == x1)
225+
@test_throws NullException (x4 == x2)
226+
@test_throws NullException (x4 == x3)
227+
@test_throws NullException (x4 == x4)
228+
end
229+
230+
# function hash(x::Nullable, h::Uint)
231+
for T in types
232+
x1 = Null(T)
233+
x2 = Null(T)
234+
x3 = NotNull(zero(T))
235+
x4 = NotNull(one(T))
236+
237+
@test isa(hash(x1), Uint)
238+
@test isa(hash(x2), Uint)
239+
@test isa(hash(x3), Uint)
240+
@test isa(hash(x4), Uint)
241+
242+
@test hash(x1) == hash(x2)
243+
@test hash(x1) != hash(x3)
244+
@test hash(x1) != hash(x4)
245+
@test hash(x2) != hash(x3)
246+
@test hash(x2) != hash(x4)
247+
@test hash(x3) != hash(x4)
248+
end

0 commit comments

Comments
 (0)
Please sign in to comment.