Re: isExpression with bool template parameter

2013-03-25 Thread cal

On Tuesday, 26 March 2013 at 06:15:54 UTC, cal wrote:

static if (is(S!(int, 5) _  : S!(U), U...))  // line B, fail
   pragma(msg, U.stringof); // tuple(int, 5);


oops the '// line B, fail' should not be there


Re: isExpression with bool template parameter

2013-03-25 Thread cal

On Tuesday, 26 March 2013 at 06:03:55 UTC, cal wrote:
I.e., why I can't match on some generic second parameter - what 
if the second parameter was an int:


struct S(A, int B) {}
static assert(is(S!(int, 5627) _ == S!(U, ??), U, ??));

how to match that in the isExpression?

cheers,
cal


However this does work (and solves my problem):

struct S(A, int B){}

static if (is(S!(int, 5) _  : S!(U), U...))  // line B, fail
   pragma(msg, U.stringof); // tuple(int, 5);

But it seems like is(S!(int, 5) _  : S!(U, V), U, V) should work 
to me.




Re: isExpression with bool template parameter

2013-03-25 Thread cal

On Tuesday, 26 March 2013 at 05:28:22 UTC, Ali Çehreli wrote:
I am not sure that I understand but usually the test is done in 
a context like foo() below:


struct S(A, bool B) {}

void foo(T)()
{
static assert(is(T == S!(U, false), U));
}

void main()
{
foo!(S!(int, false))();
}

Ali


Maybe I gave a bad example, I guess I wonder why line A passes 
but line B fails:


struct S(A, bool B) {}

static assert(is(S!(int, false) _ == S!(U, false), U)); // line 
A, pass
static assert(is(S!(int, false) _ == S!(U, V), U, V));  // line 
B, fail


void main(){}

I.e., why I can't match on some generic second parameter - what 
if the second parameter was an int:


struct S(A, int B) {}
static assert(is(S!(int, 5627) _ == S!(U, ??), U, ??));

how to match that in the isExpression?

cheers,
cal



fullyQualifiedName doesn't work with SortedRange

2013-03-25 Thread Timothee Cour
why doesn't this compile?

import std.traits;
import std.algorithm;

void main(){
auto a=sort([1]);
enum t=fullyQualifiedName!(typeof(a));
pragma(msg,t);
}

CT error: std/traits.d(298): Error: forward reference of variable parentPrefix

Timothee Cour


Re: Possible bug

2013-03-25 Thread Steven Schveighoffer
On Tue, 26 Mar 2013 01:28:03 -0400, Sergei Nosov   
wrote:



Thank you, guys!

You made the matters clear to me!

It would be an interesting enhancement over C++.

Although, Steven, I didn't quite understand what you're suggesting to  
use in case of "templated-struct-templated-constructor"


Explicitly specifying struct parameters is ok. Deducing constructor  
parameters from arguments is also ok. But what if not all of the  
constructor parameters may be deduced? E.g. one of them is an int?


Would it be a no-no case? or should we merge the lists in one? or should  
we use two bangs? S!(int, 4)!(byte, 5)(3) ? =)


What you have to do is instantiate the template, then call the constructor:

S!(int, 4).S!(byte, 5)(3)

Note that the way templates work in D, a templated struct is really a  
shortcut for:


template S(T)
{
   struct S { ... }
}

So when you instantiate it, S!(int)(5) is really shorthand for  
S!(int).S(5).


Every template is this way.  The shorthand version calls on the  
"eponymous" member implicitly, that is, the member with the same name as  
the template.  Currently, this only works if there is exactly one member.


For example, a function template is really:

template foo(T)
{
   void foo(T t) {...}
}

So doing:

foo!(int)(1)

is really the same as:

foo!(int).foo(1)

It's all outlined here: http://dlang.org/template.html

search for Implicit Template Properties

-Steve


Re: isExpression with bool template parameter

2013-03-25 Thread Ali Çehreli

On 03/25/2013 04:57 PM, cal wrote:


Trying to figure out how to pattern-match struct S below with an
isExpression:

struct S(A, bool B) {}

static assert ( !is(S!(int, false) _ == S!(U, bool), U) );
static assert ( !is(S!(int, false) _ == S!(U, V), U, V) );
static assert ( !is(S!(int, false) _ == S!(U, V), U, V : bool) );

void main(){}

Can someone help?


I am not sure that I understand but usually the test is done in a 
context like foo() below:


struct S(A, bool B) {}

void foo(T)()
{
static assert(is(T == S!(U, false), U));
}

void main()
{
foo!(S!(int, false))();
}

Ali


Re: Possible bug

2013-03-25 Thread Sergei Nosov

Thank you, guys!

You made the matters clear to me!

It would be an interesting enhancement over C++.

Although, Steven, I didn't quite understand what you're 
suggesting to use in case of 
"templated-struct-templated-constructor"


Explicitly specifying struct parameters is ok. Deducing 
constructor parameters from arguments is also ok. But what if not 
all of the constructor parameters may be deduced? E.g. one of 
them is an int?


Would it be a no-no case? or should we merge the lists in one? or 
should we use two bangs? S!(int, 4)!(byte, 5)(3) ? =)


Re: Question about auto ref

2013-03-25 Thread Namespace
You make me curious about this new attribute. Maybe I could then 
help to implement this along with its task.

I do not think anyone else has the time to do it.
I hope that you will find the link.


Re: Question about auto ref

2013-03-25 Thread Jonathan M Davis
On Tuesday, March 26, 2013 00:52:56 Namespace wrote:
> Forgot to ask:
> Wouldn't it be better to publish this decision?
> Many still believe the nonsense (like me) that 'auto ref' is
> still the solution.

An official decision would mean that Walter had been involved in it, and that 
hasn't happened. IIRC, Andrei said something positive about the temporary 
approach when it was brought up, but AFAIK, no official decision has been made.
It's just that it became clear when discussing it that if we wanted to go with 
the temporary trick (which looks like the best solution), it really should 
apply to both templated and non-templated functions and that auto ref needs to 
retain its current meaning for templated functions, which then means that we 
need a new attribute. I suppose that we could always create a DIP for it 
though.

- Jonathan M Davis


Re: Question about auto ref

2013-03-25 Thread Namespace

Forgot to ask:
Wouldn't it be better to publish this decision?
Many still believe the nonsense (like me) that 'auto ref' is 
still the solution.


Re: Possible bug

2013-03-25 Thread Steven Schveighoffer

On Mon, 25 Mar 2013 17:13:58 -0400, Ali Çehreli  wrote:


On 03/25/2013 12:40 PM, Steven Schveighoffer wrote:
 > On Mon, 25 Mar 2013 11:31:17 -0400, Ali Çehreli   
wrote:

 >
 >> This design allows templated constructors:
 >>
 >> struct S // <-- not a template
 >> {
 >> this(T)(T t) // <-- template
 >> {
 >> // ...
 >> }
 >>
 >> // ...
 >> }
 >>
 >> The same in C++...
 >
 > Templated constructors would not be disallowed if you allowed IFTI on
 > templated structs/classes without templated constructors.

It would complicate matters: The parameter would be for the constructor  
if the constructor were a template, for the struct otherwise.


In cases where the struct is templated and the constructor is not, it  
would apply to the struct.  In cases where the struct is concrete and the  
constructor is templated, it would apply to the constructor.  In the case  
where the struct is templated AND the constructor is templated, it would  
require the struct to have an explicit instantiation.


This is not complex, nor unintuitive.


 > When you decompose constructors, they are simply fucntions, and IFTI
 > exists on functions. The same should be allowed for constructors.

I completely agree and that's my point. :) The template parameter list  
of the constructor should stay with the constructor.


In the rare cases where the struct and the constructor are templated, it  
will stay with the constructor.



 > There is almost no difference between this:
 >
 > template foo(T){
 > void foo(T t) {}
 > }
 >
 > and this:
 >
 > struct foo(T){
 > this(T t) {}
 > }

Actually, the latter is a shorthand for this:

template S(T)
{
 struct S
 {
 T t;

 this(U)(U)
 {}
 }
}


No, it is shorthand for this:

template foo(T)
{
   struct foo
   {
  this(T t) {}
   }
}

Note there is only ONE template type.

For your case, the shorthand would be:

struct S(T)
{
   this(U)(U u) {}
}



As you see, T comes from the outer template and U stays with the  
constructor. It allows the following use:


void main()
{
 auto s = S!int(byte.init);
}


This would be required if both struct and constructor are templated (and  
rightly so).


-Steve


Re: Question about auto ref

2013-03-25 Thread Namespace

I appreciate your efforts and look forward to the link. :)
But I never heard anything about that. How long has it been since 
that was suggested?


But that's honestly sad to hear. I thought I would contribute to 
the solution of this problem. Then we'll have to wait and 
continue to hope.


Re: Efficiency of using array as stack

2013-03-25 Thread Ivan Kazmenko

You will likely get better performance if you use:

a ~= int.init;

instead of:

a.length++;


So that's a relief, a dynamic array in D actually *is* an 
efficient queue implementation out of the box, I just did it 
improperly in the example.  Thank you for the correction.  With 
that, the number of relocations in the queue example dropped down 
to 2.


growth of 1024 is when the new pages are tacked onto the end 
(4096 / sizeof(int)), growth of 891 is interesting.  I can 
explain it though :)


Thank you for the very detailed explanation!  Knowing how things 
work down to the bare bones, and the rationale behind that, is 
definitely helpful, both logically (to write better code) and 
psychologically (the feeling of things in control).  I just hope 
such quality explanations will be incorporated into some book or 
manual someday.


-
Ivan Kazmenko.


Re: When to call setAssertHandler?

2013-03-25 Thread Sean Kelly
On Mar 22, 2013, at 2:58 AM, Benjamin Thaut  wrote:

> So I want to install my own assertHandler. The problem is, that even if I 
> call "setAssetHandler" in a shared module constructor, and that module does 
> not import any other modules, it is still not initialized first. Is there a 
> way to set the assert before any module constructors run without hacking 
> druntime?

I'm afraid not.  I suppose this is a case I should have handled, but it didn't 
occur to me at the time.

Re: Can std.json handle Unicode?

2013-03-25 Thread Sean Kelly
On Mar 23, 2013, at 5:22 AM, Jacob Carlborg  wrote:

> I'm wondering because I see that std.json uses isControl, isDigit and 
> isHexDigit from std.ascii and not std.uni. This also causes a problem with a 
> pull request I recently made for std.net.isemail. In one of its unit tests 
> the DEL character (127) is used. According to std.ascii.isControl this is a 
> control character, but not according to std.uni.isControl. This will cause 
> the test suite for the pull request not to be run since std.json chokes on 
> the DEL character.

I don't know about control characters, but std.json doesn't handle UTF-16 
surrogate pairs in strings, which are legal JSON.  I *think* it does properly 
handle the 32 bit code points though.

Re: Question about auto ref

2013-03-25 Thread Jonathan M Davis
On Monday, March 25, 2013 23:35:06 Namespace wrote:
> > Because the number of instantiations of the template could grow
> > exponentially
> > as the number of auto ref parameters grows. Being able to use
> > the trick with
> > the temporary with templated functions could really help reduce
> > template bloat
> > when the current meaning of auto ref is not necessary, but that
> > means coming
> > up with a new attribute rather than reusing auto ref with
> > non-templated
> > functions.
> 
> I use the "trick" with the temporary. But why introduce rather a
> new attribute?
> I thought the real reason why auto ref was first introduced was
> to solve the rvalue ref problem. Now we could do it. So what's
> wrong with auto ref for non-
> template functions?
> I'm afraid that the introducing of a new attribute means to spend
> a lot of time. Is that really needed? :/ Or am I wrong?

The problem is that we need the temporary trick with templated functions as 
well as non-templated functions. auto ref on templated functions as it stands 
is great for creating parameters that retaining all of the attributes on a 
type - including refness - but it causes template bloat, which in the case 
that auto ref was originally intended to solve is completely unnecessary. The 
temporary trick will work just fine for that, but you can't use auto ref for 
that on templated functions, because we'd lose out on what it currently does, 
which is needed for forwarding arguments (much as it was accidental that we 
got that ability). So, in order to have the temporary trick with templated 
functions, we need a new attribute. That being the caes, there's no point in 
implementing auto ref for non-templated functions, as they should just use the 
same attribute as would be used with template functions.

> I haven't heard of it.
> Would be very nice if you could do it and post the link. :)

I can try, but the search of my e-mail client sucks, so it's always a pain for 
me to find anything in old posts.

- Jonathan M Davis


Named Tuple Names

2013-03-25 Thread Jonathan Crapuchettes
Is there a way to get the names of the fields in a named tuple? It looks 
like the names are actually aliases.

Thanks,
JC


Re: Question about auto ref

2013-03-25 Thread Namespace
Because the number of instantiations of the template could grow 
exponentially
as the number of auto ref parameters grows. Being able to use 
the trick with
the temporary with templated functions could really help reduce 
template bloat
when the current meaning of auto ref is not necessary, but that 
means coming
up with a new attribute rather than reusing auto ref with 
non-templated

functions.
I use the "trick" with the temporary. But why introduce rather a 
new attribute?
I thought the real reason why auto ref was first introduced was 
to solve the rvalue ref problem. Now we could do it. So what's 
wrong with auto ref for non-

template functions?
I'm afraid that the introducing of a new attribute means to spend 
a lot of time. Is that really needed? :/ Or am I wrong?


Andrei is flat out against this. I wouldn't expect that te over 
happen.

Good to know.

We pretty much need a new attribute. IIRC, Kenji had a 
suggestion for what it
would be, but I don't remember what it was now. I'd have to go 
digging through

the archives to find it.

- Jonathan M Davis


I haven't heard of it.
Would be very nice if you could do it and post the link. :)


Re: Question about auto ref

2013-03-25 Thread Jonathan M Davis
On Monday, March 25, 2013 20:43:29 Namespace wrote:
> > Basically, someone needs to implement it and then talk Walter
> > into accepting
> > it. That'll be easier for someone like Kenji, who's already a
> > major
> > contributor, but in theory, anyone can do it. It's just that
> > there's a high
> > risk that the pull request would languish for a while. And it
> > would probably
> > need to be implemented with a name other than auto ref in order
> > to avoid the
> > aforementioned problems, and having to agree on that could
> > cause further
> > delay.
> 
> I am currently working in the required part of the compiler, but
> I need help and other opinions.
> So far I've tried both: an implementation for auto ref and ref
> const.
> 
> -> auto ref:
> auto ref for non-template functions. In this case (as you had
> suggested it once) temporary variables are created for rvalues.
> Thus the behavior of auto ref would be different for template and
> non-template functions. But I do not see how that would be
> problematic.

Because the number of instantiations of the template could grow exponentially 
as the number of auto ref parameters grows. Being able to use the trick with 
the temporary with templated functions could really help reduce template bloat 
when the current meaning of auto ref is not necessary, but that means coming 
up with a new attribute rather than reusing auto ref with non-templated 
functions.

> -> ref const:
> const ref creates for rvalues a temporary variable that is then
> passed to the function. Advantage: It is like C++. Disadvantage:
> it could break code and you get always a const parameter.

Andrei is flat out against this. I wouldn't expect that te over happen.

> As I said, I've tried both ways before. But I like to hear other
> opinions which of both would be more preferred.
> And I would be glad about any kind of help (looking on my code
> etc.).
> Maybe we could convince Walter and Andrei with a finished
> implementation.
> I hope that no one like to have a new syntax for this kind of
> thing because then we will discuss another year...

We pretty much need a new attribute. IIRC, Kenji had a suggestion for what it 
would be, but I don't remember what it was now. I'd have to go digging through 
the archives to find it.

- Jonathan M Davis


Re: Possible bug

2013-03-25 Thread Ali Çehreli

On 03/25/2013 12:40 PM, Steven Schveighoffer wrote:
> On Mon, 25 Mar 2013 11:31:17 -0400, Ali Çehreli  
wrote:

>
>> This design allows templated constructors:
>>
>> struct S // <-- not a template
>> {
>> this(T)(T t) // <-- template
>> {
>> // ...
>> }
>>
>> // ...
>> }
>>
>> The same in C++...
>
> Templated constructors would not be disallowed if you allowed IFTI on
> templated structs/classes without templated constructors.

It would complicate matters: The parameter would be for the constructor 
if the constructor were a template, for the struct otherwise.


> When you decompose constructors, they are simply fucntions, and IFTI
> exists on functions. The same should be allowed for constructors.

I completely agree and that's my point. :) The template parameter list 
of the constructor should stay with the constructor.


> There is almost no difference between this:
>
> template foo(T){
> void foo(T t) {}
> }
>
> and this:
>
> struct foo(T){
> this(T t) {}
> }

Actually, the latter is a shorthand for this:

template S(T)
{
struct S
{
T t;

this(U)(U)
{}
}
}

As you see, T comes from the outer template and U stays with the 
constructor. It allows the following use:


void main()
{
auto s = S!int(byte.init);
}

>
> -Steve

Ali



Re: Question about auto ref

2013-03-25 Thread Namespace
Basically, someone needs to implement it and then talk Walter 
into accepting
it. That'll be easier for someone like Kenji, who's already a 
major
contributor, but in theory, anyone can do it. It's just that 
there's a high
risk that the pull request would languish for a while. And it 
would probably
need to be implemented with a name other than auto ref in order 
to avoid the
aforementioned problems, and having to agree on that could 
cause further

delay.


I am currently working in the required part of the compiler, but 
I need help and other opinions.
So far I've tried both: an implementation for auto ref and ref 
const.


 -> auto ref:
auto ref for non-template functions. In this case (as you had 
suggested it once) temporary variables are created for rvalues. 
Thus the behavior of auto ref would be different for template and 
non-template functions. But I do not see how that would be 
problematic.


 -> ref const:
const ref creates for rvalues a temporary variable that is then 
passed to the function. Advantage: It is like C++. Disadvantage: 
it could break code and you get always a const parameter.


As I said, I've tried both ways before. But I like to hear other 
opinions which of both would be more preferred.
And I would be glad about any kind of help (looking on my code 
etc.).
Maybe we could convince Walter and Andrei with a finished 
implementation.
I hope that no one like to have a new syntax for this kind of 
thing because then we will discuss another year...


Re: Possible bug

2013-03-25 Thread Steven Schveighoffer

On Mon, 25 Mar 2013 11:31:17 -0400, Ali Çehreli  wrote:


This design allows templated constructors:

struct S // <-- not a template
{
 this(T)(T t) // <-- template
 {
 // ...
 }

 // ...
}

The same in C++...


Templated constructors would not be disallowed if you allowed IFTI on  
templated structs/classes without templated constructors.


When you decompose constructors, they are simply fucntions, and IFTI  
exists on functions.  The same should be allowed for constructors.


There is almost no difference between this:

template foo(T){
   void foo(T t) {}
}

and this:

struct foo(T){
   this(T t) {}
}

-Steve


Re: Possible bug

2013-03-25 Thread Steven Schveighoffer

On Mon, 25 Mar 2013 11:11:40 -0400, Sergei Nosov 
wrote:


On Monday, 25 March 2013 at 14:12:17 UTC, bearophile wrote:

Sergei Nosov:


Everything's fine if I specify parameters explicitly:

test!int hello = test!int(cptr);



Some persons have proposed alternative designs, but D is working as  
currently designed here... Unlike template functions, templated structs  
don't infer the type.


Bye,
bearophile


Thx, is there any good rationale?


There really isn't.  I have created an enhancement request that you might
be interested in voting for.

http://d.puremagic.com/issues/show_bug.cgi?id=6082

Note that auto is your friend here to avoid the dual-specification of the  
template:


auto hello = test!int(cptr);

And you can always create a wrapper function:

test!T mktest(T)(T *ptr) { return test!T(ptr);}

...

auto hello = mktest(cptr); // no explicit instantiation required

-Steve


Thrift D bindings: make check broken under ubuntu 12.04. Where to report?

2013-03-25 Thread J

Where or to whom should I report a bug in the thrift D bindings?

In recent ubuntu, the maintainers inexplicably changed the linker 
(ld) defaults to --as-needed, which breaks the 'make check' for 
Thrifts D binding, presumably because they are using some kind of 
'indirect' linking.


reproduction:

~/pkg/thrift/thrift/lib/d$ make check # using dmd 2.062 on 
x86_64. (thrift at a recent version; 3c434ab87d).

...
dmd -gc -ofunittest/debug/thrift/server/transport/ssl -unittest 
-w -wi -I../../lib/d/src -L-levent -L-lssl -L-lcrypto 
src/thrift/server/transport/ssl.d libthriftd-event.a 
libthriftd-ssl.a libthriftd.a unittest/emptymain.d
libthriftd-ssl.a(ssl_3cd_3af.o): In function 
`_D6thrift9transport3ssl10TSSLSocket6isOpenMFNdZb':
src/thrift/transport/ssl.d:(.text._D6thrift9transport3ssl10TSSLSocket6isOpenMFNdZb+0x71): 
undefined refe\

rence to `SSL_get_shutdown'
...

I can fix this by

1. putting "DFLAGS_PRE=-L--no-as-needed" in dmd.conf and using a 
dmd branch that makes DFLAGS_PRE work: 
https://github.com/glycerine/dmd/tree/fix_9805 All this does is 
pre-pend (instead of append) the contents of DFLAGS_PRE to the 
dmd command line.


or

2. manually compiling with dmd --no-as-needed ... (which is 
painful, hence the #1 step above is vastly preferred)


but somebody smarter than me should probably have a look at the 
linking in the 'make check' for D's thrift bindings and try to 
make it work even without --no-as-needed.


-J


Re: Possible bug

2013-03-25 Thread Ali Çehreli

On 03/25/2013 08:11 AM, Sergei Nosov wrote:
> On Monday, 25 March 2013 at 14:12:17 UTC, bearophile wrote:
>> Sergei Nosov:
>>
>>> Everything's fine if I specify parameters explicitly:
>>> 
>>> test!int hello = test!int(cptr);
>>> 
>>
>> Some persons have proposed alternative designs, but D is working as
>> currently designed here... Unlike template functions, templated
>> structs don't infer the type.
>>
>> Bye,
>> bearophile
>
> Thx, is there any good rationale?

This design allows templated constructors:

struct S // <-- not a template
{
this(T)(T t) // <-- template
{
// ...
}

// ...
}

The same in C++...

Ali



Re: Efficiency of using array as stack

2013-03-25 Thread Steven Schveighoffer
If you happened to get that accidental blank send, sorry, I tried to  
cancel it.


On Sat, 23 Mar 2013 19:45:21 -0400, Ivan Kazmenko  wrote:


On Saturday, 23 March 2013 at 19:33:06 UTC, Jonathan M Davis wrote:
You might want to check out this article where someone ran into similar  
issues:


https://www.semitwist.com/articles/article/view/don-t-use-arrays-as-stacks

And if you haven't read Steven's article on arrays, you should do so:

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


That was a good reading, thank you!  The whole matter became clearer for  
me.


But now, I have one more example which confuses me, and the articles  
don't seem to help right away with it.  In this example, I am moving a  
"sliding window" of length n; now that we're done with the stack, here  
is a simple usage pattern of the queue.  What I do is repeatedly (n  
times also) add an element to the back of the array and then remove an  
element from the front of it, keeping the whole queue constantly large.   
Before the start, I reserve c*n entries for my array, where c is a real  
number between 1 and 2.  I track reallocations by monitoring the address  
of an element of a which should remain still as long as the array is not  
reallocated.


-
import std.algorithm;
import std.array;
import std.range;
import std.stdio;

void main ()
{
int n = 2_000_000;
double c = 1.5;
auto a = array (iota (n));
a.reserve (cast (int) (n * c));
auto prev = &a[$ - 1];
int changes = 0;
foreach (i; 0..n)
{
debug {writeln (a.capacity);}
a.length++;
a = a[1..$];
auto next = &a[$ - i - 1];
if (prev != next)
{
changes++;
prev = next;
}
}
writeln (changes);
}
-

Now, if I set c to 2, there are no reallocations: all the work goes with  
the 2*n pre-allocated elements.  But as I decrease c down to 1, the  
number of reallocations grows *linearly*, roughly 1 per 2000 appends.   
So for c = 1, there are 1044 reallocations in total.  And that's still  
quadratic behavior, albeit divided by a large constant (~2000)!


So here is how the appender tries to add data:

1. if the block is less than a page, memory is tracked as a bin of  
like-sized blocks that fit into a page.  Starting at 16-byte blocks, then  
doubling until you reach half-page size.  So if you need something that  
consumes less than 16-bytes, a 16-byte chunk is allocated out of a 16-byte  
bin (which is a page that has nothing but 16-byte chunks in it).
2. When you reallocate to a larger block size (16 to 32 for instance), the  
block MUST be moved into another bin, because only 16-byte blocks are  
allowed in that bin.
3. When you get to PAGE size (4096 bytes) and larger, the appender takes a  
different approach:
   a. If the page following your block is unallocated, and it can simply  
extend the block into that next page, it will do so.  This avoids copying  
the data to another block, which arguably would be more expensive than  
trying to double the capacity (not sure if this is true, but that's how it  
works).
   b. If not, it will reallocate into a new or existing empty block that  
can hold the entire data, plus some additional space calculated by an  
algorithm that is not quite double, but aims to amortize appending (if you  
search in the lifetime.d file in druntime, look for newCapacity to find  
the function that calculates this extra space).


HOWEVER, setting the length is NOT considered appending by the runtime.   
The runtime takes a different approach when just setting the length -- it  
does NOT add any extra capacity to try and amortize the allocations.  The  
idea is that you set the length usually once, and then use the array  
without appending.  It is more efficient if you are appending to give it  
the elements to append rather than zero-init them first.


You will likely get better performance if you use:

a ~= int.init;

instead of:

a.length++;

What happens (locally) is, once the array size is not enough, it starts  
being grown by blocks of 1024 or 891 (?!) elements in a repeating  
pattern; one of these reallocates, the other does not.  The textbook  
growth implementation suggests doubling the array size, but it looks  
like D attempts something smarter here.  However, in my case, the result  
is ~8x slower behavior when not pre-allocating.  The more is n, the  
slower is the version without pre-allocation (c = 1) compared to the  
version with pre-allocation (c = 2).  And this means that a D array is  
not also an efficient queue out-of-the-box.  However, as in the case  
with stack, it could perhaps be efficient with a bit of tweaking (some  
custom tailored calls to reserve perhaps?).


growth of 1024 is when the new pages are tacked onto the end (4096 /  
sizeof(int)), growth of 891 is interesting.  I can explain it

Re: Possible bug

2013-03-25 Thread Sergei Nosov

On Monday, 25 March 2013 at 14:12:17 UTC, bearophile wrote:

Sergei Nosov:


Everything's fine if I specify parameters explicitly:

test!int hello = test!int(cptr);



Some persons have proposed alternative designs, but D is 
working as currently designed here... Unlike template 
functions, templated structs don't infer the type.


Bye,
bearophile


Thx, is there any good rationale?


Re: Possible bug

2013-03-25 Thread bearophile

Sergei Nosov:


Everything's fine if I specify parameters explicitly:

test!int hello = test!int(cptr);



Some persons have proposed alternative designs, but D is working 
as currently designed here... Unlike template functions, 
templated structs don't infer the type.


Bye,
bearophile


Possible bug

2013-03-25 Thread Sergei Nosov

Hi!

This code doesn't compile with dmd v2.062 on Linux_x86_64


struct test(T)
{
T *data_;
this(T *data) {
data_ = data;
}
}

void main()
{
int *cptr = null;
test!int hello = test(cptr);
}


Error:
dmd test.d
test.d(12): Error: struct test.test does not match any function 
template declaration. Candidates are:

test.d(2):test.test(T)
test.d(12): Error: struct test.test(T) cannot deduce template 
function from argument types !()(int*)


Everything's fine if I specify parameters explicitly:

test!int hello = test!int(cptr);