Re: They are not the same

2014-04-04 Thread Meta

On Saturday, 5 April 2014 at 01:57:59 UTC, Meta wrote:
When I put a println inside both functions, they both print out 
[2, 1, 0]. Shouldn't the first print [0, 1, 2] while the second 
prints [2, 1, 0]?


No, sorry, I was mistaken about what was going on.


Re: They are not the same

2014-04-04 Thread Meta

On Saturday, 5 April 2014 at 01:28:06 UTC, bearophile wrote:

Can you spot the difference between foo1 and foo2?


import std.algorithm: map;
import std.range: iota;

void foo1(in int[] a, in int[] b) pure {
int[] r;
foreach (immutable i; 0 .. a.length)
r ~= (i % 2) ? a[i] : b[i];
}

void foo2(in int[] a, in int[] b) pure {
int[] r;
foreach (x; iota(a.length)
.map!(i => (i % 2) ? a[i] : b[i]))
r ~= x;
}

void main() {}



Sometimes variants of this problem hit me. I don't even know if 
this simple problem has a name. Is it impossible to solve?


Bye,
bearophile


When I put a println inside both functions, they both print out 
[2, 1, 0]. Shouldn't the first print [0, 1, 2] while the second 
prints [2, 1, 0]?


Re: two questions on enums

2014-04-04 Thread Eric

By using the interface,

it also
forces the user to include all of the attributes of each pin 
such as
direction, max load, DC current, etc.  Since class type enums 
are references,
they are light, - and they should be immutable - so they are 
thread safe aslo.


I'm not sure how you're using your enum. In Java, the only way 
to perform a switch over an enum is if you know all the values 
during compile time. Passing a type Enum into a function (i.e. 
as opposed to "enum MyEnumType') requires using introspection 
to pull the actual values out, and then a loop to scan through 
them for your target value.


But if you've programmed a switch for a known enum type, then 
that means the enum has already been implemented and there is 
no chance for more than one type to be passed in.


So I'm confused.


I guess D does not see enums as enums, but rather as whatever
type the enum happens to implement. In java, all enums are
of enum type.  So it's probably me that's confused.

-Eric




They are not the same

2014-04-04 Thread bearophile

Can you spot the difference between foo1 and foo2?


import std.algorithm: map;
import std.range: iota;

void foo1(in int[] a, in int[] b) pure {
int[] r;
foreach (immutable i; 0 .. a.length)
r ~= (i % 2) ? a[i] : b[i];
}

void foo2(in int[] a, in int[] b) pure {
int[] r;
foreach (x; iota(a.length)
.map!(i => (i % 2) ? a[i] : b[i]))
r ~= x;
}

void main() {}



Sometimes variants of this problem hit me. I don't even know if 
this simple problem has a name. Is it impossible to solve?


Bye,
bearophile


Re: two questions on enums

2014-04-04 Thread Chris Williams

On Thursday, 3 April 2014 at 23:16:14 UTC, Eric wrote:
Okay - I'm new to D, and I'm comming from a java background.  
Suppose
you are designing an API, and you want the user to supply 
arguments
as an enum.  But the user needs to define the enum, so how can 
the API
know in advance what enum to require?  The solution is to 
require an
enum that implements a known interface.  This is easy to do in 
java,
but I haven't yet tried it in D.  I suspect it could be done 
with CTFE
or something.  An example where I use this is for electronics 
software.
If I need the user to supply a set of pins, the pins are 
supplied as an
enum which implements an interface.  By using the interface, it 
also
forces the user to include all of the attributes of each pin 
such as
direction, max load, DC current, etc.  Since class type enums 
are references,
they are light, - and they should be immutable - so they are 
thread safe aslo.


I'm not sure how you're using your enum. In Java, the only way to 
perform a switch over an enum is if you know all the values 
during compile time. Passing a type Enum into a function (i.e. as 
opposed to "enum MyEnumType') requires using introspection to 
pull the actual values out, and then a loop to scan through them 
for your target value.


But if you've programmed a switch for a known enum type, then 
that means the enum has already been implemented and there is no 
chance for more than one type to be passed in.


So I'm confused.


templates, enums, CT reflection: compiler bug or not?

2014-04-04 Thread captaindet

i stumbled upon something strange while wondering around meta/codegen-lands. it 
took me almost a week to reduce it to the following test case. i have no clue 
what is going on, whether i have entered bug territory or just encountered my 
own limitations

mind you, i have 2 issues with the code:
 
(1) that my template, which uses  __traits(compiles, ...), under certain circumstances (aka 'if things are getting complicated') fails to see symbols that one could argue are valid in this scope. (annoying maybe, but not my main problem)


(2) the strange compiler error i get when using the template on itself, but 
only if it is not the first time that the instantiation is used. this is my 
real issue cause i don't know how to work around this. during my attempts to 
reduce this, starting from much more complicated code, i encountered all sorts 
of errors, including ICE and __error stuff.

so am i being stupid or is it a compiler bug?

cheers,
det

===CODE===

module demo;

template valid(string mem){
pragma(msg, "instantiation of valid with: "~mem);
static if( !__traits( compiles, mixin(mem) ) ){
enum valid = false;
}else{
enum valid =  true;
 }
}

enum ok = valid!"foo";
pragma(msg, ok );   // -> true // fine, recognizes 'foo' in module 
scope

enum works = valid!"fails";
pragma(msg, works );// -> false // problematic, fails to see 
'fails' in module scope

enum dummy = valid!"fails";
pragma(msg, dummy );// -> false // same behavior, as long as you 
are not testing yourself

enum fails = valid!"fails"; // Error: variable demo.fails had semantic 
errors when compiling
// NOTE: if you comment out the first two usages of valid!"fails", it will work 
here,
// although it will result in "false"

//  pragma(msg, fails );

enum foo = 42;

void main(){}


Re: std.array.array seems to return flatten copy of input

2014-04-04 Thread Olivier Grant

Sorry Steven,

I hadn't seen your answer.

Thanks for the extra information.

O.

On Friday, 4 April 2014 at 20:42:32 UTC, Steven Schveighoffer 
wrote:
On Fri, 04 Apr 2014 16:35:57 -0400, Olivier Grant 
 wrote:


That is one responsive D community :) Thank you to all three 
of you for these quick answers.


I was really scratching my head on that one. This shows that 
UFCS can be quite dangerous. Is there any way to hide 
Splicer.array to the outside world? It just seems that it 
would be very easy to break client code by updating your 
implementation if you end up using a name that is already used 
elsewhere and accessed using UFCS.


I advise to call it _array to prevent such issues.

Note, you can make the field private, but that is a 
module-level directive. In order for it to apply, main would 
have to be in a separate module.


In that case, the code would simply fail to compile. As a rule, 
members ALWAYS have precedence over UFCS functions.


-Steve




Re: Manually-allocated memory and maximum array capacity

2014-04-04 Thread Artur Skawina
On 04/05/14 00:54, Joseph Rushton Wakeling wrote:
> Hello all,
> 
> If we change the length of a dynamic array using the normal GC-based methods, 
> e.g. by setting the array's .length property, we find that the array's 
> capacity typically does not simply equal the length, but some greater value; 
> there is excess allocation.
> 
> Question: is there a comparable phenomenon for memory that is manually 
> allocated using malloc?  That is, that if we specify a particular number of 
> bytes to allocate, it may be rounded up to a particular larger number?
> 
> And, if so -- is there any way of guaranteeing what that larger number will 
> be?
> 
> The reason I ask is because, suppose that I use a dynamic array as a 
> fixed-size buffer, and that its minimum size must be n.  So, I can do:
> 
> arr.length = n;
> if (arr.capacity > arr.length)
> {
> arr.length = arr.capacity;
> }
> 
> ... and get the largest possible buffer that is at least size n, but does not 
> allocate any more memory than setting length = n.
> 
> I'm wondering if I can do something similar with manual memory allocation.

Not portably, as it will be libc and/or allocator specific.

For example, for glibc this would work:

   /* static if (using_glibc) */
   size_t capacity(const void* p) @property @safe { 
  return malloc_usable_size(p);
   }

artur


Re: Manually-allocated memory and maximum array capacity

2014-04-04 Thread bearophile

Joseph Rushton Wakeling:

Question: is there a comparable phenomenon for memory that is 
manually allocated using malloc?


Manually allocated memory can over-allocate, but not 
geometrically as arrays do.


Take a look at the difference between core.memory.extend and 
core.memory.realloc.


Bye,
bearophile


Manually-allocated memory and maximum array capacity

2014-04-04 Thread Joseph Rushton Wakeling

Hello all,

If we change the length of a dynamic array using the normal GC-based methods, 
e.g. by setting the array's .length property, we find that the array's capacity 
typically does not simply equal the length, but some greater value; there is 
excess allocation.


Question: is there a comparable phenomenon for memory that is manually allocated 
using malloc?  That is, that if we specify a particular number of bytes to 
allocate, it may be rounded up to a particular larger number?


And, if so -- is there any way of guaranteeing what that larger number will be?

The reason I ask is because, suppose that I use a dynamic array as a fixed-size 
buffer, and that its minimum size must be n.  So, I can do:


arr.length = n;
if (arr.capacity > arr.length)
{
arr.length = arr.capacity;
}

... and get the largest possible buffer that is at least size n, but does not 
allocate any more memory than setting length = n.


I'm wondering if I can do something similar with manual memory allocation.

Thanks in advance for any comments and advice!

Best wishes,

-- Joe


A simplification error when calculating array lengths

2014-04-04 Thread Ali Çehreli
(This was in C and probably a common mistake that I haven't experienced 
until today.)


tldr; The following two expressions are not equivalent:

  a)length - 1 - length / 2
  b)length / 2 - 1

I was trying to write a recursive function similar to binary search:

- Process the middle element

- Call the same function with the left half

- Call the same function with the right half

void foo(int * arr, size_t length)
{
if (!length) {
return;
}

// Process the middle element
process(arr[length / 2]);

// Handle the left side
foo(arr, length / 2);

// Handle the right side (+1 to skip the middle element)
foo(arr + length / 2 + 1, /* ??? */);
}

What should be the length of the right half on the last line? Minus 1 
for the already-processed middle element and minus length/2 for the left 
half:


  a)length - 1 - length / 2

That seems to be correct. Then I simplified:

  b)length / 2 - 1

And that was a mistake because b produces size_t.max when length==1 to 
begin with. So, the calculations a and b are not equivalent. You knew it 
already ;) but it surprised me today.


Also, this is not an issue with D's slices because slices remove the 
need for such calculations:


foo(arr[$ / 2 + 1 .. $]);// Simple and correct

Which also means that maybe I should have used a pair of pointers in the 
original function instead of a pointer and a length.


Ali


Re: std.array.array seems to return flatten copy of input

2014-04-04 Thread Olivier Grant
Yes, that definitely seems like a good start. To be honest, I not 
familiar enough yet with how you are suppose to organise your 
source code in D.


Is there any agreed-on naming convention when it comes to member 
variables to avoid that kind of name clash ?


Thanks,

O.

On Friday, 4 April 2014 at 20:44:36 UTC, bearophile wrote:

Olivier Grant:


Is there any way to hide Splicer.array to the outside world?


If your splice is inside another module, and you tag the array 
field with private, you will receive an error:



auto splice( size_t N, R )( R range )
   if(isInputRange!R)
{
   struct Splicer
   {
  private R array;


This avoids your mistake, but also forbids you to use the 
std.array.array on a splice with UFCS. Is this acceptable for 
you?


Bye,
bearophile




Re: std.array.array seems to return flatten copy of input

2014-04-04 Thread bearophile

Olivier Grant:


Is there any way to hide Splicer.array to the outside world?


If your splice is inside another module, and you tag the array 
field with private, you will receive an error:



auto splice( size_t N, R )( R range )
   if(isInputRange!R)
{
   struct Splicer
   {
  private R array;


This avoids your mistake, but also forbids you to use the 
std.array.array on a splice with UFCS. Is this acceptable for you?


Bye,
bearophile


Re: std.array.array seems to return flatten copy of input

2014-04-04 Thread Steven Schveighoffer
On Fri, 04 Apr 2014 16:35:57 -0400, Olivier Grant  
 wrote:


That is one responsive D community :) Thank you to all three of you for  
these quick answers.


I was really scratching my head on that one. This shows that UFCS can be  
quite dangerous. Is there any way to hide Splicer.array to the outside  
world? It just seems that it would be very easy to break client code by  
updating your implementation if you end up using a name that is already  
used elsewhere and accessed using UFCS.


I advise to call it _array to prevent such issues.

Note, you can make the field private, but that is a module-level  
directive. In order for it to apply, main would have to be in a separate  
module.


In that case, the code would simply fail to compile. As a rule, members  
ALWAYS have precedence over UFCS functions.


-Steve


Re: std.array.array seems to return flatten copy of input

2014-04-04 Thread Olivier Grant
That is one responsive D community :) Thank you to all three of 
you for these quick answers.


I was really scratching my head on that one. This shows that UFCS 
can be quite dangerous. Is there any way to hide Splicer.array to 
the outside world? It just seems that it would be very easy to 
break client code by updating your implementation if you end up 
using a name that is already used elsewhere and accessed using 
UFCS.



Thanks,

O.

On Friday, 4 April 2014 at 20:29:28 UTC, anonymous wrote:

On Friday, 4 April 2014 at 20:19:53 UTC, Olivier Grant wrote:

import std.stdio;
import std.range;
import std.array;

auto splice( size_t N, R )( R range )
  if(isInputRange!R)
{
  struct Splicer
  {
 R array;

 @property bool empty( ) const
 { return 0 == array.length; }

 @property auto front( ) const
 { return array[0 .. N]; }

 void popFront( )
 { array = array[N .. $]; }
  }

  static assert(isInputRange!Splicer);

  assert(range.length % N == 0);

  Splicer res = { range };
  return res;
}

unittest
{
  assert(equal([1,2,3,4].splice!(2), [[1,2],[3,4]]));
}

void main( )
{
  auto a = [1,2,3,4];

  writeln(a.splice!(2));
  writeln(a.splice!(2).array);
}

which weirdly enough gives me the following output :

[[1,2],[3,4]] // I expect that.
[1,2,3,4] // But what is happening here ?


a.splice!(2).array is the field of the Splicer struct. Rename
that or call std.array.array not via UFCS.




Re: std.array.array seems to return flatten copy of input

2014-04-04 Thread Tobias Pankrath

On Friday, 4 April 2014 at 20:19:53 UTC, Olivier Grant wrote:

Hi,

I've started using D as a scripting language at work and for 
personal projects as a means to learn the language and I've 
bumped into a case where I would like to iterate a slice by a 
certain number of elements at a time such that :


foreach(s; [1,2,3,4].splice!(2))
{
   writeln(s);
}

would print :

[1,2]
[3,4]

First of all, is there such a function in D's standard library 
as I didn't seem to be able to find one ?


http://dlang.org/phobos/std_range.html#chunks


Re: std.array.array seems to return flatten copy of input

2014-04-04 Thread anonymous

On Friday, 4 April 2014 at 20:19:53 UTC, Olivier Grant wrote:

import std.stdio;
import std.range;
import std.array;

auto splice( size_t N, R )( R range )
   if(isInputRange!R)
{
   struct Splicer
   {
  R array;

  @property bool empty( ) const
  { return 0 == array.length; }

  @property auto front( ) const
  { return array[0 .. N]; }

  void popFront( )
  { array = array[N .. $]; }
   }

   static assert(isInputRange!Splicer);

   assert(range.length % N == 0);

   Splicer res = { range };
   return res;
}

unittest
{
   assert(equal([1,2,3,4].splice!(2), [[1,2],[3,4]]));
}

void main( )
{
   auto a = [1,2,3,4];

   writeln(a.splice!(2));
   writeln(a.splice!(2).array);
}

which weirdly enough gives me the following output :

[[1,2],[3,4]] // I expect that.
[1,2,3,4] // But what is happening here ?


a.splice!(2).array is the field of the Splicer struct. Rename
that or call std.array.array not via UFCS.


Re: std.array.array seems to return flatten copy of input

2014-04-04 Thread anonymous

On Friday, 4 April 2014 at 20:19:53 UTC, Olivier Grant wrote:

iterate a slice by a certain number of elements at a time such 
that :


foreach(s; [1,2,3,4].splice!(2))
{
   writeln(s);
}

would print :

[1,2]
[3,4]

First of all, is there such a function in D's standard library 
as I didn't seem to be able to find one ?


std.range.chunks


std.array.array seems to return flatten copy of input

2014-04-04 Thread Olivier Grant

Hi,

I've started using D as a scripting language at work and for 
personal projects as a means to learn the language and I've 
bumped into a case where I would like to iterate a slice by a 
certain number of elements at a time such that :


foreach(s; [1,2,3,4].splice!(2))
{
   writeln(s);
}

would print :

[1,2]
[3,4]

First of all, is there such a function in D's standard library as 
I didn't seem to be able to find one ?


I ended up implementing the following :

import std.stdio;
import std.range;
import std.array;

auto splice( size_t N, R )( R range )
   if(isInputRange!R)
{
   struct Splicer
   {
  R array;

  @property bool empty( ) const
  { return 0 == array.length; }

  @property auto front( ) const
  { return array[0 .. N]; }

  void popFront( )
  { array = array[N .. $]; }
   }

   static assert(isInputRange!Splicer);

   assert(range.length % N == 0);

   Splicer res = { range };
   return res;
}

unittest
{
   assert(equal([1,2,3,4].splice!(2), [[1,2],[3,4]]));
}

void main( )
{
   auto a = [1,2,3,4];

   writeln(a.splice!(2));
   writeln(a.splice!(2).array);
}

which weirdly enough gives me the following output :

[[1,2],[3,4]] // I expect that.
[1,2,3,4] // But what is happening here ?

I'm obviously doing something wrong but I can't figure out what.

Thanks for the help in advance,

O.


Re: How to hand in a closure variable

2014-04-04 Thread Jesse Phillips

On Friday, 4 April 2014 at 15:13:25 UTC, Bienlein wrote:

What I was actually looking for was how to get this to work:

immutable int b = if(1 == 1) { return 123; } else { return 456; 
};


But I'm happy enough with the solution through a delegate.


What bearophile said, or:

immutable int b = {if(1 == 1) { return 123; } else { return 456; 
}}();


Re: list in spam blacklist? [OT]

2014-04-04 Thread Brad Roberts
Once every few years spamhaus 'cleans up' their white lists with no notifications.  I've already 
initiated the re-removal.  Sigh.  I hate spamhaus, they're a pain in every mail sender's backside.


On 4/4/14, 10:25 AM, Hugo Florentino wrote:

Hi,

IP 173.45.241.208 (slice-1.puremagic.com) seems to be blacklisted in 
zen.spamhaus.org
Please check for a possible misuse of the server, or in case of a false 
positive report to spamhaus.org

Regards, Hugo


Re: porting GCC macro to D

2014-04-04 Thread Ali Çehreli

On 04/04/2014 08:42 AM, ketmar wrote:


You can hack around that limitation if it's acceptable to use a
temporary variable:

sure, and i can rewrite the whole call, passing destination variable as
template argument. but this looks ugly.


A regular function would work too:

void func0 () { }
int func1 () { return 42; }

int MYMACRO()
{
func0();
return func1();
}

void main()
{
int v = MYMACRO() - 16;
}

Ali



list in spam blacklist? [OT]

2014-04-04 Thread Hugo Florentino

Hi,

IP 173.45.241.208 (slice-1.puremagic.com) seems to be blacklisted in 
zen.spamhaus.org
Please check for a possible misuse of the server, or in case of a false 
positive report to spamhaus.org


Regards, Hugo


Re: How do I obtain the default hash of a user-defined struct

2014-04-04 Thread bearophile

H. S. Teoh:

This means that the hash of MyKey is computed based on its 
binary
representation, disregarding the contents of any array (and 
other

reference) fields. This will certainly break AA's.

I'm almost certain this has already been reported as a bug, but 
I
vaguely remember someone mentioning a while back that this is 
supposed
to have been fixed. But I still get the above problem in DMD 
git HEAD.

:-(


It needs to be fixed. (Or the code should not compile).

Bye,
bearophile


Re: How do I obtain the default hash of a user-defined struct

2014-04-04 Thread H. S. Teoh
On Fri, Apr 04, 2014 at 04:48:52PM +, dnspies wrote:
> On Thursday, 3 April 2014 at 23:01:27 UTC, Steven Schveighoffer wrote:
> >On Thu, 03 Apr 2014 17:42:16 -0400, bearophile 
> >wrote:
> >
> >
> >>I have filed this big problem four years ago or more.
> >
> >Bug report?
> >
> >-Steve
> 
> This is the closest I could find:
> 
> https://d.puremagic.com/issues/show_bug.cgi?id=11025
> 
> Here's a couple other related bugs:
> 
> https://d.puremagic.com/issues/show_bug.cgi?id=12516
> 
> https://d.puremagic.com/issues/show_bug.cgi?id=10374
> 
> https://d.puremagic.com/issues/show_bug.cgi?id=1926

I just found this related issue:

import std.stdio;

struct MyKey {
int a;
char[] b;
}

void main() {
auto key1 = MyKey(1, "abc".dup);
writefln("key1 hash = %x", typeid(typeof(key1)).getHash(&key1));

char[] sneaky = "def".dup;
key1.b[] = sneaky[]; // N.B.: change array contents, keep same 
pointer

writefln("key1 hash = %x", typeid(typeof(key1)).getHash(&key1));
}

Output:

key1 hash = 6cba62173367a870
key1 hash = 6cba62173367a870

This means that the hash of MyKey is computed based on its binary
representation, disregarding the contents of any array (and other
reference) fields. This will certainly break AA's.

I'm almost certain this has already been reported as a bug, but I
vaguely remember someone mentioning a while back that this is supposed
to have been fixed. But I still get the above problem in DMD git HEAD.
:-(


T

-- 
GEEK = Gatherer of Extremely Enlightening Knowledge


Re: How do I obtain the default hash of a user-defined struct

2014-04-04 Thread dnspies
On Thursday, 3 April 2014 at 23:01:27 UTC, Steven Schveighoffer 
wrote:
On Thu, 03 Apr 2014 17:42:16 -0400, bearophile 
 wrote:




I have filed this big problem four years ago or more.


Bug report?

-Steve


This is the closest I could find:

https://d.puremagic.com/issues/show_bug.cgi?id=11025

Here's a couple other related bugs:

https://d.puremagic.com/issues/show_bug.cgi?id=12516

https://d.puremagic.com/issues/show_bug.cgi?id=10374

https://d.puremagic.com/issues/show_bug.cgi?id=1926



Re: Why defining alias and not auto when using a template?

2014-04-04 Thread Frustrated

On Friday, 4 April 2014 at 13:23:48 UTC, Bienlein wrote:

Hello,

I took some code snippet from some sample D code and modified 
it a bit:


template TCopy(T, V) {
  private int i = 2;

  void copy(out T to, out V to2, T from) {
to = from;
to2 = from;
writeln("i: ", i);
  }
}

void main(string[] args)
{
int x = 2;
int y = 2;
alias myCopy = TCopy!(int, int);
myCopy.copy(x, y, 37);
writeln("x: ", x, " y: ", y);
}

My question is now why I have to declare and alias as in

alias myCopy = TCopy!(int, int);

If I define auto instead of alias, it does not compile. My 
question is why defining auto does not work. I would consider 
this more intuitive.


Thanks, Bienlein



When you type TCopy!(int, int) you are not creating an expression 
with a return variable. TCopy!(int, int) has no return variable 
so auto can't work(What would be the return value?).


All TCopy is, is a compile time container that contains a 
variable i and a method copy. It contains no return value, hence 
auto can't work.


Now, TCopy!(int, int).i or TCopy!(int, int).copy are "things" 
that are in the template that can be used.


About the only thing you could do is use an eponymous template 
like





template TCopy(T, V) {
  private int i = 2;

  void copy(out T to, out V to2, T from) {
to = from;
to2 = from;
writeln("i: ", i);
  }


T TCopy() { return null; }

}


then

auto x = TCopy!(int, int)(someTvalue);

then x would be of type T, the return value of the TCopy 
function(not the template because it doesn't have a return value).




Re: porting GCC macro to D

2014-04-04 Thread ketmar
You can hack around that limitation if it's acceptable to use a 
temporary variable:
sure, and i can rewrite the whole call, passing destination 
variable as template argument. but this looks ugly.


thanx for the answer anyway (and bearophile too).

Unfortunately, you cannot use template mixins for this, because 
they can only contain declarations, not statements.
yes, i found that hard way — with experiments. it's a pity, i 
think.


Re: porting GCC macro to D

2014-04-04 Thread Marc Schütz

On Friday, 4 April 2014 at 13:22:39 UTC, ketmar wrote:

i have some C code like this:

void func0 (void) { … }
int func1 (void) { … return smth+42; }

#define MYMACRO()  ({ func0(); func1(); })

int v;
…
v = MYMACRO()-16;



v = mixin(MYMACRO())-16;

and have the same effect as in C code: all MYMACRO content 
(this can be almost anything) *always* inlined. the only thing 
i was able to think out is to generate nested functions with 
immediate call in MYMACRO, but it will not guarantee inlining 
(i.e. i must trust compiler intellgence here).


You can hack around that limitation if it's acceptable to use a 
temporary variable:


enum MYMACRO(alias output) = `func0(); ` ~ output.stringof ~ ` = 
func1();`;

...
int a;
mixin(MYMACRO!a);
v = a - 16;

This uses the new enum template syntax available in current DMD, 
alternatively use:


template MYMACRO(alias output) {
enum MYMACRO = ...;
}

Unfortunately, you cannot use template mixins for this, because 
they can only contain declarations, not statements.


Re: How to hand in a closure variable

2014-04-04 Thread bearophile

Bienlein:


What I was actually looking for was how to get this to work:

immutable int b = if(1 == 1) { return 123; } else { return 456; 
};


immutable b = (1 == 1) ? 123 : 456;

Bye,
bearophile


Re: How to hand in a closure variable

2014-04-04 Thread Bienlein

On Friday, 4 April 2014 at 13:53:33 UTC, bearophile wrote:

If your D function has one argument, you have to give it one 
argument, even if it doesn't have a visible name and it's 
unused.


Ah! Admittedly, I though it's the return type .. So this works
now:

immutable int b = () {
if(1 == 1) {
return 123;
} else {
return 456;
}
}();

What I was actually looking for was how to get this to work:

immutable int b = if(1 == 1) { return 123; } else { return 456; };

But I'm happy enough with the solution through a delegate.


Re: Why defining alias and not auto when using a template?

2014-04-04 Thread Steven Schveighoffer

On Fri, 04 Apr 2014 09:35:57 -0400, Bienlein  wrote:




"auto" is used to declare an instance, or an object.
"alias" is used to declare a name.

What you are currently doing is saying "the function TCopy!(int, int)  
can now be refered to as myCopy". You aren't actually creating any data.


All right, thanks. Then I create an instance:

auto myCopy = new TCopy!(int, int); 
alias myCopy = new TCopy!(int, int);

Neither nor compiles now. How can? Seems to me a template is not a class  
in that sense ?!


A template is not a structure or class, it is a template. It's basically  
lexically checked, but not semantically. Once you define it's types and  
parameters, then the compiler basically substitutes those in, and compiles  
the result.


Note that a class template:

class C(T)
{
}

is short for this:

template C(T)
{
   class C
   {
   }
}

-Steve


Re: How to hand in a closure variable

2014-04-04 Thread bearophile

Bienlein:


Whereas this does not compile:

immutable int b = (int) {
if(1 == 1) {
return 123;
} else {
return 456;
}
}(); // line x  

However, this does compile and displays correctly 123:

immutable int b = (int) {
if(1 == 1) {
return 123;
} else {
return 456;
}
}(1); // line y 

writeln(b);

Note it says () in line x and (1) in line y. The (1) in line y 
is redundant, but the stuff then compiles.


If your D function has one argument, you have to give it one 
argument, even if it doesn't have a visible name and it's unused.


Bye,
bearophile


Re: Why defining alias and not auto when using a template?

2014-04-04 Thread anonymous

On Friday, 4 April 2014 at 13:23:48 UTC, Bienlein wrote:

template TCopy(T, V) {

[...]

}


On Friday, 4 April 2014 at 13:35:58 UTC, Bienlein wrote:

auto myCopy = new TCopy!(int, int); 
alias myCopy = new TCopy!(int, int);

Neither nor compiles now. How can? Seems to me a template is 
not a class in that sense ?!


Templates are not classes, yes. You can make a class template:

class TCopy(T, V) {...}

The template instance TCopy!(int, int) then is a class type which
can be newed, etc.

The same works with structs, functions, interfaces. Add some
(template) parameters and it becomes a template that instantiates
to the corresponding entity.


Re: How to hand in a closure variable

2014-04-04 Thread Bienlein
Thanks so far. I have another one, though. Not trying to tease 
people, I really don't know ;-).


This compiles and runs:

immutable int a = (int val) {
if(1 == 1) {
return val;
} else {
return 456;
}
}(123); 

writeln(a);

Whereas this does not compile:

immutable int b = (int) {
if(1 == 1) {
return 123;
} else {
return 456;
}
}(); // line x  

However, this does compile and displays correctly 123:

immutable int b = (int) {
if(1 == 1) {
return 123;
} else {
return 456;
}
}(1); // line y 

writeln(b);

Note it says () in line x and (1) in line y. The (1) in line y is 
redundant, but the stuff then compiles.


Re: When this will be freed?

2014-04-04 Thread Steven Schveighoffer

On Fri, 04 Apr 2014 09:25:49 -0400, Marc Schütz  wrote:


On Wednesday, 2 April 2014 at 16:51:57 UTC, Benjamin Thaut wrote:

Am 02.04.2014 17:57, schrieb Andrea Fontana:

I mean: if it is an exported function (of a shared library) what
happens? There's no reference kept anywhere (in D). So if I'm right it
could be freed immediatly by GC. Right?



If you pass that string to a C function, there is a reference on the  
stack. So this string will not be freed until that C-function returns.  
If that C-Function returns, it is very likely however that this was the  
only reference and the string will be freed the next time the garbage  
collector runs.


This is unfortunately only true on x86 32-bit. For x86_64, the calling  
conventions (MS, SysV [1]) say that the first few parameters are passed  
in registers, and the same is probably true for other architectures.


Usually this is still safe, as the pointer will normally either stay in  
its register, or will be spilled to the stack and kept there as long as  
the function still needs to use it. But one might imagine a corner case  
where it temporarily stores the pointer in a global or static variable.  
Even if the pointer will not be kept by the C function longer than the  
call, in such cases you would need to keep an additional reference where  
the GC can see it.


In cases where it is stored in global data, and that becomes the only  
reference, or if a C heap allocation is made, and the pointer is stored in  
there (perhaps to pass to another C function?), then it's quite possible  
the data could be collected prematurely in another thread.


You bring up a good point. This is something that should be considered  
when calling extern(C) functions.


-Steve


Re: Why defining alias and not auto when using a template?

2014-04-04 Thread Bienlein



"auto" is used to declare an instance, or an object.
"alias" is used to declare a name.

What you are currently doing is saying "the function 
TCopy!(int, int) can now be refered to as myCopy". You aren't 
actually creating any data.


All right, thanks. Then I create an instance:

auto myCopy = new TCopy!(int, int); 
alias myCopy = new TCopy!(int, int);

Neither nor compiles now. How can? Seems to me a template is not 
a class in that sense ?!




Re: porting GCC macro to D

2014-04-04 Thread bearophile

ketmar:

and have the same effect as in C code: all MYMACRO content 
(this can be almost anything) *always* inlined.


Define a function. And in D there is no way to require a sure 
inline.
Some people have asked for a __forceinline but Andrei&Walter 
don't seem sufficiently interested.


Bye,
bearophile


Re: Why defining alias and not auto when using a template?

2014-04-04 Thread monarch_dodra

On Friday, 4 April 2014 at 13:23:48 UTC, Bienlein wrote:

Hello,

I took some code snippet from some sample D code and modified 
it a bit:


template TCopy(T, V) {
  private int i = 2;

  void copy(out T to, out V to2, T from) {
to = from;
to2 = from;
writeln("i: ", i);
  }
}

void main(string[] args)
{
int x = 2;
int y = 2;
alias myCopy = TCopy!(int, int);
myCopy.copy(x, y, 37);
writeln("x: ", x, " y: ", y);
}

My question is now why I have to declare and alias as in

alias myCopy = TCopy!(int, int);

If I define auto instead of alias, it does not compile. My 
question is why defining auto does not work. I would consider 
this more intuitive.


Thanks, Bienlein


"auto" is used to declare an instance, or an object.
"alias" is used to declare a name.

What you are currently doing is saying "the function TCopy!(int, 
int) can now be refered to as myCopy". You aren't actually 
creating any data.


Re: When this will be freed?

2014-04-04 Thread Marc Schütz

On Wednesday, 2 April 2014 at 16:51:57 UTC, Benjamin Thaut wrote:

Am 02.04.2014 17:57, schrieb Andrea Fontana:
I mean: if it is an exported function (of a shared library) 
what
happens? There's no reference kept anywhere (in D). So if I'm 
right it

could be freed immediatly by GC. Right?



If you pass that string to a C function, there is a reference 
on the stack. So this string will not be freed until that 
C-function returns. If that C-Function returns, it is very 
likely however that this was the only reference and the string 
will be freed the next time the garbage collector runs.


This is unfortunately only true on x86 32-bit. For x86_64, the 
calling conventions (MS, SysV [1]) say that the first few 
parameters are passed in registers, and the same is probably true 
for other architectures.


Usually this is still safe, as the pointer will normally either 
stay in its register, or will be spilled to the stack and kept 
there as long as the function still needs to use it. But one 
might imagine a corner case where it temporarily stores the 
pointer in a global or static variable. Even if the pointer will 
not be kept by the C function longer than the call, in such cases 
you would need to keep an additional reference where the GC can 
see it.


[1] 
https://en.wikipedia.org/wiki/X86_calling_conventions#x86-64_calling_conventions


Re: Extracting Params of Templated Type

2014-04-04 Thread Meta

On Friday, 4 April 2014 at 07:23:51 UTC, Andrej Mitrovic wrote:

On 4/4/14, Meta  wrote:

alias TemplateArgs(T: Foo!U, U) = U;


It's also in std.traits, TemplateArgsOf, which is more complete.


I thought I remembered that being in std.traits, but I couldn't 
find it after quickly skimming. I must've glanced over it.


Why defining alias and not auto when using a template?

2014-04-04 Thread Bienlein

Hello,

I took some code snippet from some sample D code and modified it 
a bit:


template TCopy(T, V) {
  private int i = 2;

  void copy(out T to, out V to2, T from) {
to = from;
to2 = from;
writeln("i: ", i);
  }
}

void main(string[] args)
{
int x = 2;
int y = 2;
alias myCopy = TCopy!(int, int);
myCopy.copy(x, y, 37);
writeln("x: ", x, " y: ", y);
}

My question is now why I have to declare and alias as in

alias myCopy = TCopy!(int, int);

If I define auto instead of alias, it does not compile. My 
question is why defining auto does not work. I would consider 
this more intuitive.


Thanks, Bienlein


porting GCC macro to D

2014-04-04 Thread ketmar

i have some C code like this:

void func0 (void) { … }
int func1 (void) { … return smth+42; }

#define MYMACRO()  ({ func0(); func1(); })

int v;
…
v = MYMACRO()-16;


what it does? it uses GCC extension "statement expression" which 
allows to place almost arbitrary C operator block inside any 
expression. result of evaluating this "operator block" will be 
value of the last operator in it (return value of func1() in my 
case). this block can contain ifs, switches, local vars, local 
function declarations and so on.


in D we have no "statement expressions" in this form, afaik, and 
comma operator is very limited (and will be deprecated anyway). 
how can i reproduce such thing in D? i.e. i want to write 
something like:


v = mixin(MYMACRO())-16;

and have the same effect as in C code: all MYMACRO content (this 
can be almost anything) *always* inlined. the only thing i was 
able to think out is to generate nested functions with immediate 
call in MYMACRO, but it will not guarantee inlining (i.e. i must 
trust compiler intellgence here).


Re: How can I specify a location to write the code coverage files generated with '-cov'?

2014-04-04 Thread Saurabh Das

On Friday, 4 April 2014 at 08:52:09 UTC, Daniel Murphy wrote:

On Friday, 4 April 2014 at 04:10:51 UTC, Saurabh Das wrote:

Hello,

Say I compile a program with:

dmd -unittest -debug -cov test.d

Then, when I run ./test, a file 'test.lst' is generated in the 
current working directory. Is there a way in which I can 
instruct the file to be created in a separate './cov_log/' 
directory?


Thanks,
Saurabh


You actually can do this, through the hidden rt.cover api:

extern (C) void dmd_coverSourcePath( string pathname );
extern (C) void dmd_coverDestPath( string pathname );



That is perfect! Many many thanks!

Add these prototypes to your code and use them to override the 
default coverage paths.


Saurabh



Re: How can I specify a location to write the code coverage files generated with '-cov'?

2014-04-04 Thread Daniel Murphy

On Friday, 4 April 2014 at 04:10:51 UTC, Saurabh Das wrote:

Hello,

Say I compile a program with:

dmd -unittest -debug -cov test.d

Then, when I run ./test, a file 'test.lst' is generated in the 
current working directory. Is there a way in which I can 
instruct the file to be created in a separate './cov_log/' 
directory?


Thanks,
Saurabh


You actually can do this, through the hidden rt.cover api:

extern (C) void dmd_coverSourcePath( string pathname );
extern (C) void dmd_coverDestPath( string pathname );

Add these prototypes to your code and use them to override the 
default coverage paths.


Re: Extracting Params of Templated Type

2014-04-04 Thread Andrej Mitrovic
On 4/4/14, Meta  wrote:
> alias TemplateArgs(T: Foo!U, U) = U;

It's also in std.traits, TemplateArgsOf, which is more complete.