Skip to content
This repository was archived by the owner on May 4, 2019. It is now read-only.

Commit 04588eb

Browse files
authored
Merge pull request #150 from JuliaStats/nl/hasvalue
Prepare for change from isnull to hasvalue field in Base
2 parents e3ad30a + d12fbab commit 04588eb

File tree

9 files changed

+76
-57
lines changed

9 files changed

+76
-57
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ Let `v, w` be two `Nullable{Float64}` objects. If both `v, w` are non-null, the
145145
Arguably, the best way to lift existing methods over `Nullable` arguments is to use multiple dispatch. That is, one can very easily extend `f` to handle `Nullable{Float64}` arguments by simply defining an appropriate method:
146146
```julia
147147
function f(x::Nullable{Float64}, y::Nullable{Float64})
148-
if x.isnull | y.isnull
148+
if isnull(x) | isnull(y)
149149
return Nullable{Float64}()
150150
else
151151
return Nullable(f(x.value, y.value))

perf/reduce.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ D = DataArray(A)
1212
E = DataArray(A, B)
1313

1414
f(x) = 5 * x
15-
f{T<:Number}(x::Nullable{T}) = Nullable(5 * x.value, x.isnull)
15+
f{T<:Number}(x::Nullable{T}) =
16+
ifelse(isnull(x), Nullable{typeof(5 * x.value)}(), Nullable(5 * x.value))
1617

1718
#-----------------------------------------------------------------------------#
1819

src/indexing.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ designated by `I` is present, then it will be returned wrapped in a
1919
# Extract a scalar element from a `NullableArray`.
2020
@inline function Base.getindex{T, N}(X::NullableArray{T, N}, I::Int...)
2121
if isbits(T)
22-
Nullable{T}(X.values[I...], X.isnull[I...])
22+
ifelse(X.isnull[I...], Nullable{T}(), Nullable{T}(X.values[I...]))
2323
else
2424
if X.isnull[I...]
2525
Nullable{T}()

src/nullablevector.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Insert a value at the end of `X` from a `Nullable` value `v`. If `v` is null
1616
then this method adds a null entry at the end of `X`. Returns `X`.
1717
""" ->
1818
function Base.push!{T, V}(X::NullableVector{T}, v::Nullable{V})
19-
if v.isnull
19+
if isnull(v)
2020
resize!(X.values, length(X.values) + 1)
2121
push!(X.isnull, true)
2222
else
@@ -44,7 +44,7 @@ Insert a value at the beginning of `X` from a `Nullable` value `v`. If `v` is
4444
null then this method inserts a null entry at the beginning of `X`. Returns `X`.
4545
""" ->
4646
function Base.unshift!(X::NullableVector, v::Nullable) # -> NullableVector{T}
47-
if v.isnull
47+
if isnull(v)
4848
ccall(:jl_array_grow_beg, Void, (Any, UInt), X.values, 1)
4949
unshift!(X.isnull, true)
5050
else

src/operators.jl

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ importall Base.Operators
44
import Base: promote_op, abs, abs2, sqrt, cbrt, scalarmin, scalarmax, isless
55
using Compat: @functorize
66

7+
if isdefined(Base, :fieldname) && Base.fieldname(Nullable, 1) == :hasvalue # Julia 0.6
8+
_Nullable(R, x, hasvalue::Bool) = Nullable{R}(x, hasvalue)
9+
else
10+
_Nullable(R, x, hasvalue::Bool) = Nullable{R}(x, !hasvalue)
11+
end
12+
713
# Methods adapted from Base Julia 0.5
814
if VERSION < v"0.5.0-dev+5096"
915
promote_op(::Any, T) = T
@@ -67,10 +73,10 @@ for op in (:+, :-, :!, :~, :abs, :abs2, :sqrt, :cbrt)
6773
@inline function $op{S}(x::Nullable{S})
6874
R = promote_op($op, S)
6975
if null_safe_op(@functorize($op), S)
70-
Nullable{R}($op(x.value), x.isnull)
76+
_Nullable(R, $op(x.value), !isnull(x))
7177
else
72-
x.isnull ? Nullable{R}() :
73-
Nullable{R}($op(x.value))
78+
isnull(x) ? Nullable{R}() :
79+
Nullable{R}($op(x.value))
7480
end
7581
end
7682
$op(x::Nullable{Union{}}) = Nullable()
@@ -120,10 +126,10 @@ for op in (:+, :-, :*, :/, :%, :÷, :&, :|, :^, :<<, :>>, :(>>>),
120126
@inline function $op{S,T}(x::Nullable{S}, y::Nullable{T})
121127
R = promote_op(@functorize($op), S, T)
122128
if null_safe_op(@functorize($op), S, T)
123-
Nullable{R}($op(x.value, y.value), x.isnull | y.isnull)
129+
_Nullable(R, $op(x.value, y.value), !(isnull(x) | isnull(y)))
124130
else
125-
(x.isnull | y.isnull) ? Nullable{R}() :
126-
Nullable{R}($op(x.value, y.value))
131+
(isnull(x) | isnull(y)) ? Nullable{R}() :
132+
Nullable{R}($op(x.value, y.value))
127133
end
128134
end
129135
$op(x::Nullable{Union{}}, y::Nullable{Union{}}) = Nullable()
@@ -132,16 +138,16 @@ for op in (:+, :-, :*, :/, :%, :÷, :&, :|, :^, :<<, :>>, :(>>>),
132138
end
133139
end
134140

135-
if !method_exists(isless, (Nullable, Nullable))
141+
if !method_exists(isless, Tuple{Nullable{Int}, Nullable{Int}})
136142
function isless{S,T}(x::Nullable{S}, y::Nullable{T})
137143
# NULL values are sorted last
138144
if null_safe_op(@functorize(isless), S, T)
139-
(!x.isnull & y.isnull) |
140-
(!x.isnull & !y.isnull & isless(x.value, y.value))
145+
(!isnull(x) & isnull(y)) |
146+
(!isnull(x) & !isnull(y) & isless(x.value, y.value))
141147
else
142-
if x.isnull
148+
if isnull(x)
143149
return false
144-
elseif y.isnull
150+
elseif isnull(y)
145151
return true
146152
else
147153
return isless(x.value, y.value)
@@ -150,5 +156,5 @@ if !method_exists(isless, (Nullable, Nullable))
150156
end
151157
isless(x::Nullable{Union{}}, y::Nullable{Union{}}) = false
152158
isless(x::Nullable{Union{}}, y::Nullable) = false
153-
isless(x::Nullable, y::Nullable{Union{}}) = !x.isnull
159+
isless(x::Nullable, y::Nullable{Union{}}) = !isnull(x)
154160
end

src/reduce.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ function Base.mapreduce_impl{T}(f, op::typeof(@functorize(scalarmin)), X::Nullab
190190
i += 1
191191
while i <= last
192192
@inbounds x = f(X[i])
193-
if x.isnull || v.isnull
193+
if isnull(x) | isnull(v)
194194
return Nullable{eltype(x)}()
195195
elseif x.value < v.value
196196
v = x
@@ -207,7 +207,7 @@ function Base.mapreduce_impl{T}(f, op::typeof(@functorize(scalarmax)), X::Nullab
207207
i += 1
208208
while i <= last
209209
@inbounds x = f(X[i])
210-
if x.isnull || v.isnull
210+
if isnull(x) | isnull(v)
211211
return Nullable{eltype(x)}()
212212
elseif x.value > v.value
213213
v = x

test/indexing.jl

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,11 @@ module TestIndexing
3535

3636
# Base.getindex{T, N}(X::NullableArray{T, N}, I::Nullable{Int}...)
3737
@test_throws NullException getindex(X, Nullable{Int}(), Nullable{Int}())
38-
@test isequal(getindex(X, Nullable(1)), Nullable(_values[1], _isnull[1]))
38+
if _isnull[1]
39+
@test isnull(getindex(X, Nullable(1)))
40+
else
41+
@test isequal(getindex(X, Nullable(1)), Nullable(_values[1]))
42+
end
3943

4044
# Scalar getindex
4145
for i = 1:100
@@ -192,7 +196,7 @@ module TestIndexing
192196

193197
if VERSION >= v"0.5.0-dev+4697"
194198
# Base.checkindex(::Type{Bool}, inds::UnitRange, i::Nullable)
195-
@test_throws NullException checkindex(Bool, 1:1, Nullable(1, true))
199+
@test_throws NullException checkindex(Bool, 1:1, Nullable{Int}())
196200
@test checkindex(Bool, 1:10, Nullable(1)) == true
197201
@test isequal(X[Nullable(1)], Nullable(1))
198202

test/operators.jl

Lines changed: 37 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ module TestOperators
1818
Y = NullableArray(B, M)
1919

2020
srand(1)
21+
22+
if isdefined(Base, :fieldname) && Base.fieldname(Nullable, 1) == :hasvalue # Julia 0.6
23+
_Nullable(x, hasvalue::Bool) = Nullable(x, hasvalue)
24+
else
25+
_Nullable(x, hasvalue::Bool) = Nullable(x, !hasvalue)
26+
end
27+
2128
ensure_neg(x::Unsigned) = -convert(Signed, x)
2229
ensure_neg(x::Any) = -abs(x)
2330

@@ -43,7 +50,7 @@ module TestOperators
4350
@test op(Nullable(u0)) === Nullable(op(u0))
4451
@test op(Nullable(u1)) === Nullable(op(u1))
4552
@test op(Nullable(u2)) === Nullable(op(u2))
46-
@test op(Nullable(u0, true)) === Nullable(op(u0), true)
53+
@test op(_Nullable(u0, false)) === _Nullable(op(u0), false)
4754
end
4855

4956
for u in (u0, u1, u2), v in (v0, v1, v2)
@@ -54,17 +61,17 @@ module TestOperators
5461
(T <: AbstractFloat || S <: AbstractFloat) && op in (&, |, >>, <<, >>>) && continue
5562

5663
@test op(Nullable(u), Nullable(v)) === Nullable(op(u, v))
57-
@test op(Nullable(u, true), Nullable(v, true)) === Nullable(op(u, v), true)
58-
@test op(Nullable(u), Nullable(v, true)) === Nullable(op(u, v), true)
59-
@test op(Nullable(u, true), Nullable(v)) === Nullable(op(u, v), true)
64+
@test op(_Nullable(u, false), _Nullable(v, false)) === _Nullable(op(u, v), false)
65+
@test op(Nullable(u), _Nullable(v, false)) === _Nullable(op(u, v), false)
66+
@test op(_Nullable(u, false), Nullable(v)) === _Nullable(op(u, v), false)
6067
end
6168
end
6269
end
6370

6471
@test !Nullable(true) === Nullable(false)
6572
@test !Nullable(false) === Nullable(true)
66-
@test !(Nullable(true, true)) === Nullable(false, true)
67-
@test !(Nullable(false, true)) === Nullable(true, true)
73+
@test !(_Nullable(true, false)) === _Nullable(false, false)
74+
@test !(_Nullable(false, false)) === _Nullable(true, false)
6875
end
6976

7077
# test all types and operators (including null-unsafe ones)
@@ -91,11 +98,11 @@ module TestOperators
9198
@test isa(x, Nullable{R}) && isequal(x, Nullable(op(v1)))
9299
x = op(Nullable(v2))
93100
@test isa(x, Nullable{R}) && isequal(x, Nullable(op(v2)))
94-
x = op(Nullable(v0, true))
101+
x = op(_Nullable(v0, false))
95102
@test isa(x, Nullable{R}) && isnull(x)
96-
x = op(Nullable(v1, true))
103+
x = op(_Nullable(v1, false))
97104
@test isa(x, Nullable{R}) && isnull(x)
98-
x = op(Nullable(v2, true))
105+
x = op(_Nullable(v2, false))
99106
@test isa(x, Nullable{R}) && isnull(x)
100107
x = op(Nullable{R}())
101108
@test isa(x, Nullable{R}) && isnull(x)
@@ -114,11 +121,11 @@ module TestOperators
114121
@test isa(x, Nullable{R}) && isequal(x, Nullable(sqrt(v1)))
115122
x = sqrt(Nullable(abs(v2)))
116123
@test isa(x, Nullable{R}) && isequal(x, Nullable(sqrt(abs(v2))))
117-
x = sqrt(Nullable(v0, true))
124+
x = sqrt(_Nullable(v0, false))
118125
@test isa(x, Nullable{R}) && isnull(x)
119-
x = sqrt(Nullable(ensure_neg(v1), true))
126+
x = sqrt(_Nullable(ensure_neg(v1), false))
120127
@test isa(x, Nullable{R}) && isnull(x)
121-
x = sqrt(Nullable(ensure_neg(v2), true))
128+
x = sqrt(_Nullable(ensure_neg(v2), false))
122129
@test isa(x, Nullable{R}) && isnull(x)
123130
x = sqrt(Nullable{R}())
124131
@test isa(x, Nullable{R}) && isnull(x)
@@ -143,16 +150,16 @@ module TestOperators
143150
@test isequal(op(Nullable(u), Nullable(v)), Nullable(op(u, v)))
144151
end
145152
R = Base.promote_op(op, S, T)
146-
x = op(Nullable(u, true), Nullable(v, true))
153+
x = op(_Nullable(u, false), _Nullable(v, false))
147154
@test isa(x, Nullable{R}) && isnull(x)
148-
x = op(Nullable(u), Nullable(v, true))
155+
x = op(Nullable(u), _Nullable(v, false))
149156
@test isa(x, Nullable{R}) && isnull(x)
150-
x = op(Nullable(u, true), Nullable(v))
157+
x = op(_Nullable(u, false), Nullable(v))
151158
@test isa(x, Nullable{R}) && isnull(x)
152159

153-
x = op(Nullable(u, true), Nullable())
160+
x = op(_Nullable(u, false), Nullable())
154161
@test isa(x, Nullable{S}) && isnull(x)
155-
x = op(Nullable(), Nullable(u, true))
162+
x = op(Nullable(), _Nullable(u, false))
156163
@test isa(x, Nullable{S}) && isnull(x)
157164
x = op(Nullable(), Nullable())
158165
@test isa(x, Nullable{Union{}}) && isnull(x)
@@ -165,16 +172,16 @@ module TestOperators
165172
end
166173
@test isequal(Nullable(u)^Nullable(one(T)+one(T)), Nullable(u^(one(T)+one(T))))
167174
R = Base.promote_op(^, S, T)
168-
x = Nullable(u, true)^Nullable(-abs(v), true)
175+
x = _Nullable(u, false)^_Nullable(-abs(v), false)
169176
@test isnull(x) && eltype(x) === R
170-
x = Nullable(u, false)^Nullable(-abs(v), true)
177+
x = _Nullable(u, true)^_Nullable(-abs(v), false)
171178
@test isnull(x) && eltype(x) === R
172-
x = Nullable(u, true)^Nullable(-abs(v), false)
179+
x = _Nullable(u, false)^_Nullable(-abs(v), true)
173180
@test isnull(x) && eltype(x) === R
174181

175-
x = Nullable(u, true)^Nullable()
182+
x = Nullable(u, false)^Nullable()
176183
@test isa(x, Nullable{S}) && isnull(x)
177-
x = Nullable()^Nullable(u, true)
184+
x = Nullable()^_Nullable(u, false)
178185
@test isa(x, Nullable{S}) && isnull(x)
179186
x = Nullable()^Nullable()
180187
@test isa(x, Nullable{Union{}}) && isnull(x)
@@ -187,16 +194,16 @@ module TestOperators
187194
@test isequal(op(Nullable(u), Nullable(v)), Nullable(op(u, v)))
188195
end
189196
R = Base.promote_op(op, S, T)
190-
x = op(Nullable(u, true), Nullable(v, true))
197+
x = op(_Nullable(u, false), _Nullable(v, false))
191198
@test isnull(x) && eltype(x) === R
192-
x = op(Nullable(u, false), Nullable(v, true))
199+
x = op(_Nullable(u, true), _Nullable(v, false))
193200
@test isnull(x) && eltype(x) === R
194-
x = op(Nullable(u, true), Nullable(v, false))
201+
x = op(_Nullable(u, false), _Nullable(v, true))
195202
@test isnull(x) && eltype(x) === R
196203

197-
x = op(Nullable(u, true), Nullable())
204+
x = op(Nullable(u, false), Nullable())
198205
@test isa(x, Nullable{S}) && isnull(x)
199-
x = op(Nullable(), Nullable(u, true))
206+
x = op(Nullable(), _Nullable(u, false))
200207
@test isa(x, Nullable{S}) && isnull(x)
201208
x = op(Nullable(), Nullable())
202209
@test isa(x, Nullable{Union{}}) && isnull(x)
@@ -205,9 +212,9 @@ module TestOperators
205212
# isless
206213
@test isless(Nullable(u), Nullable(v)) === isless(u, v)
207214

208-
@test isless(Nullable(u), Nullable(v, true)) === true
209-
@test isless(Nullable(u, true), Nullable(v)) === false
210-
@test isless(Nullable(u, true), Nullable(v, true)) === false
215+
@test isless(Nullable(u), _Nullable(v, false)) === true
216+
@test isless(_Nullable(u, false), Nullable(v)) === false
217+
@test isless(_Nullable(u, false), _Nullable(v, false)) === false
211218

212219
@test isless(Nullable(u), Nullable()) === true
213220
@test isless(Nullable(), Nullable(v)) === false

test/reduce.jl

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ module TestReduce
44

55
srand(1)
66
f(x) = 5 * x
7-
f{T<:Number}(x::Nullable{T}) = Nullable(5 * x.value, x.isnull)
7+
f{T<:Number}(x::Nullable{T}) = ifelse(isnull(x), Nullable{typeof(5 * x.value)}(),
8+
Nullable(5 * x.value))
89

910
for N in (10, 2050)
1011
A = rand(N)
@@ -24,13 +25,13 @@ module TestReduce
2425
@test isequal(mapreduce(f, +, Y), Nullable{Float64}())
2526
v = mapreduce(f, +, Y, skipnull=true)
2627
@test_approx_eq v.value mapreduce(f, +, B)
27-
@test !v.isnull
28+
@test !isnull(v)
2829

2930
@test isequal(reduce(+, X), Nullable(reduce(+, X.values)))
3031
@test isequal(reduce(+, Y), Nullable{Float64}())
3132
v = reduce(+, Y, skipnull=true)
3233
@test_approx_eq v.value reduce(+, B)
33-
@test !v.isnull
34+
@test !isnull(v)
3435

3536
for method in (
3637
sum,
@@ -43,11 +44,11 @@ module TestReduce
4344
@test isequal(method(Y), Nullable{Float64}())
4445
v = method(Y, skipnull=true)
4546
@test_approx_eq v.value method(B)
46-
@test !v.isnull
47+
@test !isnull(v)
4748
@test isequal(method(f, Y), Nullable{Float64}())
4849
v = method(f, Y, skipnull=true)
4950
@test_approx_eq v.value method(f, B)
50-
@test !v.isnull
51+
@test !isnull(v)
5152
end
5253

5354
for method in (
@@ -58,7 +59,7 @@ module TestReduce
5859
@test isequal(method(Y), Nullable{Float64}())
5960
v = method(Y, skipnull=true)
6061
@test_approx_eq v.value method(B)
61-
@test v.isnull == false
62+
@test !isnull(v)
6263
end
6364

6465
H = rand(Bool, N)

0 commit comments

Comments
 (0)