Re: Class qualifier vs struct qualifier

2018-06-14 Thread David Bennett via Digitalmars-d-learn

On Wednesday, 13 June 2018 at 07:35:25 UTC, RazvanN wrote:

Hello,

I'm having a hard time understanding whether this inconsistency 
is a bug or intended behavior:


immutable class Foo {}
immutable struct Bar {}

void main()
{
import std.stdio : writeln;
Foo a;
Bar b;

writeln("typeof(a): ", typeof(a).stringof);
writeln("typeof(b): ", typeof(b).stringof);
}

prints:

typeof(Foo): Foo
typeof(Bar): immutable(Bar)


It seems like the class storage class is not taken into account 
which leads to some awkward situations like:


immutable class Foo
{
this() {}
}

void main()
{
Foo a = new Foo(); // error: immutable method `this` is not 
callable using a

   // mutable object
}

To make it work I have to add immutable to both sides of the 
expression : immutable Foo a = new immutable Foo(); this is a 
wonder of redundancy. I already declared the class as immutable 
so it shouldn't be possible to have mutable instances of it 
(and it isn't), however I am forced to write the immutable 
twice even though it is pretty obvious that the class cannot be 
mutated.


Just tested and I only seem to need to add the immutable to the 
left of the expression.


https://run.dlang.io/is/EZ7es0

Also with the struct `Bar* b = new Bar();` works fine so i guess 
the discrepancy is because the class ref is mutatable.


Re: What is the point of nothrow?

2018-06-14 Thread bauss via Digitalmars-d-learn

On Thursday, 14 June 2018 at 19:06:07 UTC, Jonathan M Davis wrote:
As I said, personally, I think that the program shut just print 
and terminate rather than throwing an Error. Walter seems to


It makes perfectly sense for it to throw an error and not just 
print and terminate.


This is especially true for server applications and especially 
server applications running in the cloud where you do not 
necessarily have access to a console, but you most likely will 
have access to a database.


So in case of a thrown Error, you can catch it and log it to a 
database.


If it was just printing it would be a lot hard to do such a task, 
especially when you take permission etc. into account.


D would _never_ be fit for large scalable applications if it 
wasn't possible to retrieve the errors on any system and 
platform, no matter your limitations.




Create an Algebraic type at compile time and more

2018-06-14 Thread uknys via Digitalmars-d-learn

Hello,

I wanted to know if such code was possible :

alias Operation = Algebraic!(/* All type that implements X UDA */)

struct X
{
int opcode;
Operation h;
}

@X(0x01, Hello(3))
@X(0x02, Hello(4))
struct Hello
{
int Hello;
}

@X(0x03, Toto(5))
@X(0x05, Toto(6))
struct Toto
{
   int A;
}


It has two problems, Operation not being defined while I use it 
in the UDA, and how to get back all the types that implements 
this UDA to give it to Algebraic.
I don't know if it's a good idea or not, but might as well try 
the dark side of meta programming.


Thanks a lot :)


Re: What is the point of nothrow?

2018-06-14 Thread Jonathan M Davis via Digitalmars-d-learn
On Thursday, June 14, 2018 18:11:20 wjoe via Digitalmars-d-learn wrote:
> On Wednesday, 13 June 2018 at 20:08:06 UTC, Jonathan M Davis
> wrote:
> > On Wednesday, June 13, 2018 10:56:41 wjoe via
> > The idea is that because your program is in an invalid state,
> > attempting a graceful shutdown is unsafe. But regardless of
> > whether you agree with that, the fact that nothrow doesn't do
> > clean-up pretty much ensures that it isn't safe in the general
> > case, and nothrow can't do clean-up without negating one of the
> > main reasons that it exists in the first place - which is to
>
> that fact also means that a program which threw an Error cannot
> be debugged anymore; because of invalid state you can neither
> know, nor assume, that what you see in your debugger or core dump
> is actually the state which led to the throw.

As I said, personally, I think that the program shut just print and
terminate rather than throwing an Error. Walter seems to have designed
things from the premise that you could rerun the program to reproduce the
problem (which in is usually true with the programs he works on). And in
that case, simply getting the error message and stacktrace would be plenty.
The problem is when you can't simply rerun the program to reproduce the
problem and is why I'm of the opinion that printing and terminating would be
better than throwing an Error.

> > improve performance by not emitting exception-handling code.
>
> if performance matters so much I would use betterC.
>
> 'Improving' performance without profiling and such a trade-off is
> a bad idea. If it were opt in - yes, I know I will get
> undebuggable code on error thrown but I want or need the
> performance gain, fair enough. But instead you are a victim of
> that implementation whether you like it or not and you might not
> even be aware about it.

betterC really has nothing to do with performance. It just has to do with
avoiding druntime so that you can have C code just link in and use the D
code as if it were C (though using it would avoid the issue of Errors, since
the runtime wouldn't be there to handle them). And again, Errors are
intended for fatal cases, so most of the concerns about doing clean-up are
irrelevant. Attempting to recover from an Error is considered to be like
attempting to recover from a segfault, which is a terrible, terrible idea.
And there are plenty of folks who want to be able to have their code be more
performant when it's not using exceptions. So, as long as folks aren't
trying to catch Errors, the fact that nothrow doesn't emit the exception
handling code really isn't a problem.

> Out of curiosity, in case of out of memory, will the program
> crash trying to throw OutOfMemoryError or is it pre-allocated
> along with the memory needed to format and print the message?

OutOfMemoryError is pre-allocated. core.exception's onOutOfMemoryError is
called rather than allocating a new OutOfMemoryError.

> And out of curiosity again, where would I find this place where
> the printing and terminating occurs ?

I'd have to go digging in druntime. I don't know. I've probably seen it
before, but it's not code that I've dealt with often enough to remember
exactly where it is off the top of my head.

> > Personally, I'm increasingly of the opinion that having Errors
> > was a mistake and that the better solution would have been to
> > just print out the error message and stack trace right there
> > and immediately kill the program. That would then give you a
> > coredump exactly where you were and avoid all of the confusion
> > about Errors being thrown but not really doing proper clean-up.
> > I don't know why Walter decided to do it the way he did,
> > particularly since he's made it very clear that the entire
> > point of Errors is to indicate a fatal error in the program,
> > that doing any clean-up at that point is dangerous, and that
> > the program needs to terminate, not try to recover.
>
> Aborting with an error code would be sufficient. No need to print
> anything.
> A backtrace can be obtained in the debugger.

Given that a coredump isn't always generated (and in the case of Windows, I
don't know if they even have an equivalent), printing out the same
information that gets printed out now would often be desirable. It's just
that if it kills the program right there rather than doing any unwinding of
the stack, then the coredump is for the state of the program at the point of
failure like it arguably should be.

> > But I don't think that changing it so that Errors terminated
> > immediately (and thus gave you a coredump for that spot in the
> > program) would change what's an Error and what's an Exception.
>
> No it wouldn't but not everything declared or treated as an error
> in D is one.
>
> There should be only a few and everything else should be an
> Exception.

There are no Errors in druntime or Phobos that I'm aware of where I would
not consider it perfectly reasonable that they're Errors, but there are
cases

Re: What is the point of nothrow?

2018-06-14 Thread wjoe via Digitalmars-d-learn
On Wednesday, 13 June 2018 at 20:08:06 UTC, Jonathan M Davis 
wrote:
On Wednesday, June 13, 2018 10:56:41 wjoe via 
Digitalmars-d-learn wrote:

On Wednesday, 13 June 2018 at 03:14:33 UTC, Jonathan M Davis
> regardless of whether the decision to treat failed memory 
> allocations as an Error was a good one or not, the fact 
> remains that as soon as an Error is thrown, you lose the 
> ability to deal with things cleanly, because full clean up 
> is not done when an Error is thrown (and can't be due to 
> things like how nothrow works). So, regardless of whether a 
> failed memory allocation is a condition that can be 
> recovered from in principle, the way that D handles GC 
> allocations make it unrecoverable in practice - at least as 
> far as GC-allocated memory is concerned.


Did I get that right?
You say when an error is thrown destructors, scope statements,
etc. are not executed - if declared as nothrow because the
exception handler mechanism stuff is missing, is that correct?
And it does execute if not declared as nothrow but can't be
relied upon because some other  nothrow functions could have
omitted some of those statements?


Yes, and there's no guarantee that clean-up will occur even if 
nothing is nothrow. While the current implementation will do


Good to know. The thought crossed my mind to remove nothrow from 
all functions... ;)


clean-up in those cases, it didn't used to, and Walter has 
repeatedly stated that it is not guaranteed to do so. Errors 
are _not_ intended to be caught and recovered from. They're 
essentially a segfault that prints a message and stack trace 
but which for some reason uses the exception throwing mechanism 
to get to the code that prints the message and exits the 
program.




So the program is in a stable enough state to run the exception 
handling mechanism to print a message and die, but not stable 
enough to run a memset or writePin(11,0) before continuing 
trampling forward to where the printing and dying happens ?


So I shoot myself in the foot with nothrow and if I don't use 
it I'm still in a world of hurt?


I understand the idea that an Error is not supposed to be 
caught but why would such a 'feature' be desirable? Where's 
the benefit if nothing can be relied upon ?


If all errors would be treated like an exception, the 
developer could decide whether it is an error which needs to 
terminate right away or be able to handle the issue and 
continue or gracefully shutdown.


The idea is that because your program is in an invalid state, 
attempting a graceful shutdown is unsafe. But regardless of 
whether you agree with that, the fact that nothrow doesn't do 
clean-up pretty much ensures that it isn't safe in the general 
case, and nothrow can't do clean-up without negating one of the 
main reasons that it exists in the first place - which is to



that fact also means that a program which threw an Error cannot 
be debugged anymore; because of invalid state you can neither 
know, nor assume, that what you see in your debugger or core dump 
is actually the state which led to the throw.



improve performance by not emitting exception-handling code.


if performance matters so much I would use betterC.

'Improving' performance without profiling and such a trade-off is 
a bad idea. If it were opt in - yes, I know I will get 
undebuggable code on error thrown but I want or need the 
performance gain, fair enough. But instead you are a victim of 
that implementation whether you like it or not and you might not 
even be aware about it.





Could even set a break point or force a core
dump right there.


The fact that Errors don't immediately kill the program and 
instead sort of unwind the stack is a definite problem for 
getting good debug information on crashes. I suspect that 
Walter doesn't quite understand the issues here, because 
whenever anyone raises issues related to stuff like this, he 
has a tendancy to basically tell people to rerun their program 
- which works fantastically in the world he typically programs 
in (compilers) but doesn't work very well with stuff like OSes 
or server programs where you frequently have no clue how to 
replicate the problem. My guess is that Errors work they do in 
part because he's not used to debugging situations where a 
coredump being created at the point of failure the first time 
it happens (rather than during attempts to reproduce the 
problem) is what you really need.




Or any program which is interactive or where input is non 
deterministic.


Out of curiosity, in case of out of memory, will the program 
crash trying to throw OutOfMemoryError or is it pre-allocated 
along with the memory needed to format and print the message?


And out of curiosity again, where would I find this place where 
the printing and terminating occurs ?



I think that the reasons that this is not a bigger problem than 
it is stem primarily from the fact that Errors are going to be 
very rare in production code unless it wasn'

Re: Static Array Idiom not working anymore.

2018-06-14 Thread Jonathan M Davis via Digitalmars-d-learn
On Thursday, June 14, 2018 08:40:10 Steven Schveighoffer via Digitalmars-d-
learn wrote:
> On 6/14/18 7:07 AM, Guillaume Piolat wrote:
> > On Tuesday, 12 June 2018 at 15:35:42 UTC, Steven Schveighoffer wrote:
> >> No, that's not what I mean. What I mean is:
> >>
> >> int[] arr = [1,2,3].s;
> >> int[] arr2 = [4,5,6].s;
> >>
> >> Legally, the compiler is allowed to reuse the stack memory allocated
> >> for arr for arr2. The lifetime of the arr data is over.
> >>
> >> -Steve
> >
> > https://github.com/p0nce/d-idioms/issues/150
> >
> > Especially if the stdlib has a way to do this now.
>
> The Phobos PR isn't merged yet, so I think it's still valid to have this
> idiom, but it needs to be changed such that the implicit slicing doesn't
> happen.
>
> To be clear, I think the static array idiom is useful for many reasons
> (my favorite is avoiding issues with literal and type size mismatch), it
> just that the showcase usage leads to an instant dangling pointer and
> should be altered.

Yeah. The problem is not the function to create a static array. The problem
is that the return value is being sliced rather than storing it on the stack
and then slicing the local variable. Slicing the return value was never a
safe thing to do, and if the compiler is now giving an error when you try to
do it, that's actually a really good thing.

- Jonathan M Davis



Re: Class qualifier vs struct qualifier

2018-06-14 Thread Jonathan M Davis via Digitalmars-d-learn
On Thursday, June 14, 2018 08:39:48 RazvanN via Digitalmars-d-learn wrote:
> > Honestly, from what I understand of how this works, what I find
> > weird is the struct case. immutable on classes does _not_ make
> > the class itself immutable. It just makes all of its members
> > immutable - hence the error about trying to allocate new Foo
> > instead of new immutable Foo. So, that is exactly what I would
> > expect. And honestly, being able to write Foo and have it imply
> > immutable Foo would get _really_ confusing when reading and
> > debugging code.
>
> Maybe it has something to do with structs being value types and
> classes
> being reference types. If you declare an immutable struct then
> you cannot
> modify it's value, while if you declare a class, the pointer to
> the class
> is mutable, while the class fields are not. This kind of makes
> sense, however
> the thing is that in both situations you are not able to mutate
> any of the
> class/struct fields no matter how you instantiate it, so it is
> really redundant
> to use `immutable` when creating the instance.

Except that it isn't redundant, because without using immutable, it looks
like you're trying to create a mutable object. Would you honestly ever look
at something like

Foo foo;

and expect the object to be immutable? And sadly, looking at the type
declaration isn't even necessarily enough to know that it was marked with
immutable, because someone could have done something dumb like put

immutable:

higher up in the file. Types normally require that you explicitly mark them
as immutable to make them immutable when using them anywhere - including
declaring variables or allocating objects. I don't see why having made all
of the members of the type immutable should change that. It's just extra
magic that makes it harder to read the code. Sure, it would save you a
little bit of typing when you do something like

auto foo = new Foo;

if makes it immutable for you, but it's at the cost of code clarity.

- Jonathan M Davis



Re: foreach DFS/BFS for tree data-structure?

2018-06-14 Thread Meta via Digitalmars-d-learn

On Thursday, 14 June 2018 at 11:31:50 UTC, Robert M. Münch wrote:

I have a simple tree C data-structure that looks like this:

node {
node parent:
vector[node] children;
}

I would like to create two foreach algorthims, one follwing the 
breadth first search pattern and one the depth first search 
pattern.


Is this possible? I read about Inputranges, took a look at the 
RBTree code etc. but don't relly know/understand where to start.


While it's possible to do with input ranges, it's not pretty and 
I'm not sure that it's as performant as the traditional method. I 
would recommend going with one of the other suggestions in this 
thread.


Re: foreach DFS/BFS for tree data-structure?

2018-06-14 Thread Steven Schveighoffer via Digitalmars-d-learn

On 6/14/18 8:35 AM, Robert M. Münch wrote:

On 2018-06-14 11:46:04 +, Dennis said:


On Thursday, 14 June 2018 at 11:31:50 UTC, Robert M. Münch wrote:
Is this possible? I read about Inputranges, took a look at the RBTree 
code etc. but don't relly know/understand where to start.


You can also use opApply to iterate over a tree using foreach, see:
https://tour.dlang.org/tour/en/gems/opdispatch-opapply


Ah... that looks very good. Need to dig a bit deeper on how to use it. 
Thanks.




Just to clarify, RBTree can easily do DFS without a real stack because 
there are a finite number of children (2) for each node, and it's an 
O(1) operation to figure out which child the current node is in relation 
to the parent (am I a left child or right child?).


Now, with your C version, if your children are stored in the array 
itself, figuring out the "next" child is a matter of doing &this + 1. 
But if you are storing pointers instead, then figuring out the next 
child would be an O(n) operation.


Using the stack to track where you are (via opApply) is a valid way as 
well. You could also unroll that into a malloc'd stack, but the code is 
not as pretty of course.


-Steve


Re: Static Array Idiom not working anymore.

2018-06-14 Thread Steven Schveighoffer via Digitalmars-d-learn

On 6/14/18 7:07 AM, Guillaume Piolat wrote:

On Tuesday, 12 June 2018 at 15:35:42 UTC, Steven Schveighoffer wrote:


No, that's not what I mean. What I mean is:

int[] arr = [1,2,3].s;
int[] arr2 = [4,5,6].s;

Legally, the compiler is allowed to reuse the stack memory allocated 
for arr for arr2. The lifetime of the arr data is over.


-Steve


https://github.com/p0nce/d-idioms/issues/150

Especially if the stdlib has a way to do this now.


The Phobos PR isn't merged yet, so I think it's still valid to have this 
idiom, but it needs to be changed such that the implicit slicing doesn't 
happen.


To be clear, I think the static array idiom is useful for many reasons 
(my favorite is avoiding issues with literal and type size mismatch), it 
just that the showcase usage leads to an instant dangling pointer and 
should be altered.


-Steve


Re: foreach DFS/BFS for tree data-structure?

2018-06-14 Thread Robert M. Münch via Digitalmars-d-learn

On 2018-06-14 11:46:04 +, Dennis said:


On Thursday, 14 June 2018 at 11:31:50 UTC, Robert M. Münch wrote:
Is this possible? I read about Inputranges, took a look at the RBTree 
code etc. but don't relly know/understand where to start.


You can also use opApply to iterate over a tree using foreach, see:
https://tour.dlang.org/tour/en/gems/opdispatch-opapply


Ah... that looks very good. Need to dig a bit deeper on how to use it. Thanks.

--
Robert M. Münch
http://www.saphirion.com
smarter | better | faster



Re: foreach DFS/BFS for tree data-structure?

2018-06-14 Thread Dennis via Digitalmars-d-learn

On Thursday, 14 June 2018 at 11:31:50 UTC, Robert M. Münch wrote:
Is this possible? I read about Inputranges, took a look at the 
RBTree code etc. but don't relly know/understand where to start.


You can also use opApply to iterate over a tree using foreach, 
see:

https://tour.dlang.org/tour/en/gems/opdispatch-opapply


Re: foreach DFS/BFS for tree data-structure?

2018-06-14 Thread rikki cattermole via Digitalmars-d-learn

On 14/06/2018 11:31 PM, Robert M. Münch wrote:

I have a simple tree C data-structure that looks like this:

node {


struct Node {


 node parent:


Node* parent;


 vector[node] children;


Node[] children;


}

I would like to create two foreach algorthims, one follwing the breadth 
first search pattern and one the depth first search pattern.


Here is (very roughly breadth):

auto search(Method method) {
struct Voldermort {
Node parent;
size_t offset;

@property {
Node front() {
return parent.children[offset];
}

bool empty() {
return offset == parent.children.length;
}
}

void popFront() {
offset++;
}
}

return Voldermort(this);
}

Depth will be a bit of a pain since you'll need to know where you have 
been at each set of children.


foreach DFS/BFS for tree data-structure?

2018-06-14 Thread Robert M. Münch via Digitalmars-d-learn

I have a simple tree C data-structure that looks like this:

node {
node parent:
vector[node] children;
}

I would like to create two foreach algorthims, one follwing the breadth 
first search pattern and one the depth first search pattern.


Is this possible? I read about Inputranges, took a look at the RBTree 
code etc. but don't relly know/understand where to start.


--
Robert M. Münch
http://www.saphirion.com
smarter | better | faster



Re: Static Array Idiom not working anymore.

2018-06-14 Thread Guillaume Piolat via Digitalmars-d-learn
On Tuesday, 12 June 2018 at 15:35:42 UTC, Steven Schveighoffer 
wrote:


No, that's not what I mean. What I mean is:

int[] arr = [1,2,3].s;
int[] arr2 = [4,5,6].s;

Legally, the compiler is allowed to reuse the stack memory 
allocated for arr for arr2. The lifetime of the arr data is 
over.


-Steve


https://github.com/p0nce/d-idioms/issues/150

Especially if the stdlib has a way to do this now.


Re: Class qualifier vs struct qualifier

2018-06-14 Thread RazvanN via Digitalmars-d-learn
Honestly, from what I understand of how this works, what I find 
weird is the struct case. immutable on classes does _not_ make 
the class itself immutable. It just makes all of its members 
immutable - hence the error about trying to allocate new Foo 
instead of new immutable Foo. So, that is exactly what I would 
expect. And honestly, being able to write Foo and have it imply 
immutable Foo would get _really_ confusing when reading and 
debugging code.


Maybe it has something to do with structs being value types and 
classes
being reference types. If you declare an immutable struct then 
you cannot
modify it's value, while if you declare a class, the pointer to 
the class
is mutable, while the class fields are not. This kind of makes 
sense, however
the thing is that in both situations you are not able to mutate 
any of the
class/struct fields no matter how you instantiate it, so it is 
really redundant

to use `immutable` when creating the instance.

What's bizarre is that marking the struct with immutable would 
affect anything other than its members.


Bar b;

should not claim that typeof(b) is immutable(Bar). b was not 
marked as
immutable. It was listed as Bar, not immutable Bar. So, b 
shouldn't be

immutable.

- Jonathan M Davis