The `list.remove` function takes a reference and throws when empty (it's the 
new standard module), but anyway, the example was more or less a simplified 
version of actual code being used (there is some additional logic that must be 
performed after obtaining the recycled node and so we cannot return 
immediately).

Thank you for informing me that the `!` operator does away with the nil-able 
type, but is it possible to elide the nil-check here? This is additional 
overhead that can still be avoided in the recycle list example. If an 
additional branch is added to a critical path when it can be avoided, it can 
end up being very undesirable.

Get Outlook for Android<https://aka.ms/ghei36>

________________________________
From: Brad Chamberlain <[email protected]>
Sent: Saturday, August 24, 2019 1:07:46 AM
To: Louis Jenkins <[email protected]>
Cc: Chapel Users Mailing List <[email protected]>; Chapel 
Sourceforge Developers List <[email protected]>; Chapel 
Educators Mailing List <[email protected]>
Subject: Re: [Chapel-developers] Chapel 1.20: Offer to help with nilability 
changes


Hi Louis —

I think there are a few options here (and probably others that the experts
could suggest... in this case, I'm mostly a messenger who's just trying
these features out for the first time today as well, so still picking up
some tricks as I go).

First an assumption: I take it that `recycleList.remove(n)` is going to
store the thing that's removed in `n`?  (i.e., `n = recycleList.remove();`
might be another way to express it showing the assignment?)

The first way to write this pattern that occurs to me is as follows, where
I'm going to take the above liberty with reframing the recycleList API:

proc recycle(): unmanaged object {
   try {
     return recycleList.remove();
   } catch exception {
     return new unmanaged object();
   }
}

Here, both branches return a non-nilable unmanaged object (assuming
remove() does when it doesn't throw), so things are fine.

Another way would be to use the '!' operator (and here I'll revert to the
original API to avoid cheating):

proc recycle(): unmanaged object {
   var n: unmanaged object?;  // this needs to use ? since n will
                              // initially be nil
   try {
     recycleList.remove(n);
   } catch exception {
     n = new unmanaged object();
   }
   return n!;  // will halt if 'n' is nil, but you've assured me it won't
}

Note, however, that if the try block throws an exception that doesn't
match your exception pattern, 'n' will be 'nil' and the ! operator will
fail.

I think a third approach would be to cast 'n' to 'unmanaged object', but
I'm not as expert at that approach yet (casting nilability away throws
when the value is 'nil' whereas '!' halts).


To your larger point, though, I think you're correct that nilability can't
be proven correct by a compiler in all cases (I suspect its equivalent to
the halting problem), so we do what compilers typically do:  Be
conservative when we can't be sure and rely on the user to help out in
such cases.

That said, note that checking nilability in Chapel is more about making
sure that you don't assign a `nil` or a `C?` to a `C` without first doing
something to convert it safely (like the '!' operator or a cast).  And
less about trying to infer whether something is assigned non-nil values
along all paths or not.

-Brad


On Sat, 24 Aug 2019, Louis Jenkins wrote:

> **Memory/Object Pool Pattern**
>
> If I know for a fact that a function will always return an object that
> is not nil, such as the case of an object pool that will create a new
> object if an object cannot be recycled, how do you represent this with
> the new changes? It seems that the compiler cannot be determine if the
> nil-ability of an object can be proven statically, such as the case in
> the below code snippet; the compiler _could_ see that, in any and all
> paths, it is impossible for `n` to be `nil`, and is therefore not
> nil-able; a lot of static analyzers are capable of performing such
> analysis as well. Would this be considered something 'impossible' to do
> from a design standpoint, or would this be something that is planned to
> be supported? If not, how do you prevent nil-ability tainting
> everything? Is it planned to be able to say to the compiler: "I know
> that this is not nil-able after this point, please stop interfering with
> my code?" - I kid, I kid, but really, is there a way to tell it that
> something is non-nilable after a point?
>
> """
> use List;
>
> var recycleList : list(unmanaged object);
> proc recycle() : unmanaged object {
>    var n : unmanaged object; // ???
>    try {
>        recycleList.remove(n);
>    } catch exception {
>        n = new unmanaged object();
>    }
>    return n;
> }
>
> var x = recycle();
> writeln(x);
> """
>
>
> On 8/23/19, 8:20 PM, "Brad Chamberlain" <[email protected]> wrote:
>
>
>    I'll answer the parts of this I remember the answers to offhand and leave
>    the rest for others:
>
>    > What would an array of `var A : [D] C` contain by default?
>
>    This would be an error (assuming a semicolon after the 'C' rather than an
>    `= ...`, as would `var A: C;` However, I believe at present, the compiler
>    only checks the latter, not the former (i.e., there's still a TODO here).
>
>
>    > Why not make all types nil-able by default and make nil-ability an
>    > opt-in feature?
>
>    That is a potential consideration for the future (but is not considered a
>    breaking change since no other types are currently nilable).
>
>    -Brad
>
>
>
>
_______________________________________________
Chapel-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/chapel-users

Reply via email to