Re: Difference between chunks(stdin, 1) and stdin.rawRead?

2024-03-28 Thread H. S. Teoh via Digitalmars-d-learn
On Thu, Mar 28, 2024 at 10:10:43PM +, jms via Digitalmars-d-learn wrote:
> On Thursday, 28 March 2024 at 02:30:11 UTC, jms wrote:
[...]
> I think I figured it out and the difference is probably in the mode.
> This documentation
> https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/fread?view=msvc-170
> mentions that "If the given stream is opened in text mode,
> Windows-style newlines are converted into Unix-style newlines. That
> is, carriage return-line feed (CRLF) pairs are replaced by single line
> feed (LF) characters."
> 
> And rawRead's documention mentions that "rawRead always reads in
> binary mode on Windows.", which I guess should have given me a clue.
> chunks must be using text-mode.

It's not so much that chunks is using text-mode, but that you opened the
file in text mode.  On Windows, if you don't want crlf translation you
need to open your file with File(filename, "rb"), not just File(filename
"r"), because the latter defaults to text mode.


T

-- 
There's light at the end of the tunnel. It's the oncoming train.


Re: Difference between chunks(stdin, 1) and stdin.rawRead?

2024-03-28 Thread jms via Digitalmars-d-learn

On Thursday, 28 March 2024 at 02:30:11 UTC, jms wrote:
Why in the below silly program am I reading both the \r and \n 
characters when using rawRead in block a, but when looping by 1 
byte chunks in block b only appear to be reading the \n 
characters?


I'm on Windows 11 using DMD64 D Compiler v2.107.1 if that 
matters, but I'm thinking this maybe has something to do with 
stdin in general that I'm not aware of. Any pointers to 
understanding what's going on would be appreciated.


import std.stdio;

void main() {
int i;
a: {
i = 0;
writeln("\nin a");
ubyte[1] buffer;
while (true) {
i++;
stdin.rawRead(buffer);
if (buffer[0] == 13) {
write("CR");
} else if (buffer[0] == 10) {
write("LF");
}
if (i > 5) {
goto b;
}

}
}
b: {

writeln("\n\nin b");
i = 0;
foreach (ubyte[] buffer; chunks(stdin, 1)) {
i++;
if (buffer[0] == 13) {
write("cr");
} else if (buffer[0] == 10) {
write("lf");
}
if (i > 5) {
goto a;
}
}
}

}



Output:
in a

CRLF
CRLF
CRLF

in b

lf
lf
lf
lf
lf
lf
in a


I think I figured it out and the difference is probably in the 
mode. This documentation 
https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/fread?view=msvc-170 mentions that "If the given stream is opened in text mode, Windows-style newlines are converted into Unix-style newlines. That is, carriage return-line feed (CRLF) pairs are replaced by single line feed (LF) characters."


And rawRead's documention mentions that "rawRead always reads in 
binary mode on Windows.", which I guess should have given me a 
clue. chunks must be using text-mode.




Re: Difference between using `import` with/without the colon

2023-03-19 Thread Jeremy via Digitalmars-d-learn

On Sunday, 19 March 2023 at 08:47:32 UTC, Basile B. wrote:

On Sunday, 19 March 2023 at 07:20:17 UTC, Jeremy wrote:

[...]


The colon-form, aka "selective import" has for effect

1. to create a local alias so this can indeed speedup symbol 
lookups in the sense that search will succeed before looking in 
the scope of the imports.
2. to make non-selected symbols, i.e not listed in the colon 
right hand side, in the import not available.


Note that using both makes no sense, but I guess you did that 
to express more clearly what you meant.


Ah, that makes sense. Thank you!


Re: Difference between using `import` with/without the colon

2023-03-19 Thread Basile B. via Digitalmars-d-learn

On Sunday, 19 March 2023 at 07:20:17 UTC, Jeremy wrote:
Hello, is there any difference at all between the following 
lines, as an example:


```d
import std.regex;
import std.regex : matchFirst;
```

What technical differences does it make (except for having the 
identifier available), using the colon?
Does it make any speed/optimization changes or am I better off 
just importing the whole module?


The colon-form, aka "selective import" has for effect

1. to create a local alias so this can indeed speedup symbol 
lookups in the sense that search will succeed before looking in 
the scope of the imports.
2. to make non-selected symbols, i.e not listed in the colon 
right hand side, in the import not available.


Note that using both makes no sense, but I guess you did that to 
express more clearly what you meant.


Re: difference between x.atomicOp!"+="(1) and atomicFetchAdd(x, 1)?

2022-11-10 Thread mw via Digitalmars-d-learn

On Thursday, 10 November 2022 at 18:30:16 UTC, Paul Backus wrote:

On Thursday, 10 November 2022 at 17:04:31 UTC, mw wrote:

Hi,

Anyone can help explain what is the difference between 
x.atomicOp!"+="(1) and atomicFetchAdd(x, 1)?


Looking at the source in druntime, `atomicOp!"+="` forwards to 
`atomicFetchAdd` internally, so they should have the same 
behavior.


Thanks! Indeed:

https://github.com/dlang/dmd/blob/master/druntime/src/core/atomic.d#L582

(source is always your best friend :-)

and looks like atomicFetchAdd is more fundamental:

```
return cast(T)(atomicFetchAdd(val, mod) + mod);
```


Re: difference between x.atomicOp!"+="(1) and atomicFetchAdd(x, 1)?

2022-11-10 Thread Paul Backus via Digitalmars-d-learn

On Thursday, 10 November 2022 at 17:04:31 UTC, mw wrote:

Hi,

Anyone can help explain what is the difference between 
x.atomicOp!"+="(1) and atomicFetchAdd(x, 1)?


Looking at the source in druntime, `atomicOp!"+="` forwards to 
`atomicFetchAdd` internally, so they should have the same 
behavior.


Re: Difference between range `save` and copy constructor

2020-02-17 Thread uranuz via Digitalmars-d-learn
> Either way, generic code should never be using a range after 
> it's been copied, and copying is a key part of how 
> idiomatic, range-based code works in D.


OK. Thanks for instructions. I shall give it a try.



Re: Difference between range `save` and copy constructor

2020-02-16 Thread Jonathan M Davis via Digitalmars-d-learn
On Sunday, February 16, 2020 12:22:01 PM MST Paul Backus via Digitalmars-d-
learn wrote:
> On Sunday, 16 February 2020 at 18:11:11 UTC, Jonathan M Davis
>
> wrote:
> > Either way, generic code should never be using a range after
> > it's been copied, and copying is a key part of how idiomatic,
> > range-based code works in D.
>
> "Copy and then never use the original again" is conceptually the
> same thing as "move", right? In which case, generic code can
> accommodate non-copyable ranges *and* more clearly communicate
> its intent by using `move` instead of a naked copy.

We already have enough of a mess with save without making things even worse
by trying to add moves into the mix. Also, non-copyable ranges have never
really been a thing, and I really don't want to see things complicated even
further trying to support such an uncommon use case. There are too many
weird corner cases with ranges as it is.

- Jonathan M Davis





Re: Difference between range `save` and copy constructor

2020-02-16 Thread Paul Backus via Digitalmars-d-learn
On Sunday, 16 February 2020 at 18:11:11 UTC, Jonathan M Davis 
wrote:
Either way, generic code should never be using a range after 
it's been copied, and copying is a key part of how idiomatic, 
range-based code works in D.


"Copy and then never use the original again" is conceptually the 
same thing as "move", right? In which case, generic code can 
accommodate non-copyable ranges *and* more clearly communicate 
its intent by using `move` instead of a naked copy.


Re: Difference between range `save` and copy constructor

2020-02-16 Thread Jonathan M Davis via Digitalmars-d-learn
On Sunday, February 16, 2020 10:53:36 AM MST Paul Backus via Digitalmars-d-
learn wrote:
> On Sunday, 16 February 2020 at 17:10:24 UTC, Jonathan M Davis
>
> wrote:
> > On Sunday, February 16, 2020 7:29:11 AM MST uranuz via
> >
> >> This is working fine with disabled postblit...
> >> import std;
> >>
> >> struct SS
> >> {
> >>
> >>  @disable this(this); // Disabled copy
> >>
> >>  bool _empty = false;
> >>
> >>  bool empty() @property {
> >>
> >>  return _empty;
> >>
> >>  }
> >>
> >>  void popFront() {
> >>
> >> _empty = true;
> >>
> >>  }
> >>
> >>  int front() @property { return 10; }
> >>
> >> }
> >>
> >>
> >> void main()
> >> {
> >>
> >>  foreach( it; SS() ) { writeln(it); }
> >>
> >> }
> >>
> >> Am I missing something?
> >
> > That code compiles, because you're passing a temporary to
> > foreach. So, the compiler does a move instead of a copy. It's
> > the difference between
> >
> > auto ss = SS();
> >
> > and
> >
> > SS ss;
> > auto ss2 = ss;
> >
> > If your main were
> >
> > void main()
> > {
> >
> > SS ss;
> > foreach( it; ss ) { writeln(it); }
> >
> > }
> >
> > then it would not compile.
>
> On the other hand, this does work:
>
>  void main()
>  {
>  SS ss;
>  foreach( it; move(ss) ) { writeln(it); }
>  }
>
> So perhaps the correct approach is to use `move` when copying
> input ranges.

Given that the way that almost all range-based functions work is to copy the
range that they're given (often then wrapping it in another range that's
returned), I don't see how it would make sense to use move outside of very
specific circumstances. If you pass a range to a function, and it's a basic
input range, then you just use the range via the return value (be it the
same range returned directly or returned within a wraper range), and if it's
a forward range, you call save before passing it to the function if you want
to be able to use the range directly again. Either way, generic code should
never be using a range after it's been copied, and copying is a key part of
how idiomatic, range-based code works in D.

And really, using move just to be able to use an uncopyable range with
foreach doesn't make a lot of sense, since if that's what you want to do,
you can always just use a normal for loop. Regardless, there isn't much
point in declaring a range type that can't be copied, since it's pretty much
only going to work with code that you write.

- Jonathan M Davis





Re: Difference between range `save` and copy constructor

2020-02-16 Thread Paul Backus via Digitalmars-d-learn
On Sunday, 16 February 2020 at 17:10:24 UTC, Jonathan M Davis 
wrote:

On Sunday, February 16, 2020 7:29:11 AM MST uranuz via

This is working fine with disabled postblit...
import std;

struct SS
{
 @disable this(this); // Disabled copy

 bool _empty = false;

 bool empty() @property {
 return _empty;
 }

 void popFront() {
_empty = true;
 }

 int front() @property { return 10; }
}


void main()
{
 foreach( it; SS() ) { writeln(it); }
}

Am I missing something?


That code compiles, because you're passing a temporary to 
foreach. So, the compiler does a move instead of a copy. It's 
the difference between


auto ss = SS();

and

SS ss;
auto ss2 = ss;

If your main were

void main()
{
SS ss;
foreach( it; ss ) { writeln(it); }
}

then it would not compile.


On the other hand, this does work:

void main()
{
SS ss;
foreach( it; move(ss) ) { writeln(it); }
}

So perhaps the correct approach is to use `move` when copying 
input ranges.


Re: Difference between range `save` and copy constructor

2020-02-16 Thread Jonathan M Davis via Digitalmars-d-learn
On Sunday, February 16, 2020 6:52:17 AM MST uranuz via Digitalmars-d-learn 
wrote:
> It's very bad. Because there seem that when I use range based
> algorithm I need to take two things into account. The first is
> how algrorithm is implemented. If it creates copies of range
> inside or pass it by reference. And the second is how the range
> is implemented if it has value or reference semantics. So every
> time I need to look into implementation and I can't rely on API
> description in most of the cases. In a lot of cases Phobos uses
> value semantics. But there are cases where I want the range
> actually be consumed, but it's not. And the other problemme is
> when algorithm expects range to have value semantics, but it's
> not. So it's a buggy mess that it's hard to think about. In
> trivial cases this is working although. But in more complex cases
> it's simplier to implement some algorithms by own hands so that
> it would work as I expect it myself rather that thinking about
> all these value-ref-range mess. But still can't say that I
> implement it correctly, because range specification actually
> sucks as yo say.
> It's just horrible

The current situation is definitely not ideal, but it can be used quite
consistently. Just follow the rule that once you copy a range, you do not
use that range ever again unless you assign it a new value. So, if you do
something like

auto result = r.find(e);

then you should not be using r again unless you assign it a new value.
e.g.

r = r.find(e);
r.popFront();

auto result = r.find(e);
r = otherRange;
r.popFront();

would be fine, because r was assigned a new value, whereas

auto result = r.find(e);
r.popFront();

should never happen in your code unless you know that typeof(r) is a type
where copying it is equivalent to calling save on it. In generic code, that
means that you should never use a range again after passing it to a function
unless you assign it a new value, or that function accepted the argument by
ref (which almost no range-based functions do).

If you want to be able to use the range again after passing it to a function
without assigning it a new value, then you need to call save so that you
pass an independent copy. e.g.

auto result = r.find.save(e);
r.popFront();

The only copying going on here is with save, so there's no problem, whereas
if r were passed to find directly, the behavior is implementation-dependent
- hence why you should not be using a range after it's been copied (which
includes passing it to a function).

The only time that generic code can reuse a range after passing it to a
function is if that function accepts its argument by ref, which almost no
range-based code does. Far more frequently, it returns the result as a
wrapper range, in which case, you can't use the original range any longer
unless you used save when calling the function or if the code is not generic
and you're coding based on the specific behavior of that particular range
type - which usually isn't something that code should be doing.

By no means do I claim that the status quo here is desirable, but if you
just follow the simple rule that you don't ever use a range once it's been
copied (unless that copy came from save), then you shouldn't run into
problems related to the fact that different ranges have different copying
semantics unless the function that you're calling is buggy.

If you're going to run into a bug along those lines though, it's likely
going to be because a function didn't call save when it was supposed to, and
it was only tested with range types where copying them is equivalent to
save. That's why it's important to test range-based code with both range
types where copying them is equivalent to save and range types which are
full-on reference types (and thus copying just results in another
reference). In general though, any range that is a forward range should have
copying it be equivalent to save, and using reference types for forward
ranges tends to be inefficient and error-prone even if range-based functions
(especially those in Phobos) should be able to handle them correctly.

- Jonathan M Davis





Re: Difference between range `save` and copy constructor

2020-02-16 Thread Jonathan M Davis via Digitalmars-d-learn
On Sunday, February 16, 2020 7:29:11 AM MST uranuz via Digitalmars-d-learn 
wrote:
> On Sunday, 16 February 2020 at 12:38:51 UTC, Jonathan M Davis
>
> wrote:
> > On Sunday, February 16, 2020 3:41:31 AM MST uranuz via
> >
> > Digitalmars-d-learn wrote:
> >> I have reread presentation:
> >> http://dconf.org/2015/talks/davis.pdf
> >> We declare that `pure` input range cannot be `unpoped` and we
> >> can't return to the previous position of it later at the time.
> >> So
> >> logically there is no sence of copying input range at all. So
> >> every Phobos algorithm that declares that it's is working with
> >> InputRange must be tested for working with range with disabled
> >
> > A range that can't be copied is basically useless. Not only do
> > almost all range-based algorithms take their argumenst by value
> > (and thus copy them), but foreach copies any range that it's
> > given, meaning that if a range isn't copyable, you can't even
> > use it with foreach. And since many range-based algorithms
> > function by wrapping one range with another, the ability to
> > copy ranges is fundamental to most range-based code.
>
> This is working fine with disabled postblit...
> import std;
>
> struct SS
> {
>  @disable this(this); // Disabled copy
>
>  bool _empty = false;
>
>  bool empty() @property {
>  return _empty;
>  }
>
>  void popFront() {
> _empty = true;
>  }
>
>  int front() @property { return 10; }
> }
>
>
> void main()
> {
>  foreach( it; SS() ) { writeln(it); }
> }
>
> Am I missing something?

That code compiles, because you're passing a temporary to foreach. So, the
compiler does a move instead of a copy. It's the difference between

auto ss = SS();

and

SS ss;
auto ss2 = ss;

If your main were

void main()
{
SS ss;
foreach( it; ss ) { writeln(it); }
}

then it would not compile.

foreach(e; range) {...}

basically gets lowered to

for(auto __r = range; !__r.empty; __r.popFront())
{
auto e = __r.front;
...
}

So,

foreach( it; SS() ) { writeln(it); }

would become

for(auto __r = SS(); !__r.empty; __r.popFront())
{
auto it = __r.front;
writeln(it);
}

whereas

SS ss;
foreach( it; ss ) { writeln(it); }

would become

SS ss;
for(auto __r = ss; !__r.empty; __r.popFront())
{
auto it = __r.front;
writeln(it);
}

- Jonathan M Davis





Re: Difference between range `save` and copy constructor

2020-02-16 Thread uranuz via Digitalmars-d-learn
On Sunday, 16 February 2020 at 12:38:51 UTC, Jonathan M Davis 
wrote:
On Sunday, February 16, 2020 3:41:31 AM MST uranuz via 
Digitalmars-d-learn wrote:

I have reread presentation:
http://dconf.org/2015/talks/davis.pdf
We declare that `pure` input range cannot be `unpoped` and we
can't return to the previous position of it later at the time. 
So

logically there is no sence of copying input range at all. So
every Phobos algorithm that declares that it's is working with
InputRange must be tested for working with range with disabled
A range that can't be copied is basically useless. Not only do 
almost all range-based algorithms take their argumenst by value 
(and thus copy them), but foreach copies any range that it's 
given, meaning that if a range isn't copyable, you can't even 
use it with foreach. And since many range-based algorithms 
function by wrapping one range with another, the ability to 
copy ranges is fundamental to most range-based code.

This is working fine with disabled postblit...
import std;

struct SS
{
@disable this(this); // Disabled copy

bool _empty = false;

bool empty() @property {
return _empty;
}

void popFront() {
   _empty = true;
}

int front() @property { return 10; }
}


void main()
{
foreach( it; SS() ) { writeln(it); }
}

Am I missing something?


Re: Difference between range `save` and copy constructor

2020-02-16 Thread uranuz via Digitalmars-d-learn
In general for value-semantics and ref-semantics the different 
code is actually needed. But generic algorithm try to pretend 
that the logic is the same. But it's not true. But in wide subset 
of trivial algorithm it's true. So it's incorrectly interpolated 
that it's true for every case. The very bad thing if range is 
passed by value it still can have value or reference semantic. 
And algorithm cannot say which is it actually. There is not such 
problemme for classes. So as I already said when passing ranges 
by ref in algorithms they behave predictible. And if I want 
algrorithm to operate on copy of algorithm then I can just create 
this copy before passing it to this algorithm. And again 
intention is more clear. But Phobos algorithms don't work like 
that. It's why I can't use them in some cases, because they are 
looking unpredictable for me.


Re: Difference between range `save` and copy constructor

2020-02-16 Thread uranuz via Digitalmars-d-learn
It's very bad. Because there seem that when I use range based 
algorithm I need to take two things into account. The first is 
how algrorithm is implemented. If it creates copies of range 
inside or pass it by reference. And the second is how the range 
is implemented if it has value or reference semantics. So every 
time I need to look into implementation and I can't rely on API 
description in most of the cases. In a lot of cases Phobos uses 
value semantics. But there are cases where I want the range 
actually be consumed, but it's not. And the other problemme is 
when algorithm expects range to have value semantics, but it's 
not. So it's a buggy mess that it's hard to think about. In 
trivial cases this is working although. But in more complex cases 
it's simplier to implement some algorithms by own hands so that 
it would work as I expect it myself rather that thinking about 
all these value-ref-range mess. But still can't say that I 
implement it correctly, because range specification actually 
sucks as yo say.

It's just horrible


Re: Difference between range `save` and copy constructor

2020-02-16 Thread Jonathan M Davis via Digitalmars-d-learn
On Sunday, February 16, 2020 3:41:31 AM MST uranuz via Digitalmars-d-learn 
wrote:
> I have reread presentation:
> http://dconf.org/2015/talks/davis.pdf
> We declare that `pure` input range cannot be `unpoped` and we
> can't return to the previous position of it later at the time. So
> logically there is no sence of copying input range at all. So
> every Phobos algorithm that declares that it's is working with
> InputRange must be tested for working with range with disabled
> copy constructor and postblit. And if it is not it means that
> this algroithm actually requires a forward range and there we
> missing `save` calls?
> Because as it was written in this presentation a range copy is
> undefined (without call to save). So it's illegal to create copy
> of range in Phobos algorithms without `save`?
> So we need a test for every algorithm that it is working with
> range with disabled copy constructor and postblit if we declare
> that we only use `save` for range copy?

A range that can't be copied is basically useless. Not only do almost all
range-based algorithms take their argumenst by value (and thus copy them),
but foreach copies any range that it's given, meaning that if a range isn't
copyable, you can't even use it with foreach. And since many range-based
algorithms function by wrapping one range with another, the ability to copy
ranges is fundamental to most range-based code.

That being said, the semantics of copying a range are not actually defined
by the range API. Whether iterating over a copy affects the original depends
on how a range was implemented. e.g. In code such as

void foo(R)(R r)
if(isInputRange!R)
{
r.popFront();
}

foo(range);

whether the range in the original range in the calling code is affected by
the element being popped from the copy inside of foo is implementation
dependent. If it's a class or a struct that's a full-on reference type, then
mutating the copy does affect the original, whereas if copying a range is
equivalent to save, then mutating the copy has no effect on the original.
And with pseudo-reference types, it's even worse, because you could end up
_partially_ mutating the original by mutating the copy, meaning that you can
get some pretty serious bugs if you attempt to use a range after it's been
copied.

This means that in practice, in generic code, you can never use a range once
it's been copied unless you overwrite it with a new value. Passing a range
to a function or using it with foreach basically means that you should not
continue to use that range, and if you want to be able to continue to use
it, you need to call save and pass that copy to the function or foreach
instead of passing the range directly to a function or foreach.

In order to fix it so that you can rely on the semantics of using a range
after it's been copied, we'd have to rework the range API and make it so
that the semantics of copying a range were well-defined, and that gets into
a huge discussion on its own.

As things stand, if you want to test range-based code to ensure that it
works correctly (including calling save correctly), you have to test it with
a variety of different range types, including both ranges where copying is
equivalent to calling save and ranges which are reference types so that
copying them simply results in another reference to the same data such that
iterating one copy iterates all copies.

- Jonathan M Davis





Re: Difference between range `save` and copy constructor

2020-02-16 Thread uranuz via Digitalmars-d-learn

I have reread presentation:
http://dconf.org/2015/talks/davis.pdf
We declare that `pure` input range cannot be `unpoped` and we 
can't return to the previous position of it later at the time. So 
logically there is no sence of copying input range at all. So 
every Phobos algorithm that declares that it's is working with 
InputRange must be tested for working with range with disabled 
copy constructor and postblit. And if it is not it means that 
this algroithm actually requires a forward range and there we 
missing `save` calls?
Because as it was written in this presentation a range copy is 
undefined (without call to save). So it's illegal to create copy 
of range in Phobos algorithms without `save`?
So we need a test for every algorithm that it is working with 
range with disabled copy constructor and postblit if we declare 
that we only use `save` for range copy?


Re: Difference between range `save` and copy constructor

2020-02-16 Thread uranuz via Digitalmars-d-learn
Also I see the problemme that someone can think that it creates 
an input range, because he doesn't provide `save` method, but 
actually it creates forward range unexpectedly, because it is 
copyable. And it makes what is actually happening in code more 
difficult. Some algrorithm can take ranges by value, but others 
take them by reference. So result can be completely different. In 
first case range is being consumed, but in another in is not. 
Personally I prefer to take range by reference in all of my 
algrorithms except cases where I is always a class (because it's 
a reference already). But I still don't know what is the right 
way. There are no official guidelines about it. So every time 
it's a problemme. Although it looks like that range is a simple 
concept, but it's actually not.


Re: Difference between range `save` and copy constructor

2020-02-16 Thread uranuz via Digitalmars-d-learn
Actually, as I understand it, the main reason that save was 
introduced was so that classes could be forward ranges


I have use of ranges as a classes in my code that rely on classes 
and polymorthism, but it's usually an InputRange that implements 
Phobos interface:

https://dlang.org/phobos/std_range_interfaces.html#.InputRange

I have virtual opSlice operator that returns InputRange. And 
sometimes implementation of range is very different. So it's 
difficult to write one range as a struct. I have a pattern in my 
code that looks like the following:


interface IContainer
{
   InputRange opSlice();
}

class MyContainer1: IContainer
{
   class Range1: InputRange {
  //... one implementation
   }
   override InputRange opSlice() {
   return new Range1(this);
   }
}

class MyContainer2: IContainer
{
   class Range2: InputRange {
  //... another implementation
   }
   override InputRange opSlice() {
   return new Range2(this);
   }
}

In this example I need a range to be a class, but not a struct.

Another problemme is that `copy contructor` is defined only for 
structs, but not classes. For the class that uses another class 
instance of the `same` type to initialize from it would be a 
regular constructor with parameter.
A copy constructor in struct semantics requires that the source 
would be actually `the same` type. But for classes source could 
be instance of another class that is inherited from current 
class. And we cannot prove statically that it's actually the same 
type.
And also if we talk about range interface constructor cannot be a 
part of it. So we cannot add `copy contructor` (if we would have 
it for class) to interface and check for it's presence in generic 
code. So here we have this workaround with `save` method...
I don't like that primitive concept has two ways to do the same 
thing. And it's unclear what is the primary way of doing this 
(copy constructor or save). It introduce the situation when half 
of the code would require range being copyable, but another part 
would require it to to have a save method. Not the situation is 
that there are a lot of algorothms in Phobos that are not working 
with ranges that have disabled postblit, but have `save` method 
that could be used to make a copy.

Still I want to be able to create ranges as classes...


Re: Difference between range `save` and copy constructor

2020-02-15 Thread Steven Schveighoffer via Digitalmars-d-learn

On 2/15/20 9:45 AM, Jonathan M Davis wrote:

On Saturday, February 15, 2020 7:34:42 AM MST Steven Schveighoffer via
Digitalmars-d-learn wrote:

On 2/15/20 5:53 AM, uranuz wrote:

I am interested in current circumstances when we have new copy
constructor feature what is the purpose of having range `save`
primitive? For me they look like doing basicaly the same thing. And when
looking in some source code of `range` module the most common thing that
`save` does is that it use constructor typeof(this) to create a new
instance and use `save` on the source range:
https://github.com/dlang/phobos/blob/v2.090.1/std/range/package.d

So what is conceptual difference between `save` and copy contructor of
range?


Nothing. IMO, any time you are doing anything in save other than `return
this;`, you shouldn't have implemented it.

The original impetus for the save requirement was so that forward ranges
could have a tangible checkable thing that allows introspection (does
the range have a save method?).

I'm not entirely sure if disabled postblit was even available at the time.

The correct way to do it would be to treat ranges that can be copied
(regardless of whether they have a copy constructor) as forward ranges,
and treat ones that cannot be copied as input ranges.

But it's hard to redo ranges like this with all existing code out there.


Actually, as I understand it, the main reason that save was introduced was
so that classes could be forward ranges. While it would be possible to use
the postblit constructor or copy constructor with structs, that obviously
won't work for classes - hence when save is required.


I remember the discussions as being about how an actual implementation 
detail was required, not just a mark. I remember a suggestion for just 
putting an enum isForward member in the range being rejected because of 
this.


Except people don't call save. They just copy, and it works for nearly 
all forward ranges in existence.


And a class allocating a new class for saving a forward range is a 
mislabeled "cheap" operation IMO.



Personally, I think that we'd be better of simply requiring that forward
rangse be copyable and force classes that want to be forward ranges to be
wrapped by structs, but that would require reworking the range API, and it's
far from a trivial change.


Yep.


In practice though, classes should almost never be used as forward ranges,
because calling save on them would requires allocating a now object, and
that gets expensive fast. As part of testing dxml, I tested it with forward
ranges that were classes in order to make sure that they were handled
correctly, and their performance was absolutely terrible in comparison to
ranges that were structs or strings.


Not surprised ;)

-Steve


Re: Difference between range `save` and copy constructor

2020-02-15 Thread Jonathan M Davis via Digitalmars-d-learn
On Saturday, February 15, 2020 7:34:42 AM MST Steven Schveighoffer via 
Digitalmars-d-learn wrote:
> On 2/15/20 5:53 AM, uranuz wrote:
> > I am interested in current circumstances when we have new copy
> > constructor feature what is the purpose of having range `save`
> > primitive? For me they look like doing basicaly the same thing. And when
> > looking in some source code of `range` module the most common thing that
> > `save` does is that it use constructor typeof(this) to create a new
> > instance and use `save` on the source range:
> > https://github.com/dlang/phobos/blob/v2.090.1/std/range/package.d
> >
> > So what is conceptual difference between `save` and copy contructor of
> > range?
>
> Nothing. IMO, any time you are doing anything in save other than `return
> this;`, you shouldn't have implemented it.
>
> The original impetus for the save requirement was so that forward ranges
> could have a tangible checkable thing that allows introspection (does
> the range have a save method?).
>
> I'm not entirely sure if disabled postblit was even available at the time.
>
> The correct way to do it would be to treat ranges that can be copied
> (regardless of whether they have a copy constructor) as forward ranges,
> and treat ones that cannot be copied as input ranges.
>
> But it's hard to redo ranges like this with all existing code out there.

Actually, as I understand it, the main reason that save was introduced was
so that classes could be forward ranges. While it would be possible to use
the postblit constructor or copy constructor with structs, that obviously
won't work for classes - hence when save is required.

Personally, I think that we'd be better of simply requiring that forward
rangse be copyable and force classes that want to be forward ranges to be
wrapped by structs, but that would require reworking the range API, and it's
far from a trivial change.

In practice though, classes should almost never be used as forward ranges,
because calling save on them would requires allocating a now object, and
that gets expensive fast. As part of testing dxml, I tested it with forward
ranges that were classes in order to make sure that they were handled
correctly, and their performance was absolutely terrible in comparison to
ranges that were structs or strings.

- Jonathan M Davis





Re: Difference between range `save` and copy constructor

2020-02-15 Thread Steven Schveighoffer via Digitalmars-d-learn

On 2/15/20 5:53 AM, uranuz wrote:
I am interested in current circumstances when we have new copy 
constructor feature what is the purpose of having range `save` 
primitive? For me they look like doing basicaly the same thing. And when 
looking in some source code of `range` module the most common thing that 
`save` does is that it use constructor typeof(this) to create a new 
instance and use `save` on the source range:

https://github.com/dlang/phobos/blob/v2.090.1/std/range/package.d

So what is conceptual difference between `save` and copy contructor of 
range?


Nothing. IMO, any time you are doing anything in save other than `return 
this;`, you shouldn't have implemented it.


The original impetus for the save requirement was so that forward ranges 
could have a tangible checkable thing that allows introspection (does 
the range have a save method?).


I'm not entirely sure if disabled postblit was even available at the time.

The correct way to do it would be to treat ranges that can be copied 
(regardless of whether they have a copy constructor) as forward ranges, 
and treat ones that cannot be copied as input ranges.


But it's hard to redo ranges like this with all existing code out there.

-Steve


Re: Difference between template and mixin template

2019-10-10 Thread Just Dave via Digitalmars-d-learn

On Thursday, 10 October 2019 at 15:56:36 UTC, Just Dave wrote:
I'm trying to get my head around mixing templates. I'm using it 
as kind of a replacement for class inheritance as it seems to 
fit better composition over inheritance. So I do something like:


mixin template NumberTemplate()
{
private:
int number = 0;
public:
int getNumber(int number)
{
return number;
}
}

interface INumber
{
getNumber(int number);
}

class Number : INumber
{
template NumberTemplate;
};

So two questions:

a) Is this correct usage?

b) It compiles if I just do:

template NumberTemplate()
{
private:
int number = 0;
public:
int getNumber(int number)
{
return number;
}
}

what is the difference between template and mixin template?


Sorry I messed up the above code example the following should 
look like:


class Number : INumber
{
mixin NumberTemplate;
};


Re: Difference between slice[] and slice

2019-09-25 Thread ag0aep6g via Digitalmars-d-learn

On 25.09.19 22:36, WhatMeWorry wrote:

On Wednesday, 25 September 2019 at 19:25:06 UTC, Ali Çehreli wrote:

On 09/25/2019 12:06 PM, WhatMeWorry wrote:

[...]

> In short, is there anytime that one would want to use
"slice[] =
> something" syntax?I

That changes element values.


Ok.  But which element(s)?


All of them. For example, `slice[] = 42;` sets all elements to 42. And 
`slice[] = another_slice[];` replaces all elements of `slice` with 
copies of `another_slice`'s elements.



  In my specific case, I was using []. Is

waste[] = waste[0..$-1];

even semantically meaningful?  Because the LDC compiler had no problem 
compiling it.


It's equivalent to this:


waste[0] = waste[0..$-1][0];
waste[1] = waste[0..$-1][1];
...
waste[waste.length - 2] = waste[0..$-1][waste.length - 2];
waste[waste.length - 1] = waste[0..$-1][waste.length - 1];


So it basically does nothing. It just copies `waste`'s elements over 
themselves.


Except that the last line makes an out-of-bounds access. That's an error 
that may be detected during compilation or at run time. Or if you're 
telling the compiler to optimize too aggressively, it might go unnoticed.


Re: Difference between slice[] and slice

2019-09-25 Thread Paul Backus via Digitalmars-d-learn
On Wednesday, 25 September 2019 at 20:36:47 UTC, WhatMeWorry 
wrote:
Ok.  But which element(s)?  In my specific case, I was using 
[]. Is


waste[] = waste[0..$-1];

even semantically meaningful?  Because the LDC compiler had no 
problem compiling it.


`waste[]` is just shorthand for `waste[0..$]`. Assigning to a 
slice means copying the contents of another array into the array 
that slice refers to. If the lengths of the source and 
destination don't match, you get an error. Since `waste[0..$]` 
and `waste[0..$-1]` can never have the same length, you will 
always get an error if you try to assign one to the other.


Source: https://dlang.org/spec/arrays.html#array-copying


Re: Difference between slice[] and slice

2019-09-25 Thread WhatMeWorry via Digitalmars-d-learn
On Wednesday, 25 September 2019 at 19:25:06 UTC, Ali Çehreli 
wrote:

On 09/25/2019 12:06 PM, WhatMeWorry wrote:

> I was
> assuming that [] meant "the entirety" of the array.

Assuming we're talking about D slices, Yes. (It could be a 
user-defined type with surprisingly different semantics.)


> In short, is there anytime that one would want to use
"slice[] =
> something" syntax?I

That changes element values.


Ok.  But which element(s)?  In my specific case, I was using []. 
Is


waste[] = waste[0..$-1];

even semantically meaningful?  Because the LDC compiler had no 
problem compiling it.





> //waste[] = waste[0..$-1]; // object.Error@(0): Array lengths
don't
> match for copy: 0 != 1
>
>  waste = waste[0..$-1]; // works

That makes slice refer to a different set of elements. In that 
example, the slice does not include the last element anymore.


Ali





Re: Difference between slice[] and slice

2019-09-25 Thread Ali Çehreli via Digitalmars-d-learn

On 09/25/2019 12:06 PM, WhatMeWorry wrote:

> I was
> assuming that [] meant "the entirety" of the array.

Assuming we're talking about D slices, Yes. (It could be a user-defined 
type with surprisingly different semantics.)


> In short, is there anytime that one would want to use "slice[] =
> something" syntax?I

That changes element values.

> //waste[] = waste[0..$-1]; // object.Error@(0): Array lengths don't
> match for copy: 0 != 1
>
>  waste = waste[0..$-1]; // works

That makes slice refer to a different set of elements. In that example, 
the slice does not include the last element anymore.


Ali



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



Re: Difference between dstring and string format specifiers support. Bug?

2016-11-09 Thread Ali Çehreli via Digitalmars-d-learn

On 11/09/2016 01:20 AM, Ali Çehreli wrote:

> arrayPtrDiff() is at the bottom of the same file but works correctly
> only for char strings:
>
>   https://github.com/dlang/phobos/blob/master/std/format.d#L6573

What I meant is, using arrayPtrDiff() is correct only for char strings. 
Otherwise, arrayPtrDiff() is working properly.


Ali



Re: Difference between dstring and string format specifiers support. Bug?

2016-11-09 Thread Ali Çehreli via Digitalmars-d-learn

On 11/09/2016 12:21 AM, Vadim Lopatin wrote:

Looks like bug.
dchar[] and wchar[] format strings support less specifiers than char[]

import std.format;
string test1 = "%02d".format(1); // works
assert(test1 == "01");
dstring test2 = "%d"d.format(1); // works
assert(test2 == "1"d);
wstring test3 = "%02d"w.format(1); // fails
assert(test3 == "01"w);
dstring test4 = "%02d"d.format(1); // fails
assert(test4 == "01"d);



It's a bug that std.format uses arrayPtrDiff() here:

  https://github.com/dlang/phobos/blob/master/std/format.d#L993

arrayPtrDiff() is at the bottom of the same file but works correctly 
only for char strings:


  https://github.com/dlang/phobos/blob/master/std/format.d#L6573

Please report it.

Ali



Re: Difference between dstring and string format specifiers support. Bug?

2016-11-09 Thread Vadim Lopatin via Digitalmars-d-learn
On Wednesday, 9 November 2016 at 08:21:53 UTC, Vadim Lopatin 
wrote:

Looks like bug.
dchar[] and wchar[] format strings support less specifiers than 
char[]


import std.format;
string test1 = "%02d".format(1); // works
assert(test1 == "01");
dstring test2 = "%d"d.format(1); // works
assert(test2 == "1"d);
wstring test3 = "%02d"w.format(1); // fails
assert(test3 == "01"w);
dstring test4 = "%02d"d.format(1); // fails
assert(test4 == "01"d);


dmd 2.072.0



Re: Difference between toLower() and asLowerCase() for strings?

2016-01-24 Thread Adam D. Ruppe via Digitalmars-d-learn

On Sunday, 24 January 2016 at 20:56:20 UTC, Jon D wrote:
I'm trying to identify the preferred ways to lower case a 
string. In std.uni there are two functions that return the 
lower case form of a string: toLower() and asLowerCase(). There 
is also toLowerInPlace().


toLower will allocate a new string, leaving the original 
untouched.


toLowerInPlace will modify the existing string.

asLowerCase will returned the modified data as you iterate over 
it, but will not actually allocate the new string.



toLower is convenient if you need to store a copy of the string 
somewhere or pass it to a function that expects an existing 
string, but allocating the new one means it is the slowest of the 
three.


toLowerInPlace is only usable if your buffer is writable, which 
many strings aren't, and might still allocate once. It is a 
middle ground for use in a relatively rare case, but if you are 
building a string and need to store it somewhere, this is a 
decent choice.


asLowerCase is the only one that will never actually build a new 
string, and thus typically gives best performance, but at the 
cost of a little bit of lesser convenience. If you are just going 
to loop over it though (including passing it to further 
transforming algorithms), use this! Or if you want to manage the 
allocation of the new string yourself, you can use this too.





As a general rule, the asLowerCase (etc.) version should be your 
first go since it is the most efficient. But the others are 
around for convenience in cases where you need a new string built 
anyway.




Re: Difference between toLower() and asLowerCase() for strings?

2016-01-24 Thread Jon D via Digitalmars-d-learn

On Sunday, 24 January 2016 at 21:04:46 UTC, Adam D. Ruppe wrote:

On Sunday, 24 January 2016 at 20:56:20 UTC, Jon D wrote:
I'm trying to identify the preferred ways to lower case a 
string. In std.uni there are two functions that return the 
lower case form of a string: toLower() and asLowerCase(). 
There is also toLowerInPlace().


toLower will allocate a new string, leaving the original 
untouched.


toLowerInPlace will modify the existing string.

asLowerCase will returned the modified data as you iterate over 
it, but will not actually allocate the new string.


[snip...]

As a general rule, the asLowerCase (etc.) version should be 
your first go since it is the most efficient. But the others 
are around for convenience in cases where you need a new string 
built anyway.


Great explanation, thank you!


Re: Difference between back (`) and double (") quoted strings

2015-09-18 Thread BBasile via Digitalmars-d-learn
On Saturday, 12 September 2015 at 08:13:33 UTC, Bahman Movaqar 
wrote:
Is there any or they are just simply syntactically equivalent? 
Are there any official docs on this?


it's like a raw string (prefixed with a r) so there is escaped 
char:


r"\": correct token for a string, terminal " is not escaped
`\`: correct token for a string, terminal ` is not escaped
"\": invalid token for a string, " is escaped

so it's usefull on Windows for example, if a litteral string 
contains a path, instead of


"C:\\folder\\file"

you can type

`C:\folder\file`



Re: Difference between back (`) and double (") quoted strings

2015-09-18 Thread BBasile via Digitalmars-d-learn

On Friday, 18 September 2015 at 09:34:38 UTC, BBasile wrote:
On Saturday, 12 September 2015 at 08:13:33 UTC, Bahman Movaqar 
wrote:
Is there any or they are just simply syntactically equivalent? 
Are there any official docs on this?


it's like a raw string (prefixed with a r) so there is escaped 
char:


there **NO** escaped chars...godamnit typo.




Re: Difference between back (`) and double (") quoted strings

2015-09-18 Thread BBasile via Digitalmars-d-learn

On Friday, 18 September 2015 at 09:35:53 UTC, BBasile wrote:

On Friday, 18 September 2015 at 09:34:38 UTC, BBasile wrote:
On Saturday, 12 September 2015 at 08:13:33 UTC, Bahman Movaqar 
wrote:
Is there any or they are just simply syntactically 
equivalent? Are there any official docs on this?


it's like a raw string (prefixed with a r) so there is escaped 
char:


there **NO** escaped chars...godamnit typo.


12 September 2015, '6 days ago',

mh haven't seen this initially. That's embarassing.


Re: Difference between back (`) and double (") quoted strings

2015-09-18 Thread Ali Çehreli via Digitalmars-d-learn

On 09/12/2015 01:13 AM, Bahman Movaqar wrote:

Is there any or they are just simply syntactically equivalent?
Are there any official docs on this?



I realized that there was no index entry for back tick in my book. I've 
just added that and provided an Index section for the web version of the 
book. Click "Index (beta)" below to see a currently-ugly but hopefully 
useful Index section:


  http://ddili.org/ders/d.en/

Ali



Re: Difference between back (`) and double (") quoted strings

2015-09-12 Thread NX via Digitalmars-d-learn
On Saturday, 12 September 2015 at 08:13:33 UTC, Bahman Movaqar 
wrote:
Is there any or they are just simply syntactically equivalent? 
Are there any official docs on this?


What if I told you, you should search the official reference 
before asking such things in the forum?


http://dlang.org/lex.html#WysiwygString

Wysiwyg: What you see is what you get

  writeln(`\asd"fg"hj
hmph'`);


\asd"fg"hj
haha'



Re: Difference between back (`) and double (") quoted strings

2015-09-12 Thread Bahman Movaqar via Digitalmars-d-learn
On 09/12/2015 12:52 PM, NX wrote:
> What if I told you, you should search the official reference before
> asking such things in the forum?

I did search the net for terms such as "d lang back quoted string" or "d
lang multi line string" or "d lang string interpolation" before asking here.
However the term "Wysiwyg string" didn't occur to my mind and from what
I could gather from the net and the test programs I wrote, I couldn't
determine the difference between `-string and "=string.  Hence
I decided to ask people here.

> http://dlang.org/lex.html#WysiwygString

Thanks for the help.


-- 
Bahman Movaqar

http://BahmanM.com - https://twitter.com/bahman__m

https://github.com/bahmanm - https://gist.github.com/bahmanm

PGP Key ID: 0x6AB5BD68 (keyserver2.pgp.com)


Re: Difference between back (`) and double (") quoted strings

2015-09-12 Thread Adam D. Ruppe via Digitalmars-d-learn

On Saturday, 12 September 2015 at 08:22:03 UTC, NX wrote:
What if I told you, you should search the official reference 
before asking such things in the forum?


Searching is kinda hard, so I encourage people to ask if 
something doesn't come up quickly. And then we need to be sure to 
always answer because their question might be the thing that 
comes up on some future user's search, and if they see "google 
it", their reaction might be "what the &^&*%^ do you think 
brought me here?!?!?!"


(at least that's my reaction!)


Re: Difference between concatenation and appendation

2015-01-25 Thread WhatMeWorry via Digitalmars-d-learn

On Monday, 26 January 2015 at 01:57:04 UTC, bearophile wrote:

Laeeth Isharc:

I think concatenation and append are used as synonyms (the 
same meaning is meant).  a~=b or a=a~b


a=a~b always allocates a new array, while a~=b sometimes 
re-allocates in place.


Bye,
bearophile


Perfect! Thank you.  I'll scribble your quote you in the margin 
of my TDPL book.







Re: Difference between concatenation and appendation

2015-01-25 Thread Jonathan M Davis via Digitalmars-d-learn
On Monday, January 26, 2015 01:17:15 WhatMeWorry via Digitalmars-d-learn wrote:
 Ok, I just made up that word. But what is the difference between
 appending and concatenating?  Page 100 of TPDL says The result
 of the concatenation is a new array... and the section on
 appending talks about possibly needing expansion and reallocation
 of memory.

 But I still don't feel like I have a grasp on the subtleties
 between them. Can someone give a short and sweet rule of thumb?

 It might be so obvious that I'll regret posting this.

~ is the concatenation operator. ~= is the append operator. ~ takes two
objects (most typically arrays, but user-defined types can define the same
operators) and returns a new one which contains the data from the first one
followed by the data from the second without affecting either object. ~=
takes two objects and adds the data from the second one to the end of the
first one (without affecting the second object). ~ is forced to allocate,
because it's creating a new object. Whether ~= allocates depends on the
data involved and the implementation, though ideally, it would avoid
allocation if it can.

In the case of arrays rather than user-defined objects, ~= is managed by the
GC. So, whether ~= allocates or not depends on whether there's room/capacity
in the block of memory that the array is a slice of after the array. If
there's enough room, then it will just increase the size of the array, and
put the new data in that memory, but if there isn't enough room (e.g.
because the memory block doesn't have enough room or because another array
refers to a pointer farther in the block of memory than the one being
appended to), then a new block of memory is allocated, the data is then
assigned to there, and the array is changed to be a slice of that memory
block. For user-defined types, it depends entirely on how ~= is implemented,
but it's probably going to either be doing something similar or be forced to
reallocate every time.

In any case, the main difference between ~ and ~= is that ~ creates a new
array or object _every_ time, and ~= mutates the first argument and will
generally only result in an allocation if it has to (particularly if you're
dealing with arrays).

I'd sugges that you read this article on D arrays:

http://dlang.org/d-array-article.html

It mixes up its terminology a bit with regards to dynamic arrays (the
language considers int[] to be a dynamic array, whereas the article refers
to the GC-allocated block of memory that the array refers to as being the
dynamic array), but it should definitely clarify a lot about D arrays for
you.

- Jonathan M Davis



Re: Difference between concatenation and appendation

2015-01-25 Thread Laeeth Isharc via Digitalmars-d-learn

On Monday, 26 January 2015 at 01:17:17 UTC, WhatMeWorry wrote:
Ok, I just made up that word. But what is the difference 
between appending and concatenating?  Page 100 of TPDL says 
The result of the concatenation is a new array... and the 
section on appending talks about possibly needing expansion and 
reallocation of memory.


But I still don't feel like I have a grasp on the subtleties 
between them. Can someone give a short and sweet rule of 
thumb?


It might be so obvious that I'll regret posting this.

Thanks.



At the risk of the blind leading the blind (I am no expert), I 
think concatenation and append are used as synonyms (the same 
meaning is meant).  a~=b or a=a~b


If there isn't enough space then the whole array is reallocated.  
You can see this/change this property by reading capacity or 
calling reserve.


If you want to do lots of appends / concatenates then use 
appender in std.array which is faster and more efficient.


Re: Difference between concatenation and appendation

2015-01-25 Thread Laeeth Isharc via Digitalmars-d-learn

On Monday, 26 January 2015 at 01:57:04 UTC, bearophile wrote:

Laeeth Isharc:

I think concatenation and append are used as synonyms (the 
same meaning is meant).  a~=b or a=a~b


a=a~b always allocates a new array, while a~=b sometimes 
re-allocates in place.


Bye,
bearophile


Thanks. That makes sense.


Re: Difference between concatenation and appendation

2015-01-25 Thread 岩倉 澪

On Monday, 26 January 2015 at 01:17:17 UTC, WhatMeWorry wrote:
Ok, I just made up that word. But what is the difference 
between appending and concatenating?  Page 100 of TPDL says 
The result of the concatenation is a new array... and the 
section on appending talks about possibly needing expansion and 
reallocation of memory.


But I still don't feel like I have a grasp on the subtleties 
between them. Can someone give a short and sweet rule of 
thumb?


It might be so obvious that I'll regret posting this.

Thanks.


I'm no expert, so take what I say with a grain of salt. That 
said, here is my understanding:


When you append to an array with ~=, it attempts to reallocate 
the array in-place, meaning it allocates on top of the already 
used space, but grabs some more space past the end of the array. 
If there isn't enough space after the array then obviously it 
can't do that, so it allocates memory somewhere else that it can 
fit and then it copies the contents of the array to the new 
location. If you were to do myArray = myArray ~ moreStuff; I 
assume this is no different from ~=. Conceptually ~= is just 
syntactic sugar in the same way that += or -= is, you are just 
doing a concatenation and then updating the array to point to the 
new result. The fact that it can reallocate in place if there is 
enough space is just like an optimization, in my mind.


Re: Difference between concatenation and appendation

2015-01-25 Thread bearophile via Digitalmars-d-learn

Laeeth Isharc:

I think concatenation and append are used as synonyms (the same 
meaning is meant).  a~=b or a=a~b


a=a~b always allocates a new array, while a~=b sometimes 
re-allocates in place.


Bye,
bearophile


Re: Difference between is and ==

2014-02-04 Thread Martijn Pot

On Tuesday, 4 February 2014 at 08:08:30 UTC, Suliman wrote:

What difference between
if ((x = stdin.readln().chomp) is q)
and
if ((x = stdin.readln().chomp) == q)

?


My interpretation of tdpl p57:

'is' compares for alias equality for arrays and classes.
Otherwise they are the same.


Re: Difference between is and ==

2014-02-04 Thread Suliman

My interpretation of tdpl p57:

'is' compares for alias equality for arrays and classes.
Otherwise they are the same.


So should next code have same behavior if I will use is instead 
of ==


import std.stdio;
import std.string;

void main()
{
getchar();
}

void getchar()
{
string x;
if ((x = stdin.readln().chomp) == q)
writeln(it's is q);
else
writeln(Not q);
}

In case I am using is, I have never get first if expression is 
true.


Re: Difference between is and ==

2014-02-04 Thread Martijn Pot

On Tuesday, 4 February 2014 at 08:25:18 UTC, Suliman wrote:

My interpretation of tdpl p57:

'is' compares for alias equality for arrays and classes.
Otherwise they are the same.


So should next code have same behavior if I will use is instead 
of ==


import std.stdio;
import std.string;

void main()
{
getchar();
}

void getchar()
{
string x;
if ((x = stdin.readln().chomp) == q)
writeln(it's is q);
else
writeln(Not q);
}

In case I am using is, I have never get first if expression is 
true.


My guess is the following:
string is an immutable(char)[]. As string is an array, 'is' 
checks for alias equality. x is not an alias for the (unnamed?) 
string literal q.


Re: Difference between is and ==

2014-02-04 Thread bearophile

Suliman:


What difference between
if ((x = stdin.readln().chomp) is q)
and
if ((x = stdin.readln().chomp) == q)

?


is performs a raw comparison of just the values, and the value 
of a string is its ptr and length field. While == compares 
their contents. So you want to use == here because you are 
interested to see if x contains the char 'q', because while their 
lengths could be equal, their ptr is surely different.


Bye,
bearophile


Re: Difference between is and ==

2014-02-04 Thread Steven Schveighoffer

On Tue, 04 Feb 2014 03:08:28 -0500, Suliman everm...@live.ru wrote:


What difference between
if ((x = stdin.readln().chomp) is q)
and
if ((x = stdin.readln().chomp) == q)

?


The first compares the pointer of the arrays. The second compares the  
contents of the array. Both check length as well for equality.


In other words, the first will always be false (the ROM literal q will  
never have the same address as some heap block), the second will be true  
if the input was the string q.


More generally, 'is' should be a bitwise comparison of the variables. '=='  
should check for logical equality, whatever that means for the variable  
types.


-Steve


Re: Difference between DList and SList from garbage collector point of view

2013-02-25 Thread Alexandr Druzhinin

25.02.2013 3:59, monarch_dodra пишет:


I don't see any any calls to remove, so I'm not sure what the algorithm
is. Wouldn't patch just grow and grow and grow?

Regardless, the design of DList is currently flawed (but a pull is open
to fix it), in the sense that a DList is just a handle on a chain of
nodes.

The problem with this approach is that calls to things such as
removeFront() or removeFront(n) merelly reposition the first
pointer. However, the nodes are never actually un-linked. I'd say there
are good chances this is what you are seeing.

Seeing a DList doesn't have splice either, I'm unsure what to tell you
in regards to working around it.

I'd say once you are done with a list, you can try to dup it: This
will allocate *more*, but will allow the GC to collect everything that
was previously removed.

...Or just SList. It's less bugged.

See this:
http://forum.dlang.org/thread/gjhclwsuqyhrimdeo...@forum.dlang.org
After some research I think that this situation is due to several 
reasons set and DList isn't single cause.

patch is local var:
 class DataChunk {
uint source_id;
uint id;
 ...
 }

 class DataStorage {
 DList!DataChunk patch;
 (RedBlackTree!DataChunk)[uint] _container_map;

 ...

auto getPatch(uint source, long last) {

bool isNewer(DataChunk dc) {
if(dc.source_id == source  dc.id  last)
return true;
else
return false;   
}

Patch patch;
foreach(datachunk; find!isNewer(_container_map[source][])) {
patch.insertFront(datachunk);
}
}
}   
so it doesn't grow.




Re: Difference between DList and SList from garbage collector point of view

2013-02-24 Thread monarch_dodra
On Sunday, 24 February 2013 at 20:16:26 UTC, Alexandr Druzhinin 
wrote:
I used in my application DList (code is large and I couldn't 
reduce it) and the application allocates memory always. I can 
not realize why and don't know it now. But when I replaced 
DList by SList (and even dynamic array) memory leaks 
disappeared at all and all works as expected. I know it is hard 
to help me without code but what may be reason of this? May be 
I don't know some simple things I should and just misuse DList?


About code causing memory leaks - it is trivial loop:

class DataChunk {
...
}

DList!DataChunk patch;
(RedBlackTree!DataChunk)[uint] _container_map;

... 

foreach(datachunk; find!isNewer(_container_map[source][])) {
patch.insertFront(datachunk);
}

if I replace DList by SList all works fine - size of used 
memory is the same all the time. But with DList the application 
uses memory more and more.


I don't see any any calls to remove, so I'm not sure what the 
algorithm is. Wouldn't patch just grow and grow and grow?


Regardless, the design of DList is currently flawed (but a pull 
is open to fix it), in the sense that a DList is just a handle 
on a chain of nodes.


The problem with this approach is that calls to things such as 
removeFront() or removeFront(n) merelly reposition the 
first pointer. However, the nodes are never actually un-linked. 
I'd say there are good chances this is what you are seeing.


Seeing a DList doesn't have splice either, I'm unsure what to 
tell you in regards to working around it.


I'd say once you are done with a list, you can try to dup it: 
This will allocate *more*, but will allow the GC to collect 
everything that was previously removed.


...Or just SList. It's less bugged.

See this:
http://forum.dlang.org/thread/gjhclwsuqyhrimdeo...@forum.dlang.org


Re: Difference between stack-allocated class and struct

2011-05-03 Thread Sean Cavanaugh
Here is my prototype COM compile-time reflection based wrapper mixin 
(which I have abandoned in favor of alias this since it covers 95% of my 
use cases even though it isn't perfectly safe).  I am new at D so you 
have been warned, though this part of the language seems pretty 
straightforward enough.  It is possible the track down the argument 
names but takes some rather intricate parsing to do correctly (and the 
example someone linked me in another thread of mine chocked on const 
types due to parsing bugs).



http://snipt.org/xsu


The wrapped interface also needs to be a mixin so it can be created in 
the correct module, with visibility to all the types passed to the 
interface's methods.



So something like the following is going to fail miserably unless ComPtr 
is also made into a mixin and instantiated in the correct module.



struct ComPtr(T)
{
public:
T m_Pointer;
mixin(WrapComInterface!(T)(m_Pointer)
};




Re: Difference between stack-allocated class and struct

2011-05-02 Thread Jonathan M Davis
 What are the differences between class instantiated by scope and struct
 itself?
 Two, that comes to my mind are:
 - vtable existance (yep, struct with inheritation - that's what i like)
 - lol, i just forgot while writing this e-mail

First off, I would point out that scoped classes are going away (though 
std.typecons.scoped serves as a replacement).

Now, structs are value types and are meant to be on the stack. When you assign 
one to another, a copy is made. If the original is altered, it doesn't affect 
the copy, and if the original goes away, the copy is unaffected.

Classes are reference types and are meant to be on the heap. When you assign 
one to another, you're merely copying the reference. Both refer to the same 
object. No copy is made. So, when you alter one, you also alter the other. 
When one goes away, it doesn't affect the other, but if the underlying object 
went away, then they would both be screwed.

Normally, class objects don't go away until the garbage collector collects 
them, but if you use scope (or std.typecons.scoped), then the object is on the 
stack instead of the heap, and as soon as that scope goes away, so does the 
object, so if you have references to it elsewhere, they're invalid, but the 
program won't know that, and it'll try and use them anyway. It can lead to 
serious bugs. Scoped classes are inherently unsafe, which is why they're going 
away.

It's like when you return an address to a local variable:

int* foo()
{
int a = 7;

return a;
}

The pointer will be invalid, and you're going to have bugs. Now, the 
compiler's going to catch such a simple case as this, but what if you did 
something like this?

int* foo()
{
int a = 7;

return bar(a);
}

int* bar(int* b)
{
return b;
}

The compiler can't catch that. The same goes if you were to use a scoped class 
instead of an int. In general, scoped classes are a _bad_ idea and should not 
be used unless profiling has shown that they speed up critical code and you're 
_certain_ that you're using them in a manner which won't cause a reference to 
the class to escape the function and outlive the function call.

As for everything else structs are structs and classes are classes. All of the 
normal differences apply. That includes the fact that structs have no 
inheritance and no vtable while classes do have inheritance and do have a 
vtable. However, you pretty much lose polymorphism if you use a scoped class. 
You're guaranteeing that the class that you're using is _exactly_ that type 
and not a subclass of that type. This is because the object is put on the 
stack inside the function and the compiler must know its _exact_ size. It's 
exactly like what you get with classes on the stack in C++. Putting them on 
the stack loses any of the advantages of polymorhism and risks slicing ( 
http://en.wikipedia.org/wiki/Object_slicing ) when you assign a subclass 
object to a base class object.

So, if you're using a scoped class, you're _not_ getting the benefits of 
polymorphism. What you're doing is saying that you know that you have an 
object of a particular type - that _exact_ type - which you know is not going 
to need to exist once you exit that scope, and you want to increase the 
efficiency of that code, so you make it so that the object is created on the 
stack instead of the heap. And in so doing, you _must_ make sure that no 
reference to that object escapes - which often isn't easy if you have to pass 
that object to any other functions, and even if you verify that it's safe now, 
it might not be later.

Structs and classes are inherently different. Structs are value types and 
classes are reference types. All you're doing with a scoped class is forcing 
the object to be put on the stack instead of the heap, which doesn't really 
change anything for the class except for the fact that it must be of that 
_exact_ type (so no polymorphism), and you have to make sure that no 
references to it escape, or you could have serious bugs.

- Jonathan M Davis


Re: Difference between stack-allocated class and struct

2011-05-02 Thread Mariusz Gliwiński
Firstly, thanks for comprehensive answer and I'd like to excuse for my 
stupid mistakes, which are caused by learning a lot and not actually 
programming.


On date 2011-05-02 23:03, Jonathan M Davis wrote:

Classes are reference types and are meant to be on the heap.

Yeah, value vs reference semantics - that was the thing i forgot...

So, if you're using a scoped class, you're _not_ getting the benefits of
polymorphism.
I completely didn't think about, that stack size needs to be known 
already at time of compiling. You just probably saved me a lot of problems.



So, scoped classes can't be used for filling gap in struct inheritance.

I'll clarify myself:
All i would need is extending - without polymorphism.
Containment, can be solution for fields which doesn't annoys so much 
(although image in auto-generated documentation, just like it's with 
subclassing, would be nice).
Unfortunately, the worse case is about methods, which have to be 
manually forwarded to contained struct.


So, does someone sees any nice solution for method forwarding as 
described? Should i make use of some mixin's?


Thanks,
Mariusz Gliwiński


Re: Difference between stack-allocated class and struct

2011-05-02 Thread Jonathan M Davis
 Firstly, thanks for comprehensive answer and I'd like to excuse for my
 stupid mistakes, which are caused by learning a lot and not actually
 programming.
 
 On date 2011-05-02 23:03, Jonathan M Davis wrote:
  Classes are reference types and are meant to be on the heap.
 
 Yeah, value vs reference semantics - that was the thing i forgot...
 
  So, if you're using a scoped class, you're _not_ getting the benefits of
  polymorphism.
 
 I completely didn't think about, that stack size needs to be known
 already at time of compiling. You just probably saved me a lot of problems.
 
 
 So, scoped classes can't be used for filling gap in struct inheritance.
 
 I'll clarify myself:
 All i would need is extending - without polymorphism.
 Containment, can be solution for fields which doesn't annoys so much
 (although image in auto-generated documentation, just like it's with
 subclassing, would be nice).
 Unfortunately, the worse case is about methods, which have to be
 manually forwarded to contained struct.
 
 So, does someone sees any nice solution for method forwarding as
 described? Should i make use of some mixin's?

alias this is supposed to be one of the better solutions for dealing with the 
sort of problem that you're looking at. Unfortunately, it's highly buggy at 
the moment, so it's questionable as to whether it would work. And even if it 
works, you can currently only have one alias this per type, so if you need 
more than that, you'd need another solution (eventually, alias this should 
work just fine, and you should be able to have multiple of them per type, but 
not yet).

At the moment, you pretty much need to do manual forwarding. Now, with the 
clever use of compile-time reflection via __traits and/or std.traits along 
with template mixins or string mixins, you should be able to get the compiler 
to generate all of the forwarded functions for you, but you'd still have to 
write the code for generating the mixins, which could be somewhat tricky. If 
you get it right though, then it would generate all of the appropriate 
functions regardless of whether any are added to or removed from the type that 
you're forwarding function calls to.

- Jonathan M Davis


Re: Difference between stack-allocated class and struct

2011-05-02 Thread Piotr Szturmaj

Mariusz Gliwiński wrote:

I'll clarify myself:
All i would need is extending - without polymorphism.
Containment, can be solution for fields which doesn't annoys so much
(although image in auto-generated documentation, just like it's with
subclassing, would be nice).
Unfortunately, the worse case is about methods, which have to be
manually forwarded to contained struct.

So, does someone sees any nice solution for method forwarding as
described? Should i make use of some mixin's?


You can use 'alias this':

http://www.digitalmars.com/d/2.0/class.html#AliasThis