x64 Link Issues - Can someone please help?

2013-04-18 Thread Trey Brisbane

Hey all,

I'm currently using D for a hook-based project that requires me
to build both a 32bit and 64bit DLL. Naturally, the 32bit DLL
builds fine, however I'm encountering linking issues for the
64bit.
I followed the instructions at
http://wiki.dlang.org/Installing_DMD_on_64-bit_Windows_7_(COFF-compatible)
for setting up 64bit building (albeit I didn't use his
environment variables - I just put the paths into sc.ini
directly), so if there's a problem with my setup, I don't see it.

Here is my build output (I'm using Xamarin Studio with Mono-D, if
that means anything):

---

Building: HookLib (Debug|x64)

Performing main compilation...

Current dictionary:
C:\Development\Projects\EyefinityMaximizer\HookLib

dmd.exe -debug -gc "main.d"
"C:\Development\Projects\EyefinityMaximizer\EyefinityMaximizer\eyemax\WinAPI.d"
"HookLib.def" "user32.lib"
"-IC:\Development\Compilers\D\dmd2\src\phobos"
"-IC:\Development\Compilers\D\dmd2\src\druntime\src"
"-L/IMPLIB:C:\Development\Projects\EyefinityMaximizer\bin\Debug\HookLib.x64.lib"
"-odobj\Debug"
"-ofC:\Development\Projects\EyefinityMaximizer\bin\Debug\HookLib.x64.dll"
-m64

HookLib.def(1) : warning LNK4017: EXETYPE statement not supported
for the target platform; ignored

HookLib.def(2) : warning LNK4017: SUBSYSTEM statement not
supported for the target platform; ignored

HookLib.x64.obj : warning LNK4197: export 'CallWndProc' specified
multiple times; using first specification

   Creating library
C:\Development\Projects\EyefinityMaximizer\bin\Debug\HookLib.x64.lib
and object
C:\Development\Projects\EyefinityMaximizer\bin\Debug\HookLib.x64.exp

phobos64.lib(dmain2_4ac_1a5.obj) : error LNK2019: unresolved
external symbol _Dmain referenced in function main

C:\Development\Projects\EyefinityMaximizer\bin\Debug\HookLib.x64.dll
: fatal error LNK1120: 1 unresolved externals

--- errorlevel 1120

Exit code 1120

Build complete -- 1 error, 0 warnings

---

As you can see, there appears to be an issue with my usage of
DLLMain() as opposed to just main(). For 32bit building, the
documentation states that the compiler recognizes DLLMain and
works accordingly - is this also the case for 64bit building?

Here is my DLLMain function, in case I'm doing something wrong
with it:

---

extern (Windows) BOOL DllMain(HINSTANCE hInstance, ULONG
ulReason, LPVOID pvReserved) {
// Main DLL switch
switch (ulReason) {
case DLL_PROCESS_ATTACH:
g_hInst = hInstance;
dll_process_attach( hInstance, true );
break;
case DLL_PROCESS_DETACH:
dll_process_detach( hInstance, true );
break;
case DLL_THREAD_ATTACH:
dll_thread_attach( true, true );
break;
case DLL_THREAD_DETACH:
dll_thread_detach( true, true );
break;
default:
break;
}
return true;
}

---

Any assistance would be appreciated, as this project is stalled
until I can build 64bit binaries.

Thanks and regards,
Trey


Re: Copying reference types by value

2013-04-18 Thread Ali Çehreli
On 04/18/2013 06:22 AM, Joseph Rushton Wakeling wrote:> On 04/17/2013 
10:29 PM, Ali Çehreli wrote:
>> Yes but as I said I am not sure how useful or needed this whole 
thing is.

>>
>> The language handles copy, move, and assignment for structs. 
takeOver() seems to

>> be a primitive operation for classes.
>
> Could you expand a bit on that?  Just that I'm not sure I understand your
> meaning completely, and I'm curious. :-)

Being value types, structs enjoy automatic handling of copy, assignment, 
and in the case of rvalues, move.


struct S
{
int i;
}

S makeS()
{
return S();
}

void main()
{
auto a = S();
auto b = a;// a is copied to b
b = a; // a is assigned to b
b = makeS();   // the returned rvalue is 'moved' to b
}

Of course that works only for structs with simple value members. When 
the automatic handling is not sufficient or does the wrong thing, then 
the programmer must provide this(this), opAssign(), or ~this(). Things 
get more interesting when the members are mutable or immutable references.


With the above definition of S, all of the following compile:

immutable(S) imm0;
S mut = imm0;// immutable to mutable

immutable(S) imm1 = mut;  // mutable to immutable

immutable(S) imm2 = imm0; // immutable to immutable

Now naively add another member to S:

struct S
{
int i;
int[] arr;  // <-- added
}

Only the latter of the three assignments compile:

immutable(S) imm0;
S mut = imm0; // compilation ERROR

immutable(S) imm1 = mut;  // compilation ERROR

immutable(S) imm2 = imm0; // compiles

Anyway... I am trying to wrap up what I have learned so far before going 
any further. :)


For classes, none of these operations make sense: There is no automatic 
copying, no automatic assignment, nor there are rvalues to move.


> I'd assumed this problem would be some fairly straightforward aspect 
of the
> language that I just wasn't familiar with, so I'm quite struck by the 
fact that

> it actually seems a non-trivial problem.

My experience has been with C++ so I don't know how this is solved in 
Java or C#. Maybe this is not a problem with the common idioms in those 
languages, which would also mean that this is not a problem with D 
classes. Rather, if one has decided to go with a class, then value 
semantics were not a consideration to begin with.


Ali



Re: refuses to open file

2013-04-18 Thread Ali Çehreli

On 04/18/2013 04:25 PM, rbt...@digitalpath.net wrote:

> Let's start over it has nothing to due with the file.  It's the file name
> thats the problem.

Let's start with the obvious. :)

>   Directory of c:\d\projects\equipment

> std.exception.ErrnoException@std\stdio.d(289): Cannot open file
> `c:\d\projects\eqipment\test.d' in mode `rb' (No such file or directory)

There is a typo in that path.

Ali



Re: A little of coordination for Rosettacode

2013-04-18 Thread bearophile
Maybe there is a way to translate this Haskell version to D with 
bigints:


http://rosettacode.org/wiki/Find_largest_left_truncatable_prime_in_a_given_base#Haskell

Unrelated: now I have a kind of efficient longest common 
subsequence algorithm with O(n) memory usage. Maybe there is some 
interest for it in Phobos.


Bye,
bearophile


Re: refuses to open file

2013-04-18 Thread rbtwms
Let's start over it has nothing to due with the file.  It's the file name
thats the problem.  I wote a short test program to demenstrate the problem.
It shows that if the file name has a path it causes the exception. i.e:

(prompt)dir
 Volume in drive C is OS
 Volume Serial Number is E221-AB60

 Directory of c:\d\projects\equipment

04/18/2013  03:57 PM 1,070 test.d
   1 File(s)  1,070 bytes
   0 Dir(s)  899,752,787,968 bytes free
(prompt)test 2000 c:\d\projects\equipment\test.d
args.length = 3
out of switch
Type is 2000 case 2
std.exception.ErrnoException@std\stdio.d(289): Cannot open file
`c:\d\projects\eqipment\test.d' in mode `rb' (No such file or directory)

0x0041A83C
0x0041A6C7
0x0040F577
0x0040B240
0x0040B27A
0x0040AE9C
0x00421F3D
0x752E33AA in BaseThreadInitThunk
0x770C9EF2 in RtlInitializeExceptionChain
0x770C9EC5 in RtlInitializeExceptionChain

(prompt)test 2000 test.d
out of switch
args.length = 3
out of switch
Type is 2000 case 2
out of switch
args[2] = [test.d]
efile name is File(1F81FE0) case 3
out of switch
out of for
Command line was: ["test", "2000", "test.d"]
File is open

test.d follows:
/* Test program
To test file opening problem
*/
import std.stdio, std.string, std.conv;
void main (string[] args)
{
auto fname = "l:\\filepro\\mvammach\\key";
  File efile;
  int type;

writeln("args.length = ", args.length);
if (args.length >= 3){
for (int n=1; n <= args.length; n++){
  switch (n){
case 1:
  break;
case 2:
  type = to!int( args[1] );
  writefln("Type is %s case 2", type);
  break;
case 3:
  efile = File(args[2]);
  writefln("args[2] = [%s]", args[2]);
  writefln("efile name is %s case 3", efile);
  break;
default:
  break;
 } // end switch
 writeln("out of switch");
   } // end for
 writeln("out of for");
   } // end if
   else {
 efile = File(fname,"r");
 writefln("fname = [%s] in else", fname);
 writefln("efile = [%s]", efile);
   } // end else
writeln("Command line was: ", args[]);
if(efile.isOpen()) writeln ("File is open");
} // end main


Re: Assigning a static array

2013-04-18 Thread H. S. Teoh
On Thu, Apr 18, 2013 at 02:43:54PM -0700, Ali Çehreli wrote:
> On 04/18/2013 02:06 PM, Brad Anderson wrote:
> >Is this supposed to be allowed:
> >
> >ubyte[] a;
> >ubyte[16] b;
> >a = b;
> >assert(a.ptr == b.ptr);
> >
> >Because if so that makes it terribly easy to do a bug like this (as I
> >just saw in IRC):
> >
> >struct A
> >{
> > ubyte[] a;
> > this(ubyte c)
> > {
> > ubyte[16] b;
> > b[] = c;
> > this.a = b;  // a now points at an immediately invalid static
> >array
> > }
> >}
> 
> There is a similar problem with the automatically generated array arguments.
> 
> The following constructor takes any number of ints that come in array form:
> 
> import std.stdio;
> 
> struct S
> {
> int[] a;
> 
> this(int[] args...)
> {
> a = args;
> }
> 
> void foo()
> {
> writeln(a);
> }
> }
[...]

Yeah I got bitten by this before. Took me several days to find the
problem, 'cos it was nested deep inside a complex data structure, and at
a glance it doesn't *look* wrong.

I'm all for making this @system at the very least, if not outright
compile error. Storing a persistent reference to a stack-allocated
object is outright wrong... in the case of variadic array args, if the
compiler can't prove that args will *always* be a dynamic array, then
any attempt to save a reference to it should be rejected outright IMO.


T

-- 
It is impossible to make anything foolproof because fools are so ingenious. -- 
Sammy


Re: Assigning a static array

2013-04-18 Thread Ali Çehreli

On 04/18/2013 02:54 PM, Steven Schveighoffer wrote:

>> The program prints the following because the temporary arrays that are
>> generated when calling the constructors are long gone:
>>
>> [1, 1, 1]
>> [1, 1, 1]
>>
>> The programmer *may have* ;) expected the following output:
>>
>> [1, 1, 1]
>> [2, 2, 2]
>
> There is no guarantee that the incoming array from a variadic function
> is heap-based.
>
> But an interesting way to deal with it is that you can overload with an
> explicit slice parameter, and the variadic version will ONLY bind to a
> variadic call.

Interesting.

Personally, I would not even bother with the second one and expect the 
caller to simply put square brackets around the arguments:


import std.stdio;

struct S
{
int[] a;

this(int[] args)  // <-- now requires a slice
{
a = args;
}

void foo()
{
writeln(a);
}
}

void main()
{
S[] a;

foreach (i; 0 .. 2) {
a ~= S([i, i, i]); // <-- minor inconvenience
}

foreach (e; a) {
e.foo();
}
}

It is now safe, right?

> And the correct expectation for your code should be:
>
> [0, 0, 0]
> [1, 1, 1]
>
> :)
>
> -Steve

Wow! I made an off-by-6 error there. :)

Ali



Re: Assigning a static array

2013-04-18 Thread bearophile

Steven Schveighoffer:

There is no guarantee that the incoming array from a variadic 
function is heap-based.


But an interesting way to deal with it is that you can overload 
with an explicit slice parameter, and the variadic version will 
ONLY bind to a variadic call.


For example, in dcollections' ArrayList I have two constructors:

   /**
 * Create an array list based on a number of elements.
 */
this(V[] elems...)
{
_array = elems.dup;
}

/**
 * Use an array as the backing storage.  This does not 
duplicate the
 * array.  Use new ArrayList(storage.dup) to make a 
distinct copy.  Beware

 * of using a stack-based array when using this constructor!
 */
this(V[] storage)
{
_array = storage;
}


To avoid those bugs I have suggested the simpler possible thing: 
(V[] elems...) to dup the data on the heap every time. In theory 
if you write "(scope V[] elems...)" it will be free to not dup 
the data, avoiding the heap allocation and the associated little 
performance loss. In practice as you know "scope" is not yet 
implemented. D2 language is not close to being fully implemented.


Bye,
bearophile


Re: Assigning a static array

2013-04-18 Thread Steven Schveighoffer


There is a similar problem with the automatically generated array  
arguments.


The following constructor takes any number of ints that come in array  
form:


import std.stdio;

struct S
{
 int[] a;

 this(int[] args...)
 {
 a = args;
 }

 void foo()
 {
 writeln(a);
 }
}

void main()
{
 S[] a;

 foreach (i; 0 .. 2) {
 a ~= S(i, i, i);  // <-- WARNING temporary array
 }

 foreach (e; a) {
 e.foo();
 }
}

The program prints the following because the temporary arrays that are  
generated when calling the constructors are long gone:


[1, 1, 1]
[1, 1, 1]

The programmer *may have* ;) expected the following output:

[1, 1, 1]
[2, 2, 2]


There is no guarantee that the incoming array from a variadic function is  
heap-based.


But an interesting way to deal with it is that you can overload with an  
explicit slice parameter, and the variadic version will ONLY bind to a  
variadic call.


For example, in dcollections' ArrayList I have two constructors:

   /**
 * Create an array list based on a number of elements.
 */
this(V[] elems...)
{
_array = elems.dup;
}

/**
 * Use an array as the backing storage.  This does not duplicate the
 * array.  Use new ArrayList(storage.dup) to make a distinct copy.   
Beware

 * of using a stack-based array when using this constructor!
 */
this(V[] storage)
{
_array = storage;
}

The first version binds only to cases where the parameter is not  
*explicitly* a slice, so I am guaranteed that the array is allocated on  
the stack!  The second binds to slices, and I assume from my comment,  
fixed-sized arrays (been a while since I looked at that code).


And the correct expectation for your code should be:

[0, 0, 0]
[1, 1, 1]

:)

-Steve


Re: Assigning a static array

2013-04-18 Thread Brad Anderson

On Thursday, 18 April 2013 at 21:45:56 UTC, bearophile wrote:
Yes, this is supposed to be allowed with the current design of 
D. But with the latest dmd 2.063alpha that code doesn't work, 
see below.


[snip]

Now that code gives a warning:

temp.d(11): Warning: explicit slice assignment this.hash2 = 
(digest(str))[] is better than this.hash2 = digest(str)


(This is the result of a small battle I have started years ago 
that is now half work, thanks to the work of Hara implementing 
my enhancement request. I am glad to see our time was not 
wasted.)


To remove that warning you have to write:

this.hash1 = md5.digest(str);
this.hash2 = digest!MD5(str)[];

Now it's visible that for hash2 you are slicing something 
that's probably a fixed-sized array. This gives you a 
significant help in understanding what's going on.




That's good to hear, Bearophile. Thanks Kenji.


Re: Assigning a static array

2013-04-18 Thread bearophile

Jonathan M Davis:


I could see an argument that it should have to be

a = b[];

so that the slicing is explicit instead of just

a = b;

where it's implicit, but AFAIK, that's not currently required.


It's currently a warning, and it will be required.

--

Ali Çehreli:

There is a similar problem with the automatically generated 
array arguments.


The following constructor takes any number of ints that come in 
array form:


import std.stdio;

struct S
{
int[] a;

this(int[] args...)
{
a = args;
}

void foo()
{
writeln(a);
}
}

void main()
{
S[] a;

foreach (i; 0 .. 2) {
a ~= S(i, i, i);  // <-- WARNING temporary array


This is a known problem, I have put it in Bugzilla since lot of 
time and it seems there are various persons that agree with me 
and you on it. So hopefully this source of bugs will be removed, 
allocating that data on the heap.


Bye,
bearophile


Re: Assigning a static array

2013-04-18 Thread bearophile

Brad Anderson:


Is this supposed to be allowed:

ubyte[] a;
ubyte[16] b;
a = b;
assert(a.ptr == b.ptr);


Yes, this is supposed to be allowed with the current design of D. 
But with the latest dmd 2.063alpha that code doesn't work, see 
below.


The Rust language removes this source of bugs because it manages 
accurately the memory zones. D will probably improve its error 
detection capabilities for such simple cases, but I think it will 
not solve this problem in general, unless it improves its type 
system, similarly to Rust.




import std.digest.md;
import std.stdio;

struct Hash {
  ubyte[] hash1;
  ubyte[] hash2;

  this (string str) {
auto md5 = new MD5Digest();
this.hash1 = md5.digest(str);
this.hash2 = digest!MD5(str);
  }
};

void main() {
  auto h = Hash("hello world!");
  writeln(toHexString(h.hash1));
  writeln(toHexString(h.hash2));
}


It's not obvious at all what the problem is.


Now that code gives a warning:

temp.d(11): Warning: explicit slice assignment this.hash2 = 
(digest(str))[] is better than this.hash2 = digest(str)


(This is the result of a small battle I have started years ago 
that is now half work, thanks to the work of Hara implementing my 
enhancement request. I am glad to see our time was not wasted.)


To remove that warning you have to write:

this.hash1 = md5.digest(str);
this.hash2 = digest!MD5(str)[];

Now it's visible that for hash2 you are slicing something that's 
probably a fixed-sized array. This gives you a significant help 
in understanding what's going on.


Bye,
bearophile


Re: Assigning a static array

2013-04-18 Thread Ali Çehreli

On 04/18/2013 02:06 PM, Brad Anderson wrote:

Is this supposed to be allowed:

ubyte[] a;
ubyte[16] b;
a = b;
assert(a.ptr == b.ptr);

Because if so that makes it terribly easy to do a bug like this (as I
just saw in IRC):

struct A
{
 ubyte[] a;
 this(ubyte c)
 {
 ubyte[16] b;
 b[] = c;
 this.a = b;  // a now points at an immediately invalid static
array
 }
}


There is a similar problem with the automatically generated array arguments.

The following constructor takes any number of ints that come in array form:

import std.stdio;

struct S
{
int[] a;

this(int[] args...)
{
a = args;
}

void foo()
{
writeln(a);
}
}

void main()
{
S[] a;

foreach (i; 0 .. 2) {
a ~= S(i, i, i);  // <-- WARNING temporary array
}

foreach (e; a) {
e.foo();
}
}

The program prints the following because the temporary arrays that are 
generated when calling the constructors are long gone:


[1, 1, 1]
[1, 1, 1]

The programmer *may have* ;) expected the following output:

[1, 1, 1]
[2, 2, 2]

Ali



Re: Assigning a static array

2013-04-18 Thread Jonathan M Davis
On Thursday, April 18, 2013 23:06:32 Brad Anderson wrote:
> Is this supposed to be allowed:
> 
> ubyte[] a;
> ubyte[16] b;
> a = b;
> assert(a.ptr == b.ptr);
> 
> Because if so that makes it terribly easy to do a bug like this
> (as I just saw in IRC):
> 
> struct A
> {
> ubyte[] a;
> this(ubyte c)
> {
> ubyte[16] b;
> b[] = c;
> this.a = b; // a now points at an immediately invalid
> static array
> }
> }

Yes, that's legal, though it should arguably be @system, since it's doing 
essentially the same thing as

int i;
int* p = &i;

which _is_ @system. The compiler doesn't currently consider slicing a static 
array in general to be @system though, much as it should ( 
http://d.puremagic.com/issues/show_bug.cgi?id=8838 ). I could see an argument 
that it should have to be

a = b[];

so that the slicing is explicit instead of just

a = b;

where it's implicit, but AFAIK, that's not currently required. You have to be 
very careful when slicing static arrays. If it were up to me, exlicit slicing 
would _always_ be required when slicing a static array, even when calling 
functions which take a dynamic array, but that's not how it works 
unfortunately.

- Jonathan M Davis


Re: Assigning a static array

2013-04-18 Thread Brad Anderson
For reference, here was what user soos on IRC was doing that 
caused him to hit this :


import std.digest.md;
import std.stdio;

struct Hash {
  ubyte[] hash1;
  ubyte[] hash2;

  this (string str) {
auto md5 = new MD5Digest();
this.hash1 = md5.digest(str);
this.hash2 = digest!MD5(str);
  }
};

void main() {
  auto h = Hash("hello world!");
  writeln(toHexString(h.hash1));
  writeln(toHexString(h.hash2));
}


It's not obvious at all what the problem is.


Assigning a static array

2013-04-18 Thread Brad Anderson

Is this supposed to be allowed:

ubyte[] a;
ubyte[16] b;
a = b;
assert(a.ptr == b.ptr);

Because if so that makes it terribly easy to do a bug like this 
(as I just saw in IRC):


struct A
{
ubyte[] a;
this(ubyte c)
{
ubyte[16] b;
b[] = c;
this.a = b;  // a now points at an immediately invalid 
static array

}
}


Re: writeln an object

2013-04-18 Thread Ali Çehreli

On 04/18/2013 12:37 PM, John Colvin wrote:

> However, by a wider definition of the word, a struct could also be said
> to be an object.

You are missing some words there. :) Not a struct itself, but instances 
of it are said to be objects.


Ali



Re: writeln an object

2013-04-18 Thread John Colvin

On Thursday, 18 April 2013 at 18:46:09 UTC, gedaiu wrote:

i have a struct not an object.


There's a slight nomenclature clash here:

Object is the base class in D. Therefore one could say that an 
object is an instatiation of Object and therefore a class.


However, by a wider definition of the word, a struct could also 
be said to be an object.


Re: writeln an object

2013-04-18 Thread David
Just drop the override:

> struct Value {
> string strVal;
> 
> this(string val) {
> strVal = val;
> }
> 
> override string toString() {
> return strVal;
> }
> }


struct Value {
string strVal;

this(string val) {
strVal = val;
}

string toString() {
return strVal;
}
}


Re: writeln an object

2013-04-18 Thread gedaiu

On Thursday, 18 April 2013 at 18:25:21 UTC, John Colvin wrote:
On Thursday, 18 April 2013 at 18:04:03 UTC, Andrej Mitrovic 
wrote:

On 4/18/13, gedaiu  wrote:

i've done that but i get this error:

Error: function base.Value.Value.toString cannot override a
non-virtual function
Error: function base.Value.Value.toString override only 
applies

to class member functions



If it's a struct then don't put "override".


Just to provide a bit more info:

Classes all derive from Object, which defines toString. Hence, 
you need to override it to define your own.


Structs don't have a parent (or any inheritance at all) and 
hence you don't override anything, you just define the method.


i'm realy sorry... it's my mistake...

i have a struct not an object. I have someting like this when i 
get the error:


struct Value {
string strVal;

this(string val) {
strVal = val;
}

override string toString() {
return strVal;
}
}


Re: writeln an object

2013-04-18 Thread John Colvin

On Thursday, 18 April 2013 at 18:04:03 UTC, Andrej Mitrovic wrote:

On 4/18/13, gedaiu  wrote:

i've done that but i get this error:

Error: function base.Value.Value.toString cannot override a
non-virtual function
Error: function base.Value.Value.toString override only applies
to class member functions



If it's a struct then don't put "override".


Just to provide a bit more info:

Classes all derive from Object, which defines toString. Hence, 
you need to override it to define your own.


Structs don't have a parent (or any inheritance at all) and hence 
you don't override anything, you just define the method.


Re: writeln an object

2013-04-18 Thread Andrej Mitrovic
On 4/18/13, gedaiu  wrote:
> i've done that but i get this error:
>
> Error: function base.Value.Value.toString cannot override a
> non-virtual function
> Error: function base.Value.Value.toString override only applies
> to class member functions
>

If it's a struct then don't put "override".


Re: writeln an object

2013-04-18 Thread gedaiu

On Thursday, 18 April 2013 at 17:42:53 UTC, JN wrote:

On Thursday, 18 April 2013 at 17:36:10 UTC, gedaiu wrote:

Hi,

how i can control what writeln outputs when I pass an object 
parameter?


Thanks,
Bogdan


You can override the toString() method, like this 
http://dpaste.dzfl.pl/db7dbe28


i've done that but i get this error:

Error: function base.Value.Value.toString cannot override a 
non-virtual function
Error: function base.Value.Value.toString override only applies 
to class member functions


Re: writeln an object

2013-04-18 Thread JN

On Thursday, 18 April 2013 at 17:36:10 UTC, gedaiu wrote:

Hi,

how i can control what writeln outputs when I pass an object 
parameter?


Thanks,
Bogdan


You can override the toString() method, like this 
http://dpaste.dzfl.pl/db7dbe28


writeln an object

2013-04-18 Thread gedaiu

Hi,

how i can control what writeln outputs when I pass an object 
parameter?


Thanks,
Bogdan


Re: Why are fixed length arrays passed by value while variable are passed by reference?

2013-04-18 Thread ixid

I don't consider curent situation with static arrays as
incosistent.


When correctly understood is isn't as inconsistent, thank you for 
explaining, this was the knowledge I was after.


Re: Why are fixed length arrays passed by value while variable are passed by reference?

2013-04-18 Thread Steven Schveighoffer
On Thu, 18 Apr 2013 11:26:22 -0400, Maxim Fomin   
wrote:



On Thursday, 18 April 2013 at 13:37:45 UTC, ixid wrote:
I know this will not be changed, I just want to understand why it is as  
it is.


My naive thought is that consistency is the best scheme and that  
everything should have been passed by value or everything by reference  
unless the user specifies otherwise.


Classifying types as passed by value and passed by reference
types is a little bit confusing sometimes)

In D, like in C, everything is passed by value (unless parameter
is specified as ref, also note that in C passing by reference is
a simulation done by pointers). Confusion comes when there is
data which points to another data. Learning how data types are
constructed is better approach than classifying their categories.
The former sometimes can explain what the latter cannot:

http://dpaste.dzfl.pl/7744d11e

AA array behaves like a reference type, but when it is reset to
null, it acts like a value type. Contradiction is caused by
complex data structes with mixed structs and pointers in AA
implementation.


AA's are not passed by reference, they ARE a reference.  That reference is  
ALWAYS passed by value, unless ref is used.


The problem with AA's is that the special reference null mutates upon  
first addition to the AA, and never changes afterwards, unless  
reassigned.  It is always passed by value.


In fact, if default construction allowed allocating the initial reference  
(or null wasn't treated specially), we wouldn't have that problem.


-Steve


Re: Why are fixed length arrays passed by value while variable are passed by reference?

2013-04-18 Thread Ali Çehreli

On 04/18/2013 07:20 AM, ixid wrote:

Jacob Carlborg said:

>> An array is represent using a struct with a pointer to the array data
>> and the length, like this:
>>
>> struct Array
>> {
>> void* ptr;
>> size_t length;
>> }

The terms "array" and "slice" are commonly interchanged but I think it 
adds to the confusion. The above is the definition of a slice. An array 
is simply a collection of objects placed next to each other.


>> The struct is passed by value, but since it contains a pointer to the
>> data it will be passed by reference. Note that if you do:
>>
>> void foo (int[] a)
>> {
>> a ~= 3;
>> }
>>
>> auto b = [3, 4];
>> foo(b);
>>
>> The caller will not see the change made by "foo".
>>
>> Don't know if this explanation helped you to understand.
>
> What does a fixed length array look like when passed, doesn't it have a
> similar payload of data and length?

No. It is all of the elements side by side. That is the definition of an 
array.


int[3] a;
assert(a.sizeof == ((a[0]).sizeof * a.length));
assert(cast(void*)&a == cast(void*)&(a[0]));

A fixed-length array does not have a ptr or length member. The former is 
simly the address of the fixed-length array itself and the latter is a 
compile-time constant.


> I take it you mean the struct method
> is the variable length array.

Yes. The struct above is a slice. (Although, in reality length is 
defined before ptr.)


Ali



Re: Why are fixed length arrays passed by value while variable are passed by reference?

2013-04-18 Thread Maxim Fomin

On Thursday, 18 April 2013 at 13:37:45 UTC, ixid wrote:
I know this will not be changed, I just want to understand why 
it is as it is.


My naive thought is that consistency is the best scheme and 
that everything should have been passed by value or everything 
by reference unless the user specifies otherwise.


Classifying types as passed by value and passed by reference
types is a little bit confusing sometimes)

In D, like in C, everything is passed by value (unless parameter
is specified as ref, also note that in C passing by reference is
a simulation done by pointers). Confusion comes when there is
data which points to another data. Learning how data types are
constructed is better approach than classifying their categories.
The former sometimes can explain what the latter cannot:

http://dpaste.dzfl.pl/7744d11e

AA array behaves like a reference type, but when it is reset to
null, it acts like a value type. Contradiction is caused by
complex data structes with mixed structs and pointers in AA
implementation.

I have read a comment by Andrei that they tried making fixed 
length arrays into reference types but it did not work well. 
Did the current situation arise through the reality of language 
development or is there a reason for the inconsistency?


I don't consider curent situation with static arrays as
incosistent.


Re: Why are fixed length arrays passed by value while variable are passed by reference?

2013-04-18 Thread Simen Kjaeraas

On 2013-04-18, 16:20, ixid wrote:

An array is represent using a struct with a pointer to the array data  
and the length, like this:


struct Array
{
void* ptr;
size_t length;
}

The struct is passed by value, but since it contains a pointer to the  
data it will be passed by reference. Note that if you do:


void foo (int[] a)
{
a ~= 3;
}

auto b = [3, 4];
foo(b);

The caller will not see the change made by "foo".

Don't know if this explanation helped you to understand.


What does a fixed length array look like when passed, doesn't it have a  
similar payload of data and length? I take it you mean the struct method  
is the variable length array.



The fixed length array is much more similar to a struct. An int[2], for
instance, is in many ways equivalent to struct { int a; int b; }.
Two ways this is visible is that static arrays are allocated on the stack,
and take up space in a struct or class the same way a struct would:

struct S1 {
int[] a;
}
static assert( S1.sizeof == int[].sizeof );

struct S2 {
int[17] a;
}
static assert( S2.sizeof == 17 * int.sizeof );


Also, like Jacob wrote, there is the difference of ref/value semantics
when embedded in a struct/class. If I have these two functions:

void foo1( S1 s ) {
   s.a[0] = 7;
}

void foo2( S2 s ) {
   s.a[0] = 7;
}

void test( ) {
   S1 s1 = S1(new int[4]);
   S2 s2 = S2();
   foo1(s1);
   foo2(s2);
}

The values in s1 will have changed, while those in s2 will not.

All in all, static arrays are treated as value types everywhere else,
and so treating them as value types when passed to a function makes
more sense.

--
Simen


Re: Why are fixed length arrays passed by value while variable are passed by reference?

2013-04-18 Thread ixid
An array is represent using a struct with a pointer to the 
array data and the length, like this:


struct Array
{
void* ptr;
size_t length;
}

The struct is passed by value, but since it contains a pointer 
to the data it will be passed by reference. Note that if you do:


void foo (int[] a)
{
a ~= 3;
}

auto b = [3, 4];
foo(b);

The caller will not see the change made by "foo".

Don't know if this explanation helped you to understand.


What does a fixed length array look like when passed, doesn't it 
have a similar payload of data and length? I take it you mean the 
struct method is the variable length array.


Re: Why are fixed length arrays passed by value while variable are passed by reference?

2013-04-18 Thread Jacob Carlborg

On 2013-04-18 15:37, ixid wrote:

I know this will not be changed, I just want to understand why it is as
it is.

My naive thought is that consistency is the best scheme and that
everything should have been passed by value or everything by reference
unless the user specifies otherwise.

I have read a comment by Andrei that they tried making fixed length
arrays into reference types but it did not work well. Did the current
situation arise through the reality of language development or is there
a reason for the inconsistency?


An array is represent using a struct with a pointer to the array data 
and the length, like this:


struct Array
{
void* ptr;
size_t length;
}

The struct is passed by value, but since it contains a pointer to the 
data it will be passed by reference. Note that if you do:


void foo (int[] a)
{
a ~= 3;
}

auto b = [3, 4];
foo(b);

The caller will not see the change made by "foo".

Don't know if this explanation helped you to understand.

--
/Jacob Carlborg


Why are fixed length arrays passed by value while variable are passed by reference?

2013-04-18 Thread ixid
I know this will not be changed, I just want to understand why it 
is as it is.


My naive thought is that consistency is the best scheme and that 
everything should have been passed by value or everything by 
reference unless the user specifies otherwise.


I have read a comment by Andrei that they tried making fixed 
length arrays into reference types but it did not work well. Did 
the current situation arise through the reality of language 
development or is there a reason for the inconsistency?


Re: Copying reference types by value

2013-04-18 Thread Joseph Rushton Wakeling
On 04/17/2013 10:29 PM, Ali Çehreli wrote:
> Yes but as I said I am not sure how useful or needed this whole thing is.
> 
> The language handles copy, move, and assignment for structs. takeOver() seems 
> to
> be a primitive operation for classes.

Could you expand a bit on that?  Just that I'm not sure I understand your
meaning completely, and I'm curious. :-)

> That's what I meant by "a wrapper function." But I think move is a more
> fundamental operation that elides a copy. If we had only copyFrom(), then the
> following would indeed need to copy:
> 
> // foo() returns a class object
> a.copyFrom(foo());
> 
> On the other hand, takeOver() would have the ability to move the members of 
> the
> returned rvalue object without needing to copy.

OK, clear.  In fact seems possible that copying vs. takeover might be useful to
define separately and use whichever is optimal for the given use-case.

> Agreed.

I'd assumed this problem would be some fairly straightforward aspect of the
language that I just wasn't familiar with, so I'm quite struck by the fact that
it actually seems a non-trivial problem.