Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add generic isnull and unsafe_get methods #18484

Merged
merged 1 commit into from
Oct 1, 2016

Conversation

davidagold
Copy link
Contributor

It would be useful to have a generic fallback for isnull when operating on iterators (usually tuples) of both Nullable and non-Nullable objects. Is there anything else we need to do here to make sure this is optimized away in the case of non-Nullable arguments? What should tests look like?

cc: @johnmyleswhite @nalimilan @quinnj

@johnmyleswhite
Copy link
Member

johnmyleswhite commented Sep 13, 2016

I'm not sure how Base wants to handle things, but I would say that the removal of a dead branch in code like the following is what we require:

function loop(x::Vector)
    s = 0.0
    for x_i in x
        if !isnull(x_i)
            s += x_i
        end
    end
    return s
end

code_llvm(loop, (Vector{Float64}, ))

@davidagold
Copy link
Contributor Author

That makes sense. I will leave that assessment to somebody who can read LLVM code.

This PR also seems an appropriate place to introduce an analogous method for the value field of a Nullable:

unwrap(x::Nullable) = x.value
unwrap(x) = x

as in John's jplyr notes.

@johnmyleswhite
Copy link
Member

I think we definitely want something like unwrap, although we might want to call it something like unsafe_get since it is essentially a version of get(x::Nullable) that is unsafe, but extended to work on non-nullables (in a way that ironically ends up being safe).

@nalimilan
Copy link
Member

Regarding unsafe_unwrap, maybe rename get to unwrap by the way?

@kshyatt kshyatt added the missing data Base.missing and related functionality label Sep 13, 2016
@eschnett
Copy link
Contributor

In other contexts (e.g. C++ futures), unwrap is a slightly different operation: It converts Nullable{Nullable{T}} to Nullable{T}, which is always safe. That is, it peels off one layer if there are multiple layers.

@TotalVerb
Copy link
Contributor

LLVM can already eliminate the branch, but inference cannot. See Dead branch elimination after inlining #17880

@davidagold
Copy link
Contributor Author

Should this wait for or become part of #18510 ?

@nalimilan
Copy link
Member

Should this wait for or become part of #18510 ?

The two changes can be made independently, so we can merge any of them we want.

@tkelman tkelman added the needs tests Unit tests are required for this change label Sep 18, 2016
@nalimilan
Copy link
Member

@davidagold Should probably add a test for the new method? Then I vote for merging.

@davidagold
Copy link
Contributor Author

Ready for review.

@tkelman tkelman removed the needs tests Unit tests are required for this change label Sep 28, 2016

@test_throws UndefRefError unsafe_get(Nullable())

# unsafe_get(x)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could as well merge this loop with the one above.

Copy link
Contributor Author

@davidagold davidagold Sep 29, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose? But it doesn't need to be executed multiple times.

EDIT: Oh wait, misread this. Yes, I agree.

@test unsafe_get(x4) === a
end

@test_throws UndefRefError unsafe_get(Nullable())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe also test with another type, e.g. Nullable{String}()?

@@ -61,7 +61,11 @@ end

get(x::Nullable) = x.isnull ? throw(NullException()) : x.value

unsafe_get(x::Nullable) = x.value
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs a docstring.

@@ -174,6 +201,17 @@ end

@test isnull(Nullable())

# isnull(x)
for T in types
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

@davidagold
Copy link
Contributor Author

I've added a docstring for unsafe_get added, modified the isnull docstring, and moved the latter from docs/helpdb/Base.jl to base/nullable.jl. I've also incorporated Milan's suggestions.


Return the value of `x` for `x::Nullable`; return `x` for all other `x`.

Unsafe because does not check whether or not `x` is null before attempting to
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe "This function is unsafe because it does not..."?

@davidagold
Copy link
Contributor Author

@nalimilan How's this?

"""
unsafe_get(x)

Return the value of `x` for [`Nullable`](:obj:`Nullable`) `x`; return `x` for
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just being curious, do we need this to get links?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's my understanding. @kshyatt included these in https://github.com/JuliaLang/julia/pull/18511/files#diff-1955b2684af6e5a407aa36281f8bafdeR94, so I figured I'd include them here, too.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this documented somewhere? Maybe somebody could add a word about this at http://docs.julialang.org/en/latest/manual/documentation/? @MichaelHatherly

(FWIW, the repetition of the object name sounds a bit annoying to me...)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That syntax is being removed in #18588 in favour of [Nullable](@ref), so probably no need to add it to the docs at this point.

so I figured I'd include them here, too.

We can never have too many cross references 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I'll remove the references for now. I think we will all live with the repetition in the docstring.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does the auto conversion script translate them from the current rst-in-markdown hybrid to the new style? if so it won't hurt to add if this gets merged before the conversion

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, handled automatically. It's fine to keep adding xrefs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I will add it back in.

@davidagold davidagold changed the title Add generic isnull method Add generic isnull and unsafe_get methods Sep 29, 2016
Also move isnull docstring out of helpdb and into base/nullable.jl.
@davidagold
Copy link
Contributor Author

I think everything is good here. @nalimilan ?

@nalimilan nalimilan merged commit 35b2583 into JuliaLang:master Oct 1, 2016
@davidagold davidagold deleted the patch-1 branch October 1, 2016 22:22
@tkelman
Copy link
Contributor

tkelman commented Oct 2, 2016

These docstrings need to be added to the manual if this is exported

@tkelman
Copy link
Contributor

tkelman commented Oct 2, 2016

This was also missing a make docs update to the modified docstring. That should be done at the same time, or it will end up in someone else's unrelated PR.

@tkelman tkelman added the needs docs Documentation for this change is required label Oct 2, 2016
"""
isnull(x::Nullable) = x.isnull
isnull(x) = false

isnull(x::Nullable) = !x.hasvalue
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bad rebase

@davidagold
Copy link
Contributor Author

Yeesh, who knew I was such a scrub. I'll fix this and the documentation bit
today.

On Monday, October 3, 2016, Tony Kelman notifications@github.com wrote:

@tkelman commented on this pull request.

In base/nullable.jl
#18484 (review):

+julia> x = Nullable(1, true)
+Nullable{Int64}()
+
+julia> isnull(x)
+true
+
+julia> x = 1
+1
+
+julia> isnull(x)
+false
+```
+"""
+isnull(x::Nullable) = x.isnull
+isnull(x) = false
+
isnull(x::Nullable) = !x.hasvalue

bad rebase


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#18484 (review),
or mute the thread
https://github.com/notifications/unsubscribe-auth/ALUCm5Bkx2EbY7dqHH6AKbyzmRrXpEGsks5qwLA_gaJpZM4J7-CG
.

@davidagold
Copy link
Contributor Author

davidagold commented Oct 4, 2016

@tkelman should I revert this or put those fixes in a new PR?

EDIT: Also, what precisely do you mean by "add docstrings to the manual" ?

@tkelman
Copy link
Contributor

tkelman commented Oct 4, 2016

little cleanup in a new pr is all that's needed, it's not that bad

@tkelman tkelman removed the needs docs Documentation for this change is required label Oct 7, 2016
StefanKarpinski pushed a commit that referenced this pull request Feb 8, 2018
StefanKarpinski pushed a commit that referenced this pull request Feb 8, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
missing data Base.missing and related functionality
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants