Taming templates and mixin magic: type inpector helper in D/Phobos?

2018-04-03 Thread Carlos Navarro via Digitalmars-d-learn
As a newbie in D (and making a lots of mistakes), I've found 
myself relying heavily in the use of a rudimentary type inspector 
to visualize my templated code instantiations.
It's simple and incomplete as hell but good enough to see what 
happens under the hood quickly.


QUESTION: Is there a function like that already in D?


//real-life example
goodEnoughTypeInspector!Human;
goodEnoughTypeInspector!(Database!Human);

//compile-time output
Inspecting type: Human
 - public string name
 - public string address
 - public bool active

Inspecting type: Database!(Human)
 - private string[] name
 - private string[] address
 - private bool[] active
 - public pure nothrow @nogc @safe ulong() count
 - public void insert




Re: Learning D - modules packages and the package.d

2018-04-03 Thread Jonathan M Davis via Digitalmars-d-learn
On Wednesday, April 04, 2018 04:54:50 Ali via Digitalmars-d-learn wrote:
> I am going through the Learning D book by Michael Parker
> So every now and then I will make post about the book
> either critics of the book, book content or questions
>
>
> First critic
> chapter 2 - the special package module
>
> this small section, suggest an idiom to create a package which
> can have any name
> the book suggest somepack
> and inside it add a module package.d , so you will end up
> somepack/package.d
> inside the file add
>
> > module somepack; //notice this named after the folder
> > //then public import std.stdio, somepack.one, somepack.two;
> > //etc
>
> at first i though package.d is special name, as in i must call
> the file package.d or this trick or idiom to work
> also it felt weird that the module name, is named after the
> folder name, which previously was referred to as the package name
>
> anyway, i started playing with this, and renaming everything
> and my conclusion is
>
> i not really sure, if D really support or have packages
> as in D is aware that some modules are together in a package
>
> it seems to me at this time D only support modules
> modules can have names with . in them
> you can use the . in module names to make it seem as if its
> packages
>
> > import io = long.module.name
>
> also seem as a trick that complements having modules with long
> names with dots in them
>
> and it seems you really need to match file and module names
>
> my critic of the chapter 2 so far, the book doesn't really help
> clarify this situation
> i am relieved though to learn that D doesnt treat special
> file/module names as special

In general, modules correspond to files, and packages correspond to folders.
That can be played with by naming modules with names that don't match their
file names, but it tends to cause problems with build tools. In general,
modules and packages should match their corresponding file and folder names
if you don't want problems.

package.d is a special case. package is not a legal module name, so when the
package.d feature was added to the language, the odds of it conflicting with
any existing files were very low. What happens with package.d is that when
you try to import a package rather than a module, the compiled looks for a
package.d file within the package that you're trying to import, and it
imports that module. The typical thing to do is to have the module name
within that module match the package name. I don't know what happens if you
try to do otherwise, but I wouldn't expect it to work, because in this case,
the compiler is specifically looking for package.d and not the module with
with matching module declaration. _That_ is all that's special about
package.d - it's what's imported you try to import a package.

Now, if there is a package.d, it's typically the case that it has public
import statements for the modules inside the package so that importing the
package will then import all of the modules within the package, but what
actually gets imported when importing the package is entirely dependent on
what's in package.d. It can define symbols of its own, and it doesn't _have_
to publicly import anything. And since public imports can be used in any
module, there's nothing really special about them in package.d. It's just
that using them in package.d makes it possible to have it be the case that
importing a package imports all of the modules within that package.

The entire reason that the package.d feature was added to the language was
so that a module could be broken up into multiple modules within a package
with the same name without breaking code in the process - e.g.
std.algorithm, std.container, std.datetime, and std.range were all
originally modules, but now, they're all packages. Personally, I don't think
that it's great practice to use package.d if you don't have to (and
importing that many symbols at once can negatively impact compilation
times), but some folks like to use it for their libraries so that you can
import everything at once.

- Jonathan M Davis



Re: Learning D - modules packages and the package.d

2018-04-03 Thread Ali via Digitalmars-d-learn

On Wednesday, 4 April 2018 at 04:54:50 UTC, Ali wrote:
at first i though package.d is special name, as in i must call 
the file package.d or this trick or idiom to work


the trick was to have one module that public import all the 
modules you import as group in other modules


so instead of importing a dozen or so modules, you only import 
one module that imports everything you need


Learning D - modules packages and the package.d

2018-04-03 Thread Ali via Digitalmars-d-learn

I am going through the Learning D book by Michael Parker
So every now and then I will make post about the book
either critics of the book, book content or questions


First critic
chapter 2 - the special package module

this small section, suggest an idiom to create a package which 
can have any name

the book suggest somepack
and inside it add a module package.d , so you will end up 
somepack/package.d

inside the file add


module somepack; //notice this named after the folder
//then public import std.stdio, somepack.one, somepack.two; 
//etc


at first i though package.d is special name, as in i must call 
the file package.d or this trick or idiom to work
also it felt weird that the module name, is named after the 
folder name, which previously was referred to as the package name


anyway, i started playing with this, and renaming everything
and my conclusion is

i not really sure, if D really support or have packages
as in D is aware that some modules are together in a package

it seems to me at this time D only support modules
modules can have names with . in them
you can use the . in module names to make it seem as if its 
packages



import io = long.module.name


also seem as a trick that complements having modules with long 
names with dots in them


and it seems you really need to match file and module names

my critic of the chapter 2 so far, the book doesn't really help 
clarify this situation
i am relieved though to learn that D doesnt treat special 
file/module names as special


Re: is this even possible? newbie + mixin template + foreach (allMembers)

2018-04-03 Thread Seb via Digitalmars-d-learn

On Tuesday, 3 April 2018 at 18:49:00 UTC, Carlos Navarro wrote:

QUESTION:

Obviously I'm no geting mixins/templates nor traits and I'm 
failing miserably to find/identify the right examples or 
documentation to help me tackle this thing. What is wrong in 
this code? is this pattern sintactically possible? what I'm 
getting wrong?


[...]


ICEs (compiler segfault) should _always_ be reported on Bugzilla. 
The compiler should never ever segfault - even on invalid code.


I just did so for you: 
https://issues.dlang.org/show_bug.cgi?id=18718


Re: Better way to append to array than ~= ?

2018-04-03 Thread Alex via Digitalmars-d-learn
On Tuesday, 3 April 2018 at 20:02:46 UTC, Vladimirs Nordholm 
wrote:

On Tuesday, 3 April 2018 at 19:53:11 UTC, Meta wrote:
On Tuesday, 3 April 2018 at 19:02:25 UTC, Vladimirs Nordholm 
wrote:

[...]


In this specific case, since you know the length of `Args`, 
you can pre-allocate an array of that size and loop through it 
doing your initialization.


However, if you want really performant code, you should 
allocate a static array on the stack outside of the function 
and pass it in as a buffer.


I don't think I know the size of the arguments.

If I pass in "123" and MySpecialType('a'), the result should be:

assert(foo("123", MySpecialType('a')) == 
[MySpecialType('1'), MySpecialType('2'), MySpecialType('3'), 
MySpecialType('a')]);


What should the length of the pre-allocated array be?


In my try, I iterate the args twice. The first time to calculate 
the number of elements, then preallocate and then iterate them 
again and constructing the proper objects.


It is not nice, but about 1/3 of time, compared to original 
version, compiled in release mode.


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


Re: Better way to append to array than ~= ?

2018-04-03 Thread Meta via Digitalmars-d-learn
On Tuesday, 3 April 2018 at 20:02:46 UTC, Vladimirs Nordholm 
wrote:

On Tuesday, 3 April 2018 at 19:53:11 UTC, Meta wrote:
On Tuesday, 3 April 2018 at 19:02:25 UTC, Vladimirs Nordholm 
wrote:

[...]


In this specific case, since you know the length of `Args`, 
you can pre-allocate an array of that size and loop through it 
doing your initialization.


However, if you want really performant code, you should 
allocate a static array on the stack outside of the function 
and pass it in as a buffer.


I don't think I know the size of the arguments.

If I pass in "123" and MySpecialType('a'), the result should be:

assert(foo("123", MySpecialType('a')) == 
[MySpecialType('1'), MySpecialType('2'), MySpecialType('3'), 
MySpecialType('a')]);


What should the length of the pre-allocated array be?


You know the static types of the arguments, so it is not 
impossible. However, the more flexible you need to be, the more 
complex your code will have to be, and it probably won't be worth 
the added complexity. Anyway, sorry for derailing a bit. That's 
not really your question.


Using Appender!MySpecialType might be marginally faster than ~=, 
but from the looks of it you are already using Appender. I don't 
know if there's much more you can do to speed up appending 
without just rolling your own solution or restructuring your code.


Re: Better way to append to array than ~= ?

2018-04-03 Thread Vladimirs Nordholm via Digitalmars-d-learn

On Tuesday, 3 April 2018 at 19:53:11 UTC, Meta wrote:
On Tuesday, 3 April 2018 at 19:02:25 UTC, Vladimirs Nordholm 
wrote:

[...]


In this specific case, since you know the length of `Args`, you 
can pre-allocate an array of that size and loop through it 
doing your initialization.


However, if you want really performant code, you should 
allocate a static array on the stack outside of the function 
and pass it in as a buffer.


I don't think I know the size of the arguments.

If I pass in "123" and MySpecialType('a'), the result should be:

assert(foo("123", MySpecialType('a')) == [MySpecialType('1'), 
MySpecialType('2'), MySpecialType('3'), MySpecialType('a')]);


What should the length of the pre-allocated array be?


Re: mixin break; in switch containing static foreach

2018-04-03 Thread Vladimirs Nordholm via Digitalmars-d-learn

On Tuesday, 3 April 2018 at 19:41:54 UTC, Alex wrote:
On Tuesday, 3 April 2018 at 19:31:50 UTC, Vladimirs Nordholm 
wrote:

[...]


Would labelling help?
https://run.dlang.io/is/vE1KyD


Ah! Okay, now I see.

Thanks Alex and Adam!


Re: Better way to append to array than ~= ?

2018-04-03 Thread Meta via Digitalmars-d-learn
On Tuesday, 3 April 2018 at 19:02:25 UTC, Vladimirs Nordholm 
wrote:

Hello people.

I currently have a function which multiple times per second 
takes in arguments, and appends the argument as my special 
type. The following code should explain what I do more properly:


struct MySpecialType { char c; }

auto foo(Args...)(Args args)
{
MySpecialType[] bar;

foreach(ref arg; args)
{
static if(is(typeof(arg) == MySpecialType))
{
bar ~= arg;
}
else
{
foreach(c; to!string(arg))
{
bar ~= MySpecialType(c);
}
}
}

// do more stuff
}

Now, from my trace.log, some of the topmost things on the 
timing list are `std.array.Appender!(immutable(char).stuff>`. I also remember reading some years ago that ~= isn't 
optimal for speed.


So my question is: Is there a better and/or faster way of doing 
this, or is this the best approach?


In this specific case, since you know the length of `Args`, you 
can pre-allocate an array of that size and loop through it doing 
your initialization.


However, if you want really performant code, you should allocate 
a static array on the stack outside of the function and pass it 
in as a buffer.


Re: mixin break; in switch containing static foreach

2018-04-03 Thread Adam D. Ruppe via Digitalmars-d-learn
On Tuesday, 3 April 2018 at 19:31:50 UTC, Vladimirs Nordholm 
wrote:

switch(foo)


Put the label on the switch

whatever: switch(foo)



mixin(format("
case Foo.%s:bar = Bar.%s;break;
", f, f));


then use the label here

break whatever;


Re: mixin break; in switch containing static foreach

2018-04-03 Thread Alex via Digitalmars-d-learn
On Tuesday, 3 April 2018 at 19:31:50 UTC, Vladimirs Nordholm 
wrote:
My base problem is that I want to mixin `break` into a switch 
statement, but the mixin is within a static foreach. Take a 
look at the following code:


switch(foo)
{
static foreach(f; EnumMembers!Foo)
{
mixin(format("
case Foo.%s:bar = Bar.%s;break;
", f, f));
}

default: /* do stuff */; break;
}

The above code returns the error "Error: must use labeled 
`break` within `static foreach`". For a more complete example, 
take a look att this sample code: 
https://dpaste.dzfl.pl/f3ab6d9679fc


I also attempted this solution, but I got the error that the 
label didn't exist. (And it looks pretty ugly)


mixin(format("%s: case Foo.%s: abc = Foo.X%s; break %s;", 
f, f, f, f));


Any of you have a solution for this problem?

Best regards,
Vladimirs Nordholm


Would labelling help?
https://run.dlang.io/is/vE1KyD



mixin break; in switch containing static foreach

2018-04-03 Thread Vladimirs Nordholm via Digitalmars-d-learn
My base problem is that I want to mixin `break` into a switch 
statement, but the mixin is within a static foreach. Take a look 
at the following code:


switch(foo)
{
static foreach(f; EnumMembers!Foo)
{
mixin(format("
case Foo.%s:bar = Bar.%s;break;
", f, f));
}

default: /* do stuff */; break;
}

The above code returns the error "Error: must use labeled `break` 
within `static foreach`". For a more complete example, take a 
look att this sample code: https://dpaste.dzfl.pl/f3ab6d9679fc


I also attempted this solution, but I got the error that the 
label didn't exist. (And it looks pretty ugly)


mixin(format("%s: case Foo.%s: abc = Foo.X%s; break %s;", f, 
f, f, f));


Any of you have a solution for this problem?

Best regards,
Vladimirs Nordholm


Re: is this even possible? newbie + mixin template + foreach (allMembers)

2018-04-03 Thread Alex via Digitalmars-d-learn

On Tuesday, 3 April 2018 at 18:57:29 UTC, WebFreak001 wrote:


you need to use a static foreach for this. You can insert a 
static foreach basically where you can insert a function 
definition like void foo() {}


foreach is more like a function call like foo(), so you can't 
put it in the mixin template.


A mixin template is basically expected to be mixin-able in 
global scope or in a class/struct so it can't have any things 
like function calls because that would be the same as writing 
`foo();` at global level instead of in the main function.


static foreach on the other hand allows exactly that because it 
literally unrolls the contents and inserts it multiple times, 
so you can also put it in mixin templates if the content of the 
loop is valid in mixin templates.


If you need to support older compilers you can use normal 
foreach with ctfe by generating a code string or do recursive 
templates, but I would really encourage you to use static 
foreach instead, it is cleaner and faster.


I think, the OP has something other in mind. Look at this:

´´´
void main(){}

struct World
{
floatrotation;
bool active;

//mixin BuildStuff!();
}

mixin BuildStuff!();

mixin template BuildStuff()
{
static foreach(elem; __traits(allMembers, World))
{
pragma(msg, elem);
}
}
´´´

While the outer mixin works as expected, the inner one results in 
a seg fault.

No idea why, however, too...


Better way to append to array than ~= ?

2018-04-03 Thread Vladimirs Nordholm via Digitalmars-d-learn

Hello people.

I currently have a function which multiple times per second takes 
in arguments, and appends the argument as my special type. The 
following code should explain what I do more properly:


struct MySpecialType { char c; }

auto foo(Args...)(Args args)
{
MySpecialType[] bar;

foreach(ref arg; args)
{
static if(is(typeof(arg) == MySpecialType))
{
bar ~= arg;
}
else
{
foreach(c; to!string(arg))
{
bar ~= MySpecialType(c);
}
}
}

// do more stuff
}

Now, from my trace.log, some of the topmost things on the timing 
list are `std.array.Appender!(immutable(char).`. I 
also remember reading some years ago that ~= isn't optimal for 
speed.


So my question is: Is there a better and/or faster way of doing 
this, or is this the best approach?




Re: is this even possible? newbie + mixin template + foreach (allMembers)

2018-04-03 Thread WebFreak001 via Digitalmars-d-learn

On Tuesday, 3 April 2018 at 18:49:00 UTC, Carlos Navarro wrote:

QUESTION:

Obviously I'm no geting mixins/templates nor traits and I'm 
failing miserably to find/identify the right examples or 
documentation to help me tackle this thing. What is wrong in 
this code? is this pattern sintactically possible? what I'm 
getting wrong?


CONTEXT:
I'm a newbie trying to extend a struct using a mixin template 
like this one:


struct World {
floatrotation;
bool active;
mixin BuildStuff;
}

mixin template BuildStuff() {
foreach(elem; __traits(allMembers, typeof(this))) {
//pragma(msg, elem);
}
} //full example here: https://run.dlang.io/is/OeXS4j

COMPILER OUTPUT:

2.067.1 to 2.071.2: Failure with output:
-
onlineapp.d(18): Error: declaration expected, not 'foreach'
onlineapp.d(18): Error: declaration expected, not '__traits'
onlineapp.d(22): Error: template member expected
-

2.072.2 to 2.075.1: Failure with output:
-
onlineapp.d(18): Error: declaration expected, not 'foreach'
onlineapp.d(18): Error: declaration expected, not '__traits'
onlineapp.d(22): Error: matching '}' expected, not EOF
-

Since  2.076.1: Segfault and no output


you need to use a static foreach for this. You can insert a 
static foreach basically where you can insert a function 
definition like void foo() {}


foreach is more like a function call like foo(), so you can't put 
it in the mixin template.


A mixin template is basically expected to be mixin-able in global 
scope or in a class/struct so it can't have any things like 
function calls because that would be the same as writing `foo();` 
at global level instead of in the main function.


static foreach on the other hand allows exactly that because it 
literally unrolls the contents and inserts it multiple times, so 
you can also put it in mixin templates if the content of the loop 
is valid in mixin templates.


If you need to support older compilers you can use normal foreach 
with ctfe by generating a code string or do recursive templates, 
but I would really encourage you to use static foreach instead, 
it is cleaner and faster.


Re: @property for simple methods?

2018-04-03 Thread Vladimirs Nordholm via Digitalmars-d-learn

On Monday, 2 April 2018 at 15:05:04 UTC, Seb wrote:
On Monday, 2 April 2018 at 14:51:57 UTC, Vladimirs Nordholm 
wrote:

On Monday, 2 April 2018 at 14:20:49 UTC, Dennis wrote:

[...]


Ah! First time I read the docs I didn't understand the 
typeof(exp) explanation, but yours made me understand that 
part.


Do you think I should I omit the @property tag, if the only 
wanted behaviour is to set a value (`foo.bar = "baz";`) ?


Yes I would omit @proporty if you don't need it as it isn't 
really useful at the moment.

There's a DIP to fix it and make it more powerful though:

https://github.com/dlang/DIPs/pull/97

And if you are looking for @read, @write limitations the 
accessors library might be interesting to you:


https://code.dlang.org/packages/accessors


Nice read, and the library seems interesting 


is this even possible? newbie + mixin template + foreach (allMembers)

2018-04-03 Thread Carlos Navarro via Digitalmars-d-learn

QUESTION:

Obviously I'm no geting mixins/templates nor traits and I'm 
failing miserably to find/identify the right examples or 
documentation to help me tackle this thing. What is wrong in this 
code? is this pattern sintactically possible? what I'm getting 
wrong?


CONTEXT:
I'm a newbie trying to extend a struct using a mixin template 
like this one:


struct World {
floatrotation;
bool active;
mixin BuildStuff;
}

mixin template BuildStuff() {
foreach(elem; __traits(allMembers, typeof(this))) {
//pragma(msg, elem);
}
} //full example here: https://run.dlang.io/is/OeXS4j

COMPILER OUTPUT:

2.067.1 to 2.071.2: Failure with output:
-
onlineapp.d(18): Error: declaration expected, not 'foreach'
onlineapp.d(18): Error: declaration expected, not '__traits'
onlineapp.d(22): Error: template member expected
-

2.072.2 to 2.075.1: Failure with output:
-
onlineapp.d(18): Error: declaration expected, not 'foreach'
onlineapp.d(18): Error: declaration expected, not '__traits'
onlineapp.d(22): Error: matching '}' expected, not EOF
-

Since  2.076.1: Segfault and no output










Re: @property for simple methods?

2018-04-03 Thread Vladimirs Nordholm via Digitalmars-d-learn

On Monday, 2 April 2018 at 15:15:05 UTC, Dennis wrote:
On Monday, 2 April 2018 at 14:51:57 UTC, Vladimirs Nordholm 
wrote:
Do you think I should I omit the @property tag, if the only 
wanted behaviour is to set a value (`foo.bar = "baz";`) ?


You're probably fine either way, it's mostly for making your 
intention clear. Jonathan M Davis made a great explanation:

(https://forum.dlang.org/post/mailman.709.1481234980.9448.digitalmars-d-le...@puremagic.com)


His reasoning is the same as mine. I only have the @property as 
documentation :)


Second Language Acquisition - Dogme & Direct Method

2018-04-03 Thread markmst via Digitalmars-d-learn
The Dogme method, based on the writing of Scott Thornbury, 
“considers language learning to be a process where language 
emerges rather than one where it is acquired”. The entire method 
is based on conversation and the teaching (or in group lessons 
‘moderation’) as such does not follow specific syllabus. While 
there is considerable criticism on this method (especially if 
followed strictly avoiding all text-material), interestingly it 
represents an excellent example of point (B) highlighted above – 
tapping into “Primary Language Acquisition Process Methods”. Also 
in Children Primary Language Acquisition very little 
text-material is used. (Picture-)Books are material to support a 
learning process entirely based on conversation. Almost every 
person went through this apparently highly effective process; the 
efficiency of this approach for Adult Education depends on the 
overall curriculum (eg intensity of program, frequency of 
lessons, setup of lessons). To elaborate on the efficiency it has 
to be noted that Children follow this approach over 1-2 years 
fulltime (in the “direct method”, see below). Furthermore the 
method was developed with very specific (e.g. non-tonal) 
languages in mind. Learning for example Chinese without basic 
graphical illustrations of tones or letters might be challenging.


www.language-school.sg


Re: How to Stay Away From Faux Pas in a Foreign Language?

2018-04-03 Thread Timoses via Digitalmars-d-learn

On Tuesday, 3 April 2018 at 15:02:34 UTC, markmst wrote:

Why Pay For Learning a Foreign


I actually read this until "Why Pay For Learning a Foreign 
Language". I didn't get the joke... Go figure..


How to Stay Away From Faux Pas in a Foreign Language?

2018-04-03 Thread markmst via Digitalmars-d-learn
Many language learners will have a similar story to narrate. They 
have often used a foreign word accidentally, which may sound 
similar in the English as well as in the target language and yet 
are completely different in their meanings, Such linguistic 
goof-ups are referred to as "false friends". When you are 
learning a new language, there is hardly a strategic way to 
identify your false friends.


The reason for that is they occur without any set patterns and 
mostly due to coincidence. For instance, in the Portuguese 
language, when your superior volunteers to assist in your office 
presentation, it signifies that they will not assist but observe 
it.


On several occasions, certain words of a foreign language may 
appear funny to a person who is not aware of it, especially on a 
menu at a restaurant. But it is still important to resist the 
temptation of laughing out loud Why Pay For Learning a Foreign 
Language at that local language. The reason for that is the 
locals around you will consider it extremely rude.


Try to speak at a slow and measured pace, especially when you are 
travelling between two countries. You need to give adequate time 
between your mouth and brain to ensure that you are not using the 
wrong language in the wrong country. When you learn to avoid 
these common mistakes while speaking a foreign language, you can 
enjoy a fabulous time. Plus, you can pick up quite a few lingo 
while not offending the locals.


More information on :

www.language-school.hk


Re: Why toUTF8 not accept wchar[] as argument?

2018-04-03 Thread Timoses via Digitalmars-d-learn

On Tuesday, 3 April 2018 at 13:12:05 UTC, Timoses wrote:

On Tuesday, 3 April 2018 at 05:20:55 UTC, Seb wrote:
Better diagnostics and error messages is a key goal in 2018 
for dmd ;-)


Awesome! How about telling the user which of the template 
constraints failed? Would be so awesome. Currently, there's a 
need to check every single one (as mentioned by bauss) which 
can sometimes be a hassle.


I guess related issues are:
https://issues.dlang.org/show_bug.cgi?id=9626
https://issues.dlang.org/show_bug.cgi?id=4970


Re: Why toUTF8 not accept wchar[] as argument?

2018-04-03 Thread Timoses via Digitalmars-d-learn

On Tuesday, 3 April 2018 at 05:20:55 UTC, Seb wrote:
Better diagnostics and error messages is a key goal in 2018 for 
dmd ;-)


Awesome! How about telling the user which of the template 
constraints failed? Would be so awesome. Currently, there's a 
need to check every single one (as mentioned by bauss) which can 
sometimes be a hassle.





Re: What is the equivalent of C++'s std::optional and std::nullopt in D?

2018-04-03 Thread Timoses via Digitalmars-d-learn

On Tuesday, 3 April 2018 at 02:10:09 UTC, helxi wrote:
For reference: 
https://en.cppreference.com/w/cpp/utility/optional


See also this topic recently discussed:
https://forum.dlang.org/post/p9qvb8$1j1n$1...@digitalmars.com


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