Le mardi 06 janvier 2015 à 05:27 -0800, ele...@gmail.com a écrit :
> 
> 
> On Tuesday, January 6, 2015 10:43:16 PM UTC+10, Milan Bouchet-Valat wrote:
>         Le mardi 06 janvier 2015 à 04:38 -0800, ele...@gmail.com a écrit : 
>         > 
>         > 
>         > On Tuesday, January 6, 2015 7:38:00 PM UTC+10, Milan Bouchet-Valat 
>         > wrote: 
>         >         Le lundi 05 janvier 2015 à 19:16 -0800, ele...@gmail.com a 
> écrit : 
>         >         > My reasoning for Nullable{T} is that it is type stable.  
> Taking your 
>         >         > example, None and Int would be different type objects, 
> introducing a 
>         >         > type instability and potential performance penalty.  But 
> Nullable{T} 
>         >         > is always type Nullable{T} and get(Nullable{T}) is always 
> type T. 
>         >         >  Allowing Nullable{T} to decay into T would re-introduce 
> the type 
>         >         > instability. 
>         >         Right. But that doesn't mean `Nullable(3) == 3` shouldn't 
> return `true`. 
>         >         This operation could be allowed, provided that 
> `Nullable{Int}() == 3` 
>         >         raised a `NullException` or returned `Nullable{Bool}()`. 
>         > 
>         > 
>         > Yeah, (==){T}(a::Nullable{T}, b::T) should be able to be defined as 
>         > !isnull(a) && get(a) == b 
>         I'd consider this definition (which is different from the ones I 
>         suggested above) as unsafe: if `a` is `null`, then you silently get 
>         `false`. Better provide additional safety by either returning a 
>         `Nullable`, or raising an exception. 
>         
> 
> 
> If the Nullable does not have a value then it doesn't equal any value
> of the type, so the correct answer is false.  If it returns bool or
> some sort of Nullable than again its type unstable and also can't be
> directly used in an if.  A user who cares about the null case can
> always check isnull() themselves directly on the original object.
We're hitting the debate about what John calls [1] ontological
missingness vs. epistemological missingness. You appear to assume that
if a `Nullable` is `null`, then it has no value (ontological
missingness). But another conception (which is more common in
statistics) is that the value exists somewhere, but we don't know it
(epistemological missingness).

In the former situation, you indeed know that `(null != 3) == true`. In
the latter, you have to propagate the uncertainty by saying `(null != 3)
== null`.

> And throwing exceptions is expensive and prevents the test being used
> in high performance code.  In fact I would consider it rather nasty if
> something like an equality test could throw.  That means the ==
> function can't be used in any code that is a callback from C if there
> is any possibility of one of its parameters being a nullable.
>
> Thats not to say that a user can't define their *own* version with
> either of these characteristics if it suits their use-case, but any
> general case should prefer the type stable high performance usage.
My two proposals higher in the thread are type-stable. And I don't think
raising an exception hurts performance (even `getindex` does it), and
while it can be a problem with C callbacks, that's already the case of
all functions that raise exceptions (including `get(::Nullable)` itself
-- thus any code working with `Nullable` may raise exceptions if not
written carefully).

That said, I agree that always returning a `Nullable{Bool}` may not be
very practical in most contexts, even though it's consistent. The
solutions of throwing an exception or returning `false` are certainly
more practical. But that decision should be taken with regard to the
broader scope of how applying functions to `Nullable` works (discussion
at https://github.com/JuliaLang/julia/pull/9446 )


Regards


1:
https://github.com/JuliaCon/presentations/tree/master/RepresentingData

> Cheers
> Lex
>  
> 
> 
>         > 
>         > Cheers 
>         > Lex 
>         >   
>         >         
>         >         Regarding the original question: 
>         >         > On Tuesday, January 6, 2015 12:03:24 PM UTC+10,
>         Seth wrote: 
>         >         >         I'm trying to figure out how (and under
>         what circumstances) 
>         >         >         one would use Nullable. That is, it seems
>         that it might be 
>         >         >         valuable when you don't know whether the
>         value/object exists 
>         >         >         (sort of like Python's None, I guess), but
>         then something like 
>         >         >         "Nullable(3) == 3" returns false, and that
>         sort of messes up 
>         >         >         how I'm thinking about it. 
>         >         >         
>         >         >         
>         >         >         The code I'd imagine would be useful would
>         be something like 
>         >         >         
>         >         >         
>         >         >         function foo(x::Int, y=Nullable{Int}())  #
>         that is, y defaults 
>         >         >         to python's "None" but is restricted to
>         Int 
>         >         >             if !isnull(y) 
>         >         >                 return x+y  # x + get(y) works,
>         but why must we invoke 
>         >         >         another method to get the value? 
>         >         >             else 
>         >         >                 return 2x 
>         >         >             end 
>         >         >         end 
>         >         >         
>         >         >         
>         >         >         I'm left wondering why it wasn't
>         reasonable to allow y to 
>         >         >         return get(y) if not null, else raise a
>         NullException, 
>         >         The question is how you define "return". In the
>         strict sense, if you 
>         >         write `return y`, then `y` must be returned, not
>         `get(y)`, or the Julia 
>         >         language would really be a mess. 
>         >         
>         >         That said, with return type declarations, if
>         `foo()::Int` allowed 
>         >         stating that `foo()` always returns an `Int`, then
>         `y` could 
>         >         automatically be converted to an `Int`, raising an
>         exception if it's 
>         >         `null`. But that merely allows you to type `return
>         y` instead of 
>         >         `return get(y)`, so not a big deal. 
>         >         
>         >         Finally, there's the question of whether `x + y`
>         should be allowed to 
>         >         mean `x + get(y)`. That's debatable, but I think a
>         more useful behavior 
>         >         would be to make it equivalent to 
>         >         `isnull(y) ? Nullable(x + get(y)) :
>         Nullable{Int}()`. That would allow 
>         >         handling the possibility of missingness only when
>         you actually want to 
>         >         get an `Int` from a `Nullable{Int}`. 
>         >         
>         >         This has been discussed more generally for any
>         function call at 
>         >         https://github.com/JuliaLang/julia/pull/9446 
>         >         
>         >         >         and the conclusion I'm coming to is that I
>         don't understand 
>         >         >         the concept of Nullable yet. Any
>         pointers? 
>         >         >         
>         >         
>         >         Regards 
>         

Reply via email to