Re: opOpAssign of AA: defined behavior?

2020-06-23 Thread Eduard Staniloiu via Digitalmars-d-learn

On Tuesday, 23 June 2020 at 09:15:57 UTC, WebFreak001 wrote:

[...]

it will give me a range violation at runtime and not init it 
for me at all.


There is `aa.require("a", Foo.init) += 4;` now which solves 
this, but I would prefer having the small simple syntax well 
defined for all types instead of only primitives. Also I don't 
see anywhere in the specification that `require` must actually 
return a ref value, so I can't trust this either.


You make a very good case.

I think this would make a great bootcamp issue 
(https://issues.dlang.org/)


Cheers,
Edi



Re: Do I understand std.experimental.allocator composition correctly?

2019-08-27 Thread Eduard Staniloiu via Digitalmars-d-learn

On Monday, 26 August 2019 at 01:06:55 UTC, James Blachly wrote:
The documentation for std.experimental.allocator is a little 
dense and I wanted to make sure I am understanding composition 
correctly.


[...]


Yes, you are correct.

Edi


Re: Exercism, call for mentors

2019-08-21 Thread Eduard Staniloiu via Digitalmars-d-learn

On Tuesday, 20 August 2019 at 09:40:06 UTC, Björn Lindström wrote:

Hello,

I've recently decided to pick up D, and have started doing some 
exercises on
https://exercism.io/ (a non-profit programming exercise 
platform), which I think is an excellent way to pick up the 
basics in a new language.


While doing the exercises on my own is rewarding already, I 
would greatly appreciate if someone would want to pick up the 
mantle of mentor in D over there. Evidently someone liked the 
idea at one point enough to contribute D versions of a lot of 
the exercises, but based on progress of the queue, nobody is 
checking it frequently at the moment.


I've been doing some mentoring there myself, for Python and 
Bash, and I think it's quite fun, and I learn a lot that way. 
It forces me to regularly think hard about the basics, trying 
to give considered advice to beginners.


Anyway, if someone would be willing to give it a go, you can go 
to https://exercism.io/become-a-mentor and follow the 
instructions there.


Thanks,
Björn


This is a great idea. I didn't know about https://exercism.io/
I've got a lot on my plate in the following weeks, but I'll try to
make some time to mentor.

I hope others in the community will join as well.

Cheers,
Edi


Re: Why in Phobos is empty() sometimes const and sometimes not

2019-07-29 Thread Eduard Staniloiu via Digitalmars-d-learn

On Monday, 29 July 2019 at 17:32:58 UTC, Matt wrote:
I've noticed that for some ranges in Phobos empty is marked 
const (e.g. iota) but for other ranges (e.g. multiwayMerge) it 
is not const. Is there a reason why? Isn't empty guaranteed not 
to alter the data of the range and so should be const?


This is causing me considerable headaches as I try to write my 
own ranges that accept other ranges and have it all work for 
the general case. Any advice would be welcome.


You could use introspection (a static i) to check if the type 
defines a const/non-const version and write the appropriate empty 
declaration.


As for why it’s like this I’ll have to look at the code in 
Phobos, but I’m currently away from my pc (on the phone).


Cheers,
Edi


Building GDC with auto-generated header files

2019-07-29 Thread Eduard Staniloiu via Digitalmars-d-learn

Cheers, everybody

I'm working on this as part of my GSoC project [0].

I'm working on building gdc with the auto-generated `frontend.h` 
[1], but I'm having some issues


There are functions in dmd that don't have an `extern (C)` or 
`extern (C++)` but they are used by gdc (are exposed in `.h` 
files)


An example of such a function is `checkNonAssignmentArrayOp`[2] 
from `dmd/arrayop.d` which is can be found in 
`gcc/d/dmd/expression.h` [3]


How does the linker find the right match in dmd? Since the 
function is `extern (D)`, isn't it mangled differently than C++?


[0] - 
https://forum.dlang.org/thread/djurwumzfrrttvtdg...@forum.dlang.org

[1] - https://github.com/dlang/dmd/pull/9971
[2] - 
https://github.com/dlang/dmd/blob/master/src/dmd/arrayop.d#L85
[3] - 
https://github.com/gcc-mirror/gcc/blob/master/gcc/d/dmd/expression.h#L84


Zero length arrays in D

2019-02-18 Thread Eduard Staniloiu via Digitalmars-d-learn

Hello

According to the spec[0], D supports zero length arrays [1].

I have given this a shot at https://run.dlang.io/is/PwbPxJ

Attempting to use the zero-length array results in a compiler 
error


`a.contents[2]` -> Error: array index 2 is out of bounds 
(*a).contents[0 .. 0]


The way I've used around this error is "safely" break/trick the 
type system


```
int *p = a.contents.ptr;
int[] p_cont = p[0 .. n];
p_cont[2] = 10; // fine
```

Is this the intended way of working with zero length arrays?

Cheers,
Edi


[0] - https://dlang.org/spec/arrays.html#static-arrays, best 
practices pt 2
[1] - 
https://gcc.gnu.org/onlinedocs/gcc-4.7.4/gcc/Zero-Length.html


Re: Is it possible to modify shared struct array in a function.

2019-02-08 Thread Eduard Staniloiu via Digitalmars-d-learn

On Friday, 8 February 2019 at 06:55:15 UTC, Jerry wrote:

On Friday, 8 February 2019 at 04:51:08 UTC, Sudhi wrote:
On Friday, 8 February 2019 at 04:30:23 UTC, Arun 
Chandrasekaran wrote:

On Friday, 8 February 2019 at 04:13:39 UTC, Sudhi wrote:

[...]


Works fine for me with DMD64 D Compiler v2.083.1. 
https://run.dlang.io/is/RRM8GU



My example code was wrong. Below is the right one.

struct Company
{
string name;
string location;
}

struct Racks
{
int number;
int location;
}

struct Metadata
{
string name;
Company[] companies;
Racks[] racks;
}

struct Item
{
Metadata[] met;
int count;
}

shared (Item) item;

void main()
{
   updateMetadata();
}

void updateMetadata()
{
   Company company;
   company.name = "Hello";
   company.location = "Bangalore";
   item.met.companies ~= company;
   import std.stdio: writeln;
   writeln(item);
}

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


You have to cast away shared:

auto loc_item = cast(Item) item;
loc_item.met ~= m;
item = cast(shared) loc_item;

Just to be clear, this is not threadsafe and require a mutex if 
you do this other than as init in main.


You do not need to cast away shared. You had a couple of issues 
with your `updateMetadata()` function.


First of, `met` is an array, so you need to index it: your code 
`item.met.companies ~= company` becomes `item.met[0].companies ~= 
company`. This will compile, but throw a range error because you 
don't have any `Metadata` object in your `met` array.


I have typed below the revised form of your function

```
void updateMetadata()
{
   // create a Company instance. This must be shared
   shared Company company;
   company.name = "Hello";
   company.location = "Bangalore";

   // create a shared Metadata instance
   shared Metadata m;
   m.name = "m";

   // append m to the array of meta
   item.met ~= m;
   // append the company to the array of companies, for a given 
meta

   item.met[0].companies ~= company;

   import std.stdio: writeln;
   writeln(item);
}
```

The working version is at https://run.dlang.io/is/RvRKrU

Cheers,
Edi


Re: std.container.rbtree as Interval Tree?

2019-02-07 Thread Eduard Staniloiu via Digitalmars-d-learn

On Tuesday, 5 February 2019 at 19:12:43 UTC, James Blachly wrote:



However, even when allowing (pseudo)duplicates, this means the 
distinct intervals with same start but different end 
coordinates are not deterministically placed/sorted within the 
tree, because they are not sortable with the simple `this.start 
< other.start` less function.




I have updated the example with an `opCmp` implementation.
https://run.dlang.io/is/ailnsy

I believe this is what you are looking for.

Cheers,
Edi




Re: std.container.rbtree as Interval Tree?

2019-02-05 Thread Eduard Staniloiu via Digitalmars-d-learn

On Monday, 4 February 2019 at 22:54:01 UTC, James Blachly wrote:
I tried to implement an interval tree backed by 
std.container.rbtree today and fell flat.


A standard way to make an interval tree is to make an augmented 
tree; I supposed since rbtree was a generic container and 
because I could define opCmp, this should be a cinch. I ran 
into two problems.


First (minor problem), RedBlackTree considers a return value of 
0 from opCmp equivalent to "equals", which is discordant with 
the guidance given for opCmp.[1] This is a  minor pedantic 
point, since you cannot store un-orderable elements in the tree 
anyway.


More importantly, though, I cannot figure out how to implement 
an interval query function on the tree. Typically, the tree 
would have a "key" that is the left position of the interval 
and the augmented part of the tree would be that a second value 
-- a right, or end, position. My Elem == key type is a struct 
encapsulating both of these (start, end; plus some metadata).


For my Interval element type, I overloaded opCmp to take an 
integer, but unfortunately RedBlackTree's upperBound() and 
lowerBound() functions are defined in terms of "Elem" which is 
aliased to the contained element type, rather than a generic 
type.


Q1: Is there a simple or elegant way to do this without 
re-implementing RedBlackTree? I apologize if it is obvious and 
I am missing it. I suppose it may work if I rewrite Interval's 
opCmp to not consider the upper bound, and by creating a dummy 
interval to pass to upperBound and lowerBound, but that seems 
inelegant compared to passing an integer.


Q2: Would replacing "Elem" with a generic type "T" in the 
function signatures for upperBound, lowerBound, and various 
related fns like _firstGreater / _firstGreaterEqual solve this 
problem?


James

[1] https://dlang.org/spec/operatoroverloading.html#eqcmp ("For 
example ... x and y are disjoint sets, then neither x < y nor y 
< x holds, but that does not imply that x == y. Thus, it is 
insufficient to determine equality purely based on opCmp alone. 
")


I think you are making a slight confusion. Your `Interval` struct 
and the `Elem` type that `lowerBound` takes, are the same type.


You can define your RBTree and Interval as follows
```
struct Interval
{
int start;
int end;
}

alias IntervalTree = RedBlackTree!(Interval, (i1, i2) => i1.start 
< i2.start);

```

Please see this runable example: https://run.dlang.io/is/4cPTik

The in-order traversal will be the same as the wikipedia example 
here: https://en.wikipedia.org/wiki/Interval_tree


Hope this helps.

Cheers,
Edi


Re: __traits for checking if a type is dynamic array (slice)

2018-11-26 Thread Eduard Staniloiu via Digitalmars-d-learn

On Monday, 26 November 2018 at 09:28:37 UTC, Basile B. wrote:

On Monday, 26 November 2018 at 09:04:25 UTC, Per Nordlöw wrote:

Why is there no

- __traits(isArray, T)

alongside

- __traits(isStaticArray, T) and
- __traits(isAssociativeArray, T)

when dmd already has `ENUMTY.Tarray` alongside

- ENUMTY.Tsarray and
- ENUMTY.Taarray

and std.traits already has a wrapper for this at

https://dlang.org/phobos/std_traits.html#isDynamicArray

?

Should we add this new builtin trait and use it in 
std.traits.isDynamicArray?


If so, should we call it

- __traits(isDynamicArray) or
- __traits(isArray) or
- __traits(isArraySlice) or
- __traits(isSlice) or

something else?


Yeah maybe just try, although i see some alias this implication 
in the current std.traits implementation. Adding a new trait is 
rarely a big deal as far as i could see in the past (i.e no big 
never endings discussions).


This would be a nice addition, imho.

As Basile B is saying, there is quite a bit of work done for the 
`isDynamicArray` implementation. If you have the time to drill 
down from 
https://github.com/dlang/phobos/blob/master/std/traits.d#L6618


I was expecting the `isArray` check to be something like `enum 
isArray(T) = is(T == U[], U)`


I would like to see this in the compiler traits :D


Re: Making external types available to mixins

2018-11-22 Thread Eduard Staniloiu via Digitalmars-d-learn

On Sunday, 18 November 2018 at 11:29:51 UTC, John Chapman wrote:
On Saturday, 17 November 2018 at 21:11:38 UTC, Adam D. Ruppe 
wrote:
On Saturday, 17 November 2018 at 17:58:54 UTC, John Chapman 
wrote:

Has anyone had a similar need and come up with a solution?


You might be able to just pass it the Calendar type, and then 
fetch its parent module and get the ICalendarFactory from 
there (assuming they are defined in the same module).


But generally speaking, passing strings to a mixin that refer 
to something in another module isn't going to work well thanks 
to scoping rules. You are better off passing a symbol of some 
sort.


So there is no actual Calendar type. There's an 
ICalendarFactory type that creates instances of ICalendar 
(these types are part of a third-party API).  "Calendar" is 
just a key users could use when calling a "makeWith" method 
that would build the ICalendar/Factory names, instantiate the 
factory, call the appropriate factory method and return the 
result. There are thousands of such object/factory pairs in the 
API. Just trying to cut out a lot of boilerplate code, but it 
doesn't seem doable this way.


Cheers,

So I had a go at this and I have a working solution.
https://run.dlang.io/is/oaH6Ib

At first, I tried to do everything in the mixin, as you can see 
with the `failedAttempt` function. The idea was that this should 
have worked like `mixin(failedAttempt!"Calendar"(1, 2, 3));`. As 
you can see, and the name suggests, I wasn't able to make it work 
with `args`.


The solution I have to your problem is to use a template, in this 
case the `theType` template that will expand to the fully 
qualified name. So you'd use it like

`makeWith!(theType!"Calendar")(args);`

Hope it helps!

Edi


Re: Built-in array opSliceAssign

2018-10-30 Thread Eduard Staniloiu via Digitalmars-d-learn

On Thursday, 25 October 2018 at 21:00:46 UTC, Adam D. Ruppe wrote:
On Thursday, 25 October 2018 at 19:56:18 UTC, Stanislav Blinov 
wrote:
The current behavior of the compiler is quite the opposite of 
those "same as" above.


Yeah, I guess I am maybe selectively reading the spec in light 
of the implementation... but I think the examples are just 
sloppy. Or maybe we have a buggy implementation but idk which 
is more useful.


I still hold my believe that if opAssign is defined then that 
should be used.


In my humble opinion, the current way might/could be faster, but 
it's not correct.


Re: Built-in array opSliceAssign

2018-10-25 Thread Eduard Staniloiu via Digitalmars-d-learn

On Thursday, 25 October 2018 at 12:55:38 UTC, Adam D. Ruppe wrote:
On Thursday, 25 October 2018 at 12:25:37 UTC, Eduard Staniloiu 
wrote:
IMHO, this is a bug. The code should lower to calls to 
opAssing for types that define opAssign.


The spec doesn't exactly say it uses memset, but it does imply 
it:


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

talking about "aggressive parallel code optimizations than 
possible with the serial semantics of C" and "copying" rather 
than "assigned" etc.


but indeed postblit lets this work.


You are right. Thank you!

I guess I never read/understood it like this.
I expected it to use opAssign as that is what's the most natural 
and intuitive decision for me.


I take it that this is the expected behaviour, then.


Re: Built-in array opSliceAssign

2018-10-25 Thread Eduard Staniloiu via Digitalmars-d-learn
On Thursday, 25 October 2018 at 13:01:06 UTC, Eduard Staniloiu 
wrote:

On Thursday, 25 October 2018 at 12:38:44 UTC, Paul Backus wrote:
On Thursday, 25 October 2018 at 12:25:37 UTC, Eduard Staniloiu 
wrote:
As I wrote in the comments above, I was expecting `a[] = b[]` 
to iterate the slices and assign the elements of b into a.


What really happens is a memcpy: as you can see from godblot 
[0], this gets lowered to a call to `_d_arraycopy`, in 
druntime.


In D, when you assign one aggregate to another, opAssign is 
only called for the aggregate, not for any of its elements. 
However, postblit constructors are called for both. Example: 
https://run.dlang.io/is/XfDaWw




Can you, please, give me a link to where it says this in the 
specs?


Based on the example, I would expect that the code gets lowered 
to some version of `_d_arrayassign` [0]. I still think that 
this is problematic, as it's unexpected to the user: you're 
expecting the assignment operator to be called, not the 
postblit.


I know that the compiler can and will create an opAssign if a 
postblit or dtor is defined, as you can write the assignment as 
a this._dtor; blit rhs into this.


This being said, I think that if the user took the time to 
define opAssign, it should be called, because he might want to 
do something extra when an assignment occurs: an ex. having 
different logs "creating new obj" vs "changing existing obj".



Your example will work as expected if you change the opAssign 
to a postblit constructor: https://run.dlang.io/is/HBbGO2


Accidentally sent to early.

One extra reason as to why, imho, this implicit call to the 
postblit is evil, is that a lot of code will probably break when 
we'll transition to the CopyConstructor. See RazvanN's PR [0].


This is actually how I stumbled upon this, as I am using his 
branch with my repo.


[0] - https://github.com/dlang/dmd/pull/8688


Re: Built-in array opSliceAssign

2018-10-25 Thread Eduard Staniloiu via Digitalmars-d-learn

On Thursday, 25 October 2018 at 12:38:44 UTC, Paul Backus wrote:
On Thursday, 25 October 2018 at 12:25:37 UTC, Eduard Staniloiu 
wrote:
As I wrote in the comments above, I was expecting `a[] = b[]` 
to iterate the slices and assign the elements of b into a.


What really happens is a memcpy: as you can see from godblot 
[0], this gets lowered to a call to `_d_arraycopy`, in 
druntime.


In D, when you assign one aggregate to another, opAssign is 
only called for the aggregate, not for any of its elements. 
However, postblit constructors are called for both. Example: 
https://run.dlang.io/is/XfDaWw




Can you, please, give me a link to where it says this in the 
specs?


Based on the example, I would expect that the code gets lowered 
to some version of `_d_arrayassign` [0]. I still think that this 
is problematic, as it's unexpected to the user: you're expecting 
the assignment operator to be called, not the postblit.


I know that the compiler can and will create an opAssign if a 
postblit or dtor is defined, as you can write the assignment as a 
this._dtor; blit rhs into this.


This being said, I think that if the user took the time to define 
opAssign, it should be called, because he might want to do 
something extra when an assignment occurs: an ex. having 
different logs "creating new obj" vs "changing existing obj".



Your example will work as expected if you change the opAssign 
to a postblit constructor: https://run.dlang.io/is/HBbGO2




Built-in array opSliceAssign

2018-10-25 Thread Eduard Staniloiu via Digitalmars-d-learn

Hello, everyone!

I have a question regarding the expected behaviour of the 
built-in array's opSliceAssign.


Given the following code:

```
import std.stdio;

struct A
{
int x;

ref A opAssign(A rhs)
{
writefln("slice_bug.opAssign: begin");

return this;
}
}

void main(string[] args)
{
A[] a = [A(1), A(2), A(3)];
A[] b = [A(2), A(3), A(4)];

// Expecting opAssign to be called for every element in a
a[] = b[];

// In other words, I was under the impression that the above
// is sintactic-sugar for
for (size_t i = 0; i < a.lenght; ++i)
{
a[i] = b[i]; // This calls opAssign, as expected
}
}
```

As I wrote in the comments above, I was expecting `a[] = b[]` to 
iterate the slices and assign the elements of b into a.


What really happens is a memcpy: as you can see from godblot [0], 
this gets lowered to a call to `_d_arraycopy`, in druntime.


I'm not sure if this is the intended behaviour, though.
I'm saying this as I've got bitten by this, because I'm doing 
reference counting inside opAssign.


IMHO, this is a bug. The code should lower to calls to opAssing 
for types that define opAssign.


I've also pasted the code on https://run.dlang.io/is/vneELO

[0] - https://godbolt.org/z/_IXCAV




Re: How to destruct class instances allocated by a Region-allocator over a single GC block

2018-04-10 Thread Eduard Staniloiu via Digitalmars-d-learn

On Monday, 9 April 2018 at 14:51:24 UTC, Per Nordlöw wrote:
On Monday, 9 April 2018 at 13:51:47 UTC, Steven Schveighoffer 
wrote:
Well, you know the type, because make returned it no? The 
contract is, you call obj = make!X(args), then you have to 
call dispose(obj), where obj is of the type X. That's how it 
knows.


If you are thinking you want to destroy the whole block at 
once (typed as void[]), that's not how it works.


stdx.allocator is not going to help you with GC collection, 
it's not geared towards that purpose.


Ok, thanks!


If you are using a custom allocator to allocate memory then you 
also
have to manually dispose of the memory when it is no longer 
needed.


You can't have a custom allocator to supply you with the memory 
and
then have the GC track and dispose of it. I get the feeling that 
this

is what you were looking for?


Re: How to destruct class instances allocated by a Region-allocator over a single GC block

2018-04-07 Thread Eduard Staniloiu via Digitalmars-d-learn

On Friday, 6 April 2018 at 21:49:37 UTC, Per Nordlöw wrote:
On Tuesday, 3 April 2018 at 09:14:28 UTC, Eduard Staniloiu 
wrote:

So, say `reg` is your allocator, your workflow would be

auto obj = reg.make!Type(args);
/* do stuff */
reg.dispose(obj); // If Type has a __dtor, it will call 
obj.__dtor

  // and then reg.deallocate(obj)


If I do sucessive calls to reg.make!X where X are different 
kinds of classes of different sizes how does reg.dispose(obj) 
figure out at which address(es) (where emplace filled in the 
data) the objects reside?


It can't figure out. With custom allocators you have to manually 
do
the memory management, so the responsibility of when and which 
object needs

to be destroyed falls on the user of the custom allocator.


Re: How to destruct class instances allocated by a Region-allocator over a single GC block

2018-04-03 Thread Eduard Staniloiu via Digitalmars-d-learn
On Monday, 2 April 2018 at 21:32:47 UTC, Steven Schveighoffer 
wrote:

On 4/2/18 5:16 PM, Per Nordlöw wrote:
On Monday, 2 April 2018 at 20:43:01 UTC, Alexandru Jercaianu 
wrote:
I am not completely sure how to solve this, but maybe we can 
find some clues here [1].
It seems like we should use addRoot on the buffer returned by 
GC.instance.allocate to keep it alive.
Then, we can use addRange on each node after allocation and 
somehow use 'TypeInfo' to trigger destructors.
I'll dig into this more tomorrow and come back with a better 
answer.


How can there not be a documented answer for this question, 
given that std.experimental.allocator has been in Phobos for 2 
years?


Has std.experimental.allocator only been used for allocating 
`struct`s?


Is the Region allocator especially misfit for constructing 
classes?


Since a while, the GC also calls struct destructors, so it's 
likely to be a problem for both.


Note, addRoot and addRange will NOT call the destructors 
appropriately. It will just prevent those memory areas from 
getting collected. The memory shouldn't be collected anyway 
because RegionAllocator should have a reference to it.


The only way it will get destroyed is removing the root/range, 
and then it will get collected just like any other GC block -- 
same as it is now.


It looks like std.experimental.allocator assumes you will 
manually destroy items (possibly via dispose), it has no 
mechanism to say "here's how to destroy this memory I'm 
allocating if you happen to collect it".


-Steve


The GCAllocator from std.experimental uses the druntime 
core.memory.GC, and allocates with a call to GC.malloc [1]


The GC doesn't know how you are using the memory chunk that he 
provided you with.
He only keeps a track of this chunk and will collect it when 
there are no more references
to it; you could also manually free it, if you wish so, with a 
call to

`GCAllocator.instance.deallocate`.

As Steve has said, you will have to manually destroy the items. I 
recommend using dispose
as it checks if the destroyed object has an explicit destructor, 
which it calls, before deallocating the memory.


So, say `reg` is your allocator, your workflow would be

auto obj = reg.make!Type(args);
/* do stuff */
reg.dispose(obj); // If Type has a __dtor, it will call obj.__dtor
  // and then reg.deallocate(obj)

Hope this helps.

Cheers,
Edi

[1] - https://dlang.org/library/core/memory/gc.malloc.html


Re: Constructor qualifiers; bug or expected behavior?

2018-04-02 Thread Eduard Staniloiu via Digitalmars-d-learn

On Monday, 2 April 2018 at 10:26:32 UTC, RazvanN wrote:

Hi all,

Let's say we have this code:

struct B
{
int a;
this(int a) immutable
{
this.a = 7;
}

this(int a)
{
this.a = 10;
}
}

void main()
{
B a = immutable B(2);
writeln(a.a);
a.a = 4;
type `B`
immutable B a2 = immutable B(3);
writeln(a2.a);
a2.a = 3;// error : cannot modify
}

Both a and a2 will be constructed using the immutable 
constructor, however a is not immutable (a.a = 4 will compile 
fine). Is this the intended behavior? Shouldn't the compiler 
warn me that I'm trying to create a mutable object using the 
constructor for an immutable object? I couldn't find any 
documentation about this.


The compiler does an implicit conversion from the type `immutable 
B`
to the type `B`. It is able to do safely do so because `struct B` 
has only

value types that can be copied.

The same thing happens for
immutable x = 1;
int y = x;

If you add an indirection in `struct B`, as such

struct B
{
int a;
int* p;
/* ... */
}

Then you can see that the implicit conversion fails with
"onlineapp.d(22): Error: cannot implicitly convert expression 
B(0, null).this(2) of type immutable(B) to B"


I put the code at
https://run.dlang.io/gist/83756973012fcb4fec2660a39ffdad90=-unittest?args=-unittest

The same conversion rules that apply to built in qualified types 
applies to structs. I'm guessing the same is for classes but I 
haven't played that much with those so a second opinion would be 
nice :)


Cheers,
Edi


Re: Postblit constructor

2018-03-02 Thread Eduard Staniloiu via Digitalmars-d-learn

On Wednesday, 28 February 2018 at 18:27:49 UTC, Jiyan wrote:

On Wednesday, 28 February 2018 at 18:23:04 UTC, Jiyan wrote:

Hey,
i thought i had understood postblit, but in my Code the 
following is happening (simplified):


struct C
{
this(this){/*Do sth*/}
list!C;

void opAssign(const C c)
{
 "Postlbit from C called".writeln;
 // Do sth
}
}


Sry of course it is

"Postlbit from C called".writeln; in this(this)
and the c from opAssign should get constructed via postblit. 
Doesnt it?


I'm not sure I understood your question, so please let me know if 
this clears things out or not.


The parameter of opAssign will be constructed through a postblit 
call, but you need to explicitly assign what you want from the 
parameter inside the instance of _this_ object.


Re: Cannot make my shared PureMallocator callable in pure functions

2018-02-17 Thread Eduard Staniloiu via Digitalmars-d-learn

On Saturday, 17 February 2018 at 12:33:25 UTC, Nordlöw wrote:

I'm struggling with making

https://github.com/nordlow/phobos-next/blob/master/src/pure_mallocator.d

callable in pure functions such as here

https://github.com/nordlow/phobos-next/blob/master/src/pure_mallocator.d#L84

Shouldn't a shared

static shared PureMallocator instance;

make it possible to call

PureMallocator.instance.allocate(16);

in pure functions?


As the folks before me have pointed out, the language doesn't 
allow you to use globals inside pure code, excepting global 
immutables; this makes sense as once an immutable object was 
constructed it will never change.


As Steven pointed out, we are just trying to fool the compiler 
into thinking that allocators don't have side effects; in the 
case of Mallocator, we are just forwarding calls to libc's 
mallocator.


With this in mind, it looks to me that you just need to decide 
what is the best/easiest way for you to forward the calls. You 
could:
  1) make all you methods static (after all, the allocator is 
stateless)

  2) make `instance` immutable and make all the methods const



Re: Class allocators

2017-11-12 Thread Eduard Staniloiu via Digitalmars-d-learn

On Saturday, 11 November 2017 at 14:26:34 UTC, Nordlöw wrote:

Have anybody used allocators to construct class instances?


I might be wrong, but I think you are looking for 
std.experimental.allocator.make [0]


[0] - 
https://dlang.org/phobos/std_experimental_allocator.html#make


Re: Assert and undefined behavior

2017-10-11 Thread Eduard Staniloiu via Digitalmars-d-learn

On Wednesday, 11 October 2017 at 09:39:04 UTC, user1234 wrote:
On Wednesday, 11 October 2017 at 09:27:49 UTC, John Burton 
wrote:

[...]
I therefore feel like I ought to not use assert and should 
instead validate my assumptions with an if statement and a 
throw or exit or something.


Yes, that's the way of doing. assert() are just used to test 
the program. the -release option in DMD disable all the 
assert() (excepted assert(0) which is a bit special), so that 
in a release version, only Throwable objects can be used after 
a failure detected.


A small addition to the answers already provided.

As user1234 has already said, asserts are removed in the -release 
build, so, if you have to validate some assumption (ex. the file 
opened) you should use enforce[0].


Cheers,
Eduard

[0] - https://dlang.org/library/std/exception/enforce.html


Re: Why would an initialised struct pointer field be null in the struct's destructor?

2017-05-21 Thread Eduard Staniloiu via Digitalmars-d-learn

On Saturday, 20 May 2017 at 10:48:54 UTC, Gary Willoughby wrote:
Looks like you would want to use emplace [0] here.


public this(int n)
{
this._data = (cast(Foo*) calloc(n, Foo.sizeof))[0 .. n];

foreach(ref element; this._data)
{
auto tmp = Foo(1);
element = tmp;
}
}


Cheers,
Eduard

[0] - https://dlang.org/phobos/std_conv.html#.emplace.3


Re: Missing functionality in std.process?

2017-01-06 Thread Eduard Staniloiu via Digitalmars-d-learn

On Friday, 14 October 2016 at 16:33:51 UTC, Andre Pany wrote:
What I miss is s.th. to get the child Pids of a parent Pid. 
Again I can use OS dependent functionality to retrieve the 
processIDs of the children, but how to convert these processIDs 
to Pids for usage with kill/wait functions?


On Unix you could use
  core.sys.posix.signal.kill(pid_t, int)
  core.sys.posix.sys.wait.wait(int*)
  core.sys.posix.sys.wait.waitpid(pid_t, int*, int)

I tested the kill function and it works like a charm. Since pid_t 
is just an alias to int, just provide the process integer to the 
function.


On Windows, I'm guessing, you could use
  core.sys.windows.winbase.TerminateProcess(HANDLE, UINT)

I don't have a Windows environment set up so you will have to 
play with this.