Re: difference between x = Nullable.init and x.nullify

2017-06-05 Thread Jonathan M Davis via Digitalmars-d-learn
On Monday, June 05, 2017 10:46:39 Kagamin via Digitalmars-d-learn wrote:
> On Sunday, 4 June 2017 at 08:51:44 UTC, Jonathan M Davis wrote:
> >> On Saturday, 3 June 2017 at 06:19:29 UTC, Jonathan M Davis
> >>
> >> wrote:
> >> > Assigning Nullable!Test.init is equivalent to setting the
> >> > internal value to Test.init and setting _isNull to false.
> >
> > T _value;
> > bool _isNull = true;
>
> So it was a typo that Nullable.init sets _isNull to false?

Yes.

- Jonathan M Davis



Re: difference between x = Nullable.init and x.nullify

2017-06-05 Thread Kagamin via Digitalmars-d-learn

On Sunday, 4 June 2017 at 08:51:44 UTC, Jonathan M Davis wrote:
On Saturday, 3 June 2017 at 06:19:29 UTC, Jonathan M Davis 
wrote:
> Assigning Nullable!Test.init is equivalent to setting the 
> internal value to Test.init and setting _isNull to false.



T _value;
bool _isNull = true;


So it was a typo that Nullable.init sets _isNull to false?


Re: difference between x = Nullable.init and x.nullify

2017-06-04 Thread Jonathan M Davis via Digitalmars-d-learn
On Sunday, June 04, 2017 09:31:24 vit via Digitalmars-d-learn wrote:
> On Sunday, 4 June 2017 at 09:04:14 UTC, Jonathan M Davis wrote:
> > [...]
>
> Why Nullable!T call destroy for reference types?

It calls destroy for everything. Why it does that instead of simply
assigning T.init and setting _isNull to true, I don't know. Maybe the commit
history would say, but unless it was done as part of a bugfix, it's more
likely that you'd have to use the commit history to figure out who made it
do that and ask them. Thinking about it though, it does seem like it's
probably the wrong behavior. I'd guess that it was done with structs in
mind, and it doesn't usually make sense to put a class reference in Nullable
outside of generic code, since they can be null on their own.

- Jonathan M Davis



Re: difference between x = Nullable.init and x.nullify

2017-06-04 Thread vit via Digitalmars-d-learn

On Sunday, 4 June 2017 at 09:04:14 UTC, Jonathan M Davis wrote:

[...]


Why Nullable!T call destroy for reference types?


Re: difference between x = Nullable.init and x.nullify

2017-06-04 Thread Stanislav Blinov via Digitalmars-d-learn

On Sunday, 4 June 2017 at 09:04:14 UTC, Jonathan M Davis wrote:

if throwing in a destructor is considered a runtime error, 
perhaps another valid enhancement would be to statically 
disallow throwing Exceptions in destructors, i.e. *require* 
them be nothrow?..


My initial reaction would be that destructors should always be 
nothrow, though I vaguely recall there being some reason why it 
was supposed to be nice that destructors in D could cleanly 
deal with exceptions. And remember that when we're talking 
about rt_finalize, we're talking about finalizers, not 
destructors in general. When a destructor is in a GC 
heap-allocated object, it's treated as a finalizer and may or 
may not be run (since the object may or may not be collected),


It doesn't matter. The only thing that matters is that it may be 
run, and therefore rt_finalize has to count on that. And it sort 
of does, at the moment, by assuming the worst possible 
combination of attributes. Problem is, with current language 
rules, it cannot be any other way, as the runtime doesn't carry 
any information about attributes of finalized object, or the 
context in which finalization takes place (i.e. is it within a 
@safe function?), which, sadly, makes unsafe code silently 
executable in a safe context, in direct contradiction to language 
guarantees.


whereas when a destructor is on an object that's on the stack, 
it's really a destructor. So, while they use the same syntax,


It's worse than that. There are two "destructors": __xdtor that 
calls destructors of RAII members, and, on classes, __dtor that 
actually calls ~this() for the class. But only that class, not 
it's ancestors or descendants. Such segregation is, as it turns 
out, as useful as it is unwieldy.


and in the case of a struct, the same function could be either 
a destructor or a finalizer depending on where the struct is 
declared, they're not quite the same thing. And destroy muddies 
the water a bit, because it then explicitly calls the finalizer 
on a class, whereas it would normally be the GC that does it 
(and while calling GC-related functions in a finalizer is 
forbidden when called by the GC, it's fine when called via 
destroy, since the GC is then not in the middle of a 
collection).


So, I don't know whether it would be reasonable to require that 
destructors be nothrow. Certainly, it's _more_ likely for it to 
be reasonable for destructors on classes to be nothrow, since 
classes always live on the heap (and are thus finalizers) 
unless you're playing games with something like 
std.typecons.scoped, but I'd have to study the matter quite a 
bit more to give a properly informed answer as to whether it 
would be reasonable to require that all destructors be nothrow.


Scoped is not necessary. Classes may not necessarily exist in the 
GC heap, thanks to custom allocators and emplace(). But because 
the language does not enforce propagation of destructor 
attributes, destroy() is @system and not nothrow, which spills 
out into user code that would otherwise take advantage of static 
inference. Unfortunately, right now making it any other would 
impose certain restrictions on classes without real language 
support, and that is... scary.


Re: difference between x = Nullable.init and x.nullify

2017-06-04 Thread Jonathan M Davis via Digitalmars-d-learn
On Saturday, June 03, 2017 08:17:18 Stanislav Blinov via Digitalmars-d-learn 
wrote:
> On Saturday, 3 June 2017 at 08:01:14 UTC, Jonathan M Davis wrote:
> > On Saturday, June 03, 2017 06:41:44 Stanislav Blinov via
> >
> > Digitalmars-d-learn wrote:
> >> On Saturday, 3 June 2017 at 06:19:29 UTC, Jonathan M Davis
> >>
> >> wrote:
> >> > looking at what rt_finalize does, I don't see why it
> >> > couldn't be nothrow. So, unless I'm missing something, it
> >> > seems like that would be a good enhancement.
> >> >
> >> > - Jonathan M Davis
> >>
> >> Presently, rt_finalize cannot be made nothrow, or un-made
> >> @system, because "reasons":
> >> http://forum.dlang.org/thread/aalafajtuhlvfirwf...@forum.dlang.org
> >>
> >> Fixing that would require significant changes to the runtime,
> >> and probably the compiler. I don't think it qualifies as a
> >> simple "enhancement" :)
> >
> > Well, as I said, I could be missing something, but all
> > rt_finalize does is call rt_finalize2, and rt_finalize2 _is_
> > nothrow (it catches any Exceptions that are thrown by the
> > destructor/finalizer). So, I have no idea why it would be the
> > case that rt_finalize couldn't be nothrow, and I saw nothing in
> > that thread which contradicts that, but I could have read it
> > too quickly. Regardless, it's a perfectly valid enhancement
> > request whether it's easy to implement or not.
> >
> > - Jonathan M Davis
>
> Whoops, my bad, I forgot it indeed swallows exceptions and does
> the onFinalizeError instead. So... yep, then it seems that
> rt_finalize probably should be marked nothrow too. Hmm... if
> throwing in a destructor is considered a runtime error, perhaps
> another valid enhancement would be to statically disallow
> throwing Exceptions in destructors, i.e. *require* them be
> nothrow?..

My initial reaction would be that destructors should always be nothrow,
though I vaguely recall there being some reason why it was supposed to be
nice that destructors in D could cleanly deal with exceptions. And remember
that when we're talking about rt_finalize, we're talking about finalizers,
not destructors in general. When a destructor is in a GC heap-allocated
object, it's treated as a finalizer and may or may not be run (since the
object may or may not be collected), whereas when a destructor is on an
object that's on the stack, it's really a destructor. So, while they use the
same syntax, and in the case of a struct, the same function could be either
a destructor or a finalizer depending on where the struct is declared,
they're not quite the same thing. And destroy muddies the water a bit,
because it then explicitly calls the finalizer on a class, whereas it would
normally be the GC that does it (and while calling GC-related functions in a
finalizer is forbidden when called by the GC, it's fine when called via
destroy, since the GC is then not in the middle of a collection).

So, I don't know whether it would be reasonable to require that destructors
be nothrow. Certainly, it's _more_ likely for it to be reasonable for
destructors on classes to be nothrow, since classes always live on the heap
(and are thus finalizers) unless you're playing games with something like
std.typecons.scoped, but I'd have to study the matter quite a bit more to
give a properly informed answer as to whether it would be reasonable to
require that all destructors be nothrow.

- Jonathan M Davis



Re: difference between x = Nullable.init and x.nullify

2017-06-04 Thread Jonathan M Davis via Digitalmars-d-learn
On Saturday, June 03, 2017 14:30:05 Kagamin via Digitalmars-d-learn wrote:
> On Saturday, 3 June 2017 at 06:19:29 UTC, Jonathan M Davis wrote:
> > Assigning Nullable!Test.init is equivalent to setting the
> > internal value to Test.init and setting _isNull to false.
>
> Eh? Does it mean Nullable is default initialized to some non-null
> default value?

Well, that depends on what you mean by null. Nullable!T doesn't use
pointers, so it can't be null like a pointer is null. The whole point of
Nullable!T is to emulate the null behavior of pointers while keeping
everything on the stack. It's a struct that contains two members:

T _value;
bool _isNull = true;

So, _value is default-initialized to T.init, and _isNull defaults to true.
Whether Nullable!T is "null" or not depends on the value of _isNull. So,
Nullable!T is default-initialized to null in the sense that _isNull is true,
and all of its member functions that check for "null" check whether _isNull
is true, so it's treated as "null" when it's default-initialized, but it's
not truly null in the sense that a pointer or class reference can be null.
If that's what you want, just create a T* rather than a Nullable!T.

- Jonathan M Davis



Re: difference between x = Nullable.init and x.nullify

2017-06-03 Thread Kagamin via Digitalmars-d-learn

On Saturday, 3 June 2017 at 06:19:29 UTC, Jonathan M Davis wrote:
Assigning Nullable!Test.init is equivalent to setting the 
internal value to Test.init and setting _isNull to false.


Eh? Does it mean Nullable is default initialized to some non-null 
default value?


Re: difference between x = Nullable.init and x.nullify

2017-06-03 Thread vit via Digitalmars-d-learn

On Saturday, 3 June 2017 at 06:19:29 UTC, Jonathan M Davis wrote:

[...]


thanks


Re: difference between x = Nullable.init and x.nullify

2017-06-03 Thread Stanislav Blinov via Digitalmars-d-learn

On Saturday, 3 June 2017 at 08:01:14 UTC, Jonathan M Davis wrote:
On Saturday, June 03, 2017 06:41:44 Stanislav Blinov via 
Digitalmars-d-learn wrote:
On Saturday, 3 June 2017 at 06:19:29 UTC, Jonathan M Davis 
wrote:
> looking at what rt_finalize does, I don't see why it 
> couldn't be nothrow. So, unless I'm missing something, it 
> seems like that would be a good enhancement.

>
> - Jonathan M Davis

Presently, rt_finalize cannot be made nothrow, or un-made 
@system, because "reasons": 
http://forum.dlang.org/thread/aalafajtuhlvfirwf...@forum.dlang.org


Fixing that would require significant changes to the runtime, 
and probably the compiler. I don't think it qualifies as a 
simple "enhancement" :)


Well, as I said, I could be missing something, but all 
rt_finalize does is call rt_finalize2, and rt_finalize2 _is_ 
nothrow (it catches any Exceptions that are thrown by the 
destructor/finalizer). So, I have no idea why it would be the 
case that rt_finalize couldn't be nothrow, and I saw nothing in 
that thread which contradicts that, but I could have read it 
too quickly. Regardless, it's a perfectly valid enhancement 
request whether it's easy to implement or not.


- Jonathan M Davis


Whoops, my bad, I forgot it indeed swallows exceptions and does 
the onFinalizeError instead. So... yep, then it seems that 
rt_finalize probably should be marked nothrow too. Hmm... if 
throwing in a destructor is considered a runtime error, perhaps 
another valid enhancement would be to statically disallow 
throwing Exceptions in destructors, i.e. *require* them be 
nothrow?..


Re: difference between x = Nullable.init and x.nullify

2017-06-03 Thread Jonathan M Davis via Digitalmars-d-learn
On Saturday, June 03, 2017 06:41:44 Stanislav Blinov via Digitalmars-d-learn 
wrote:
> On Saturday, 3 June 2017 at 06:19:29 UTC, Jonathan M Davis wrote:
> > looking at what rt_finalize does, I don't see why it couldn't
> > be nothrow. So, unless I'm missing something, it seems like
> > that would be a good enhancement.
> >
> > - Jonathan M Davis
>
> Presently, rt_finalize cannot be made nothrow, or un-made
> @system, because "reasons":
> http://forum.dlang.org/thread/aalafajtuhlvfirwf...@forum.dlang.org
>
> Fixing that would require significant changes to the runtime, and
> probably the compiler. I don't think it qualifies as a simple
> "enhancement" :)

Well, as I said, I could be missing something, but all rt_finalize does is
call rt_finalize2, and rt_finalize2 _is_ nothrow (it catches any Exceptions
that are thrown by the destructor/finalizer). So, I have no idea why it
would be the case that rt_finalize couldn't be nothrow, and I saw nothing in
that thread which contradicts that, but I could have read it too quickly.
Regardless, it's a perfectly valid enhancement request whether it's easy to
implement or not.

- Jonathan M Davis



Re: difference between x = Nullable.init and x.nullify

2017-06-03 Thread Stanislav Blinov via Digitalmars-d-learn

On Saturday, 3 June 2017 at 06:19:29 UTC, Jonathan M Davis wrote:

looking at what rt_finalize does, I don't see why it couldn't 
be nothrow. So, unless I'm missing something, it seems like 
that would be a good enhancement.


- Jonathan M Davis


Presently, rt_finalize cannot be made nothrow, or un-made 
@system, because "reasons":

http://forum.dlang.org/thread/aalafajtuhlvfirwf...@forum.dlang.org

Fixing that would require significant changes to the runtime, and 
probably the compiler. I don't think it qualifies as a simple 
"enhancement" :)


Re: difference between x = Nullable.init and x.nullify

2017-06-03 Thread Jonathan M Davis via Digitalmars-d-learn
On Saturday, June 03, 2017 05:52:55 vit via Digitalmars-d-learn wrote:
> Hello,
> What's the difference between x = Nullable!Test.init and
> x.nullify?
>
>
> class Test{}
>
> void test()pure nothrow{
>  Nullable!Test x;
>
>  x = Nullable!Test.init; //OK
>  x.nullify;  //Error: function
> 'std.typecons.Nullable!(Test).Nullable.nullify!().nullify' is not
> nothrow
>
> }

Assigning Nullable!Test.init is equivalent to setting the internal value to
Test.init and setting _isNull to false. nullify doesn't assign
Nullable!Test.init to the Nullable!Test, and it doesn't assign Test.init to
_value. Rather, it calls destroy on _value and sets _isNull to true. Exactly
what destroy does depends on the type. In the case of a class, it calls
rt_finalize on it, which basically calls the class' finalizer (if it has
one). But rt_finalize is not nothrow, so destroy isn't nothrow, so nullify
isn't nothrow. However, looking at what rt_finalize does, I don't see why it
couldn't be nothrow. So, unless I'm missing something, it seems like that
would be a good enhancement.

- Jonathan M Davis