Skipnothing is missing


#1

This is more of a feature request: skipmissing is useful, as would be skipnothing, if it existed. I know it’s easy to filter the nothing values away, but it’s also nice to drop the Union element type, as is achieved with collect(skipmissing(arr)).

I could make a PR for this, but the code would be almost identical to that underlying skipmissing.


ANN: Transducers.jl, efficient and composable algorithms for map- and reduce-like operations
#2

I think the intention is to make missing stand for missing values, which propagate kind of semi-automatically when appropriate, and nothing an indicator of situations that there should be a value but there isn’t one and the caller should take explicit action to deal with the situation.

So I am not sure that skipnothing is that useful. In any case, you have

filter(!isnothing, ...)

which is not much longer.

See https://docs.julialang.org/en/v1/manual/faq/#faq-nothing-1


#3

The main distinction I can see between filtering with filter(!ismissing, ...) and collect(skipmissing(...)) is that the resulting collection no longer has element type Union{Missing, ...}. I do not know of a similarly terse way to drop the Union element type for Nothings, when dropping the nothings in a collection, which is an explicit action to deal with the situation.


#4

Try

[x for x in xs if !isnothing(x)]

#5

isnothing is not a function, but otherwise this seems like a good alternative: [x for x in xs if x != nothing].

Of course, you could do the same to remove missing values from an iterable, and yet skipmissing exists as a convenient utility function. I still don’t see any difference in utility between skipmissing, and a potential skipnothing function. From the documentation, it seems like skipmissing is motivated to ease reducing iterables containing missing values without getting a missing result. The same problem exists when reducing iterables containing nothing values, except that the reduction would most likely error instead of producing a nothing result.

Anyway, this is just a suggestion. I personally have to deal with nothing values far more than I have to deal with missing values, and I’ve often thought that skipnothing would be useful.


#6

Sorry, working on master. See

You could define it as a function then in your own code.


#7

I do have it in my own code. I just think it would be a useful utility for others.

Another difference is that Julia can’t infer that element type of that array comprehension:

julia> a = [1, nothing];
julia> function simple_skipnothing(itr)
       [x for x in itr if x != nothing]
       end
simple_skipnothing (generic function with 1 method)
julia> @code_warntype simple_skipnothing(a)
Variables:
  #self# <optimized out>
  itr::Array{Any,1}
  #5 <optimized out>
  #6 <optimized out>
  isz <optimized out>
  et <optimized out>
  v1 <optimized out>
  st <optimized out>
  #temp#@_9 <optimized out>
  #temp#@_10::Array{_,1} where _

Body:
  begin 
      SSAValue(3) = $(Expr(:new, Base.Iterators.Filter{##6#8,Array{Any,1}}, :($(QuoteNode(#6))), :(itr)))
      SSAValue(4) = $(Expr(:new, Base.Generator{Base.Iterators.Filter{##6#8,Array{Any,1}},##5#7}, :($(QuoteNode(#5))), SSAValue(3)))
      $(Expr(:inbounds, false))
      # meta: location array.jl collect 464
      #temp#@_10::Array{_,1} where _ = $(Expr(:invoke, MethodInstance for grow_to!(::Array{Any,1}, ::Base.Generator{Base.Iterators.Filter{##6#8,Array{Any,1}},##5#7}), :(Base.grow_to!), :($(Expr(:foreigncall, :(:jl_alloc_array_1d), Array{Any,1}, svec(Any, Int64), Array{Any,1}, 0, 0, 0))), SSAValue(4)))
      goto 8 # line 471:
      8: 
      # meta: pop location
      $(Expr(:inbounds, :pop))
      return #temp#@_10::Array{_,1} where _
  end::Array{_,1} where _