Re: Dscanner: is it possible to switch off style checks case-by-case?

2020-02-15 Thread mark via Digitalmars-d-learn

On Saturday, 15 February 2020 at 07:23:02 UTC, Basile B. wrote:

On Thursday, 13 February 2020 at 17:15:50 UTC, mark wrote:

I'm starting out with GtkD and have this function:


[snip]
Otherwise here is an example of how you can tune the different 
checks:



https://raw.githubusercontent.com/dlang/phobos/master/.dscanner.ini


See also the last section of


https://raw.githubusercontent.com/dlang-community/D-Scanner/master/README.md


Thank you, I made the code changes and am reading the docs you 
linked to.


Difference between range `save` and copy constructor

2020-02-15 Thread uranuz via Digitalmars-d-learn
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?


How the hell to split multiple delims?

2020-02-15 Thread AlphaPurned via Digitalmars-d-learn
I've tried 10 different ways with split and splitter, I've used 
all the stuff that people have said online but nothing works. I 
always get a template mismatch error.


Why is something so easy to do so hard in D?

auto toks = std.regex.split(l, Regex("s"));
auto toks = std.regex.splitter(l, Regex("s"));
auto toks = std.regex.splitter(l, ctRegex!r"\.");


Re: How the hell to split multiple delims?

2020-02-15 Thread mipri via Digitalmars-d-learn

On Saturday, 15 February 2020 at 11:32:42 UTC, AlphaPurned wrote:
I've tried 10 different ways with split and splitter, I've used 
all the stuff that people have said online but nothing works. I 
always get a template mismatch error.


Why is something so easy to do so hard in D?

auto toks = std.regex.split(l, Regex("s"));
auto toks = std.regex.splitter(l, Regex("s"));
auto toks = std.regex.splitter(l, ctRegex!r"\.");


Why do you think this doesn't work? I'm not just asking this to
be rude. Your problem is likely in the rest of your code.

$ rdmd --eval 'split("the quick,brown:fox",regex("[ 
,:]")).writeln'

["the", "quick", "brown", "fox"]

$ rdmd --eval 'typeid(split("the quick,brown:fox",regex("[ 
,:]"))).writeln'

immutable(char)[][]

$ rdmd --eval 'splitter("the quick,brown:fox",regex("[ 
,:]")).writeln'

["the", "quick", "brown", "fox"]

$ rdmd --eval 'typeid(splitter("the quick,brown:fox",regex("[ 
,:]"))).writeln'

std.regex.Splitter!(cast(Flag)false, string, Regex!char).Splitter

That final value is a range type. Consider the guides
at the top of https://dlang.org/phobos/std_range.html
Ranges take a while to get comfortable with.


Re: rt/aaA.d Line: 553

2020-02-15 Thread Ferhat Kurtulmuş via Digitalmars-d-learn
On Friday, 14 February 2020 at 23:41:45 UTC, Steven Schveighoffer 
wrote:

On 2/14/20 6:36 PM, Ferhat Kurtulmuş wrote:

     İf ((aa.used + 1)* GROW_DEN > aa.dim * GROW_NUM)
     aa.grow(ti.key);


This call is expensive (it reallocates all the buckets and 
reinserts all the existing data into the new bucket), it should 
be avoided if in the end we will not be incrementing used.


-Steve


I am trying to write a gc-free AA based on the original runtime 
code (mem with malloc and free). My question is that why my 
version is slower (about 1.5 times slower) than the runtime 
version?


https://controlc.com/2e58c305

Those are some differences from runtime version:

- nogc and no typeid of course.
- does not care about postblit of key types (don't need it, 
assume only basic types are allowed for key type)
- runtime version uses typeid to do some alignments which are not 
implemented in my version. Is that the reason why my code is 
slower?





Re: static foreach over enum symbols

2020-02-15 Thread Boris Carvajal via Digitalmars-d-learn

On Friday, 14 February 2020 at 22:24:14 UTC, Ben Jones wrote:

Hi all,

I'm getting unexpected results while trying to process symbols 
from a module, some of which are enums.


Depending on whether or not I comment out the first static 
foreach loop below, fullyQualifiedName gives me different 
results in the second loop.


In either case, I'm surprised I can't grab the UDAs in the 
second static foreach loop.  Any ideas what's going on?


Test case:
---a.d---
module a;

@Object
enum x = "hello";

@Object
enum y = "goodbye";

@Object
struct z{}


---main.d---

template symbols(alias Mod){
import std.meta;
alias toSymbol(alias T) = __traits(getMember, Mod, T);
alias symbols = staticMap!(toSymbol, __traits(allMembers, 
Mod));

}


void main(){
import std.traits;
import std.meta;
import a;
//commenting this out changes the results below
static foreach(sym; symbols!a){
pragma(msg, fullyQualifiedName!sym);
pragma(msg, __traits(getAttributes, sym));
}

pragma(msg, "\nget with UDAs\n");
pragma(msg, getSymbolsByUDA!(a, Object));
alias udaSyms = getSymbolsByUDA!(a, Object);
pragma(msg, staticMap!(fullyQualifiedName, udaSyms));
static foreach(us; udaSyms){
pragma(msg, fullyQualifiedName!us);
pragma(msg, __traits(getAttributes, us));
}
}

---

annotated output of dmd main.d:

with the first loop commented out:

get with UDAs

tuple("hello", "goodbye", (z))
tuple("a.x", "a.y", "a.z")
a.x
tuple()  //why is the UDA gone?
a.y
tuple()
a.z
tuple((Object))


and with the first loop:

object
tuple()
main.main.sym  //it's not a.x anymore, it's the name of the 
local var for static foreach?

tuple()
main.main.sym
tuple()
a.z
tuple((Object))

get with UDAs

tuple("hello", "goodbye", (z))
tuple("main.main.sym", "main.main.sym", "a.z") //and the 
results are changed here too?

main.main.sym
tuple()
main.main.sym
tuple()
a.z
tuple((Object))


From language spec [1]: "the name of the static foreach variable 
is bound to the i-th entry of the sequence, either as an enum 
variable declaration (for constants) or an alias declaration (for 
symbols).


Enums are treated differently, so your 'sym' is not an alias to 
the original enum but an enum itself with the same value. Because 
of that, fullyQualifiedName or any template with alias argument 
will just get the sym temporary not the enum from the symbols 
tuple.



This code should work:

static foreach(i, _; symbols!a){
 pragma(msg, fullyQualifiedName!(symbols!a[i]));
 // or manually aliased, but you need to use regular 
foreach or {{ }} to avoid redefinitions.

 alias sym = symbols!a[i];
 pragma(msg, fullyQualifiedName!sym);
  }


[1] https://dlang.org/spec/version.html#staticforeach


Re: static foreach over enum symbols

2020-02-15 Thread Boris Carvajal via Digitalmars-d-learn

On Friday, 14 February 2020 at 22:24:14 UTC, Ben Jones wrote:

Hi all,

I'm getting unexpected results while trying to process symbols 
from a module, some of which are enums.


Depending on whether or not I comment out the first static 
foreach loop below, fullyQualifiedName gives me different 
results in the second loop.


Looking more in detail it seems there is another peculiarity 
happening here, it could be that a template instance get reused 
(issue 14501). Not sure if it's really a bug or by design.



https://issues.dlang.org/show_bug.cgi?id=14501


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: rt/aaA.d Line: 553

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

On 2/15/20 6:49 AM, Ferhat Kurtulmuş wrote:

On Friday, 14 February 2020 at 23:41:45 UTC, Steven Schveighoffer wrote:

On 2/14/20 6:36 PM, Ferhat Kurtulmuş wrote:

 İf ((aa.used + 1)* GROW_DEN > aa.dim * GROW_NUM)
 aa.grow(ti.key);


This call is expensive (it reallocates all the buckets and reinserts 
all the existing data into the new bucket), it should be avoided if in 
the end we will not be incrementing used.




I am trying to write a gc-free AA based on the original runtime code 
(mem with malloc and free). My question is that why my version is slower 
(about 1.5 times slower) than the runtime version?


Have you ensured you are using -inline, -O, and -release? This is how 
druntime is compiled.



https://controlc.com/2e58c305

Those are some differences from runtime version:

- nogc and no typeid of course.
- does not care about postblit of key types (don't need it, assume only 
basic types are allowed for key type)


Postblit should be automatic for your code because you are doing the 
types directly.


- runtime version uses typeid to do some alignments which are not 
implemented in my version. Is that the reason why my code is slower?


No, alignments are important only if you don't have the type, which you 
do. The runtime uses void pointers and opaque structs, so it has to 
duplicate what the compiler is already doing for you.


Your code looks like a direct port, except for the allocations, so it 
should be as fast if compiled the same. Your code might even be faster, 
because it's going to be able to inline more aggressively. There may be 
issues with cache coherency, but I'm not sure how to find or diagnoce those.


I'll note that you are going to leak some memory because you are not 
freeing deleted buckets when you resize. In the GC version, the GC takes 
care of those.


-Steve


Re: How the hell to split multiple delims?

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

On 2/15/20 6:32 AM, AlphaPurned wrote:
I've tried 10 different ways with split and splitter, I've used all the 
stuff that people have said online but nothing works. I always get a 
template mismatch error.


Why is something so easy to do so hard in D?

auto toks = std.regex.split(l, Regex("s"));
auto toks = std.regex.splitter(l, Regex("s"));
auto toks = std.regex.splitter(l, ctRegex!r"\.");


What type is 'l'?

-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 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: rt/aaA.d Line: 553

2020-02-15 Thread Ferhat Kurtulmuş via Digitalmars-d-learn
On Saturday, 15 February 2020 at 14:30:20 UTC, Steven 
Schveighoffer wrote:

On 2/15/20 6:49 AM, Ferhat Kurtulmuş wrote:

On Friday, 14 February 2020 at 23:41:45 UTC, Steven


I'll note that you are going to leak some memory because you 
are not freeing deleted buckets when you resize. In the GC 
version, the GC takes care of those.


-Steve


I appreciate it for reviewing the code and your comments. Speed 
is good now. I put it on the dub db. I hope I am not violating 
any copyright. I included name of the original author (Martin 
Nowak) in the code, and explicitly stated that "betterC port of 
druntime/blob/master/src/rt/aaA.d".


What do you think about this one? I am not free-ing deleted entry 
in remove method:

https://github.com/aferust/bcaa/blob/a37b4ee4455477abc82425f32e9cf45394f4c4a1/source/bcaa.d#L228-L230

but here in resize:
https://github.com/aferust/bcaa/blob/a37b4ee4455477abc82425f32e9cf45394f4c4a1/source/bcaa.d#L190-L194

Thus, deleted buckets will wait until a resize call to free them. 
I think this is better for speed.


Re: How to get to body of HTTP 500 error with std.net.curl.get()?

2020-02-15 Thread Gregor Mückl via Digitalmars-d-learn

On Friday, 14 February 2020 at 13:23:01 UTC, Andre Pany wrote:

On Friday, 14 February 2020 at 00:24:27 UTC, Gregor Mückl wrote:

Hi!

I am trying to write a client for pretty... well... creatively 
designed web API. The server gives HTTP status 500 replies if 
the requests are malformed, but the actual error message is 
hidden in the body of the reply (an XML document!). 
std.net.curl.get() throws an exception in this case. But I 
would like to get the body to process the error message 
within. How can I do that?


Thanks in advance,
Gregor


Hi Gregor,

If I am not completely wrong, the exception has an attribute
"msg" which should contain the body of the http response.

Kind regards
André


Unfortunately, this is not true. The msg only contains the text 
information in the status line of the HTTP reply. If I'm not 
mistaken, the exception is created in this line in std/net/curl.d:


enforce(statusLine.code / 100 == 2, new 
HTTPStatusException(statusLine.code,
format("HTTP request returned status code %d (%s)", 
statusLine.code, statusLine.reason)));


If anything is wrong, the server I'm interested in tends to reply 
with a status code 500 and a generic status line text and a 
bloated XML body containing the actual error message.


Re: rt/aaA.d Line: 553

2020-02-15 Thread Ferhat Kurtulmuş via Digitalmars-d-learn
On Saturday, 15 February 2020 at 15:21:08 UTC, Ferhat Kurtulmuş 
wrote:
On Saturday, 15 February 2020 at 14:30:20 UTC, Steven 
Schveighoffer wrote:

On 2/15/20 6:49 AM, Ferhat Kurtulmuş wrote:

On Friday, 14 February 2020 at 23:41:45 UTC, Steven


Ops I ve made commits. Here are the links up to date
https://github.com/aferust/bcaa/blob/3f0f4eaf550a28b80cd95a4f2589b1f3a53fe6c0/source/bcaa.d#L193-L195

https://github.com/aferust/bcaa/blob/3f0f4eaf550a28b80cd95a4f2589b1f3a53fe6c0/source/bcaa.d#L231-L233





Re: Dscanner: is it possible to switch off style checks case-by-case?

2020-02-15 Thread Luhrel via Digitalmars-d-learn

On Thursday, 13 February 2020 at 17:15:50 UTC, mark wrote:

I'm starting out with GtkD and have this function:

void main(string[] args) {
Main.init(args);
auto game = new GameWindow();
Main.run();
}

and this method:

void quit(Widget widget) {
Main.quit();
}

When I run dscanner --styleCheck it reports:

./src/app.d(10:10)[warn]: Variable game is never used.
./src/app.d(22:22)[warn]: Parameter widget is never used.

These are correct. However, is it possible to switch them off 
individually?


(In Python you can switch off lint checks using a special text 
in a comment at the end of the line.)


With DLS, you can use @suppress in comment:

void quit(Widget widget) // 
@suppress(dscanner.suspicious.unused_parameter)

{
Main.quit();
}

more info: https://code.dlang.org/packages/dls

Simply install the extension to your editor.


Re: How to get to body of HTTP 500 error with std.net.curl.get()?

2020-02-15 Thread Anonymouse via Digitalmars-d-learn

On Saturday, 15 February 2020 at 16:25:42 UTC, Gregor Mückl wrote:
Unfortunately, this is not true. The msg only contains the text 
information in the status line of the HTTP reply. If I'm not 
mistaken, the exception is created in this line in 
std/net/curl.d:


enforce(statusLine.code / 100 == 2, new 
HTTPStatusException(statusLine.code,
format("HTTP request returned status code %d (%s)", 
statusLine.code, statusLine.reason)));


If anything is wrong, the server I'm interested in tends to 
reply with a status code 500 and a generic status line text and 
a bloated XML body containing the actual error message.


Not that it answers your question but requests[1] can do this, if 
you don't mind adding some dependencies.


Request req;
Response res = req.get(urlRespondingWith500);
assert(res.code == 500);
writeln(res.responseBody);  // Buffer!ubyte; use .to!string to 
get a string


When testing to confirm I ran into a bug[2] where the body is 
sometimes empty, but outside of fringe cases it should work.


[1]: https://code.dlang.org/packages/requests
[2]: https://github.com/ikod/dlang-requests/issues/115


Re: How to get to body of HTTP 500 error with std.net.curl.get()?

2020-02-15 Thread Boris Carvajal via Digitalmars-d-learn

On Friday, 14 February 2020 at 00:24:27 UTC, Gregor Mückl wrote:

Hi!

I am trying to write a client for pretty... well... creatively 
designed web API. The server gives HTTP status 500 replies if 
the requests are malformed, but the actual error message is 
hidden in the body of the reply (an XML document!). 
std.net.curl.get() throws an exception in this case. But I 
would like to get the body to process the error message within. 
How can I do that?


Thanks in advance,
Gregor


It seems you can't, that simple get wrapper is very limited.
Better create you own get function, example:

import std;

ushort get(string url, ref ubyte[] content)
{
auto cont = appender(&content);
auto http = HTTP();
http.method = HTTP.Method.get;
http.url = url;
http.onReceive = (ubyte[] data)
{
cont ~= data;
return data.length;
};
HTTP.StatusLine status;
http.onReceiveStatusLine = (HTTP.StatusLine s) { status = s; 
};

http.perform();
return status.code;
}

void main()
{
ubyte[] data;
auto scode = get("http://dlang.org/asdf";, data);
if (scode == 404)
{
// data has the body
...
}


Re: How the hell to split multiple delims?

2020-02-15 Thread Craig Dillabaugh via Digitalmars-d-learn

On Saturday, 15 February 2020 at 11:32:42 UTC, AlphaPurned wrote:
I've tried 10 different ways with split and splitter, I've used 
all the stuff that people have said online but nothing works. I 
always get a template mismatch error.


Why is something so easy to do so hard in D?

auto toks = std.regex.split(l, Regex("s"));
auto toks = std.regex.splitter(l, Regex("s"));
auto toks = std.regex.splitter(l, ctRegex!r"\.");


I had the same problem myself recently, and almost ended up here 
to ask the same question as you but stumbled across the following 
(ugly) solution without using regexs.


char[] line = "Split this by#space or#sign."

auto parts = line.splitter!(a => a=='#' | a==' ').array;






Re: How the hell to split multiple delims?

2020-02-15 Thread Paul Backus via Digitalmars-d-learn
On Saturday, 15 February 2020 at 22:30:03 UTC, Craig Dillabaugh 
wrote:
On Saturday, 15 February 2020 at 11:32:42 UTC, AlphaPurned 
wrote:
I've tried 10 different ways with split and splitter, I've 
used all the stuff that people have said online but nothing 
works. I always get a template mismatch error.


Why is something so easy to do so hard in D?

auto toks = std.regex.split(l, Regex("s"));
auto toks = std.regex.splitter(l, Regex("s"));
auto toks = std.regex.splitter(l, ctRegex!r"\.");


I had the same problem myself recently, and almost ended up 
here to ask the same question as you but stumbled across the 
following (ugly) solution without using regexs.


char[] line = "Split this by#space or#sign."

auto parts = line.splitter!(a => a=='#' | a==' ').array;


This works for me:

import std;
void main()
{
string line = "Split this by#space or#sign.";
auto parts = line.splitter(regex("[ #]")).array;
writeln(parts); // ["Split", "this", "by", "space", "or", 
"sign."]

}


Re: rt/aaA.d Line: 553

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

On 2/15/20 10:21 AM, Ferhat Kurtulmuş wrote:

On Saturday, 15 February 2020 at 14:30:20 UTC, Steven Schveighoffer wrote:

On 2/15/20 6:49 AM, Ferhat Kurtulmuş wrote:

On Friday, 14 February 2020 at 23:41:45 UTC, Steven


I'll note that you are going to leak some memory because you are not 
freeing deleted buckets when you resize. In the GC version, the GC 
takes care of those.




I appreciate it for reviewing the code and your comments. Speed is good 
now. I put it on the dub db. I hope I am not violating any copyright. I 
included name of the original author (Martin Nowak) in the code, and 
explicitly stated that "betterC port of druntime/blob/master/src/rt/aaA.d".


What do you think about this one? I am not free-ing deleted entry in 
remove method:
https://github.com/aferust/bcaa/blob/a37b4ee4455477abc82425f32e9cf45394f4c4a1/source/bcaa.d#L228-L230 



but here in resize:
https://github.com/aferust/bcaa/blob/a37b4ee4455477abc82425f32e9cf45394f4c4a1/source/bcaa.d#L190-L194 


Yes, that is the moment they truly become garbage (in the GC version), 
so it's where you should free them.


-Steve