Re: Reordered class fields?

2012-10-31 Thread Jacob Carlborg

On 2012-10-31 02:53, Peter Summerland wrote:


The order of the fields is rearranged for packing. Does that affect the
tupleof property? The example in http://dlang.org/class.html for Class
properties tulpleof seems to implie that the the fields the returned
Expression Tuple are arranged in lexical order (i.e., as defined by the
programmer in the class definition). Is this always true for classes?
What about structs?


I don't know. But I would not count on the order of tupleof. I would 
consider that implementation defined.


--
/Jacob Carlborg


Re: Reordered class fields?

2012-10-31 Thread Peter Summerland
On Wednesday, 31 October 2012 at 07:19:19 UTC, Jacob Carlborg 
wrote:

On 2012-10-31 02:53, Peter Summerland wrote:

The order of the fields is rearranged for packing. Does that 
affect the
tupleof property? The example in http://dlang.org/class.html 
for Class
properties tulpleof seems to implie that the the fields the 
returned
Expression Tuple are arranged in lexical order (i.e., as 
defined by the
programmer in the class definition). Is this always true for 
classes?

What about structs?


I don't know. But I would not count on the order of tupleof. I 
would consider that implementation defined.


Thanks for the help.

Should the the following example, taken from the D Language 
Reference, be considered incorrect or at least misleading? It 
clearly depends on lexical ordering of the returned fields:


Class Properties

The .tupleof property returns an ExpressionTuple of all the 
fields in the class, excluding the hidden fields and the fields 
in the base class.


class Foo { int x; long y; }
void test(Foo foo) {
  foo.tupleof[0] = 1; // set foo.x to 1
  foo.tupleof[1] = 2; // set foo.y to 2
  foreach (x; foo.tupleof)
writef(x);// prints 12
}


It would be nice if the Language Reference was specific on this 
point.  I am aware that the order of the members returned by 
__traits(allMembers, D) is not defined (per the LR). But that is 
a larger, more complex list.


I am just beginning with D, but I think having the tupleof 
property for classes and structs return their fields in lexical 
order might be useful.


E.g., I have written a scan function to load up a struct or 
class from a row returned by a database query. I have, say, 
scan!x,y,z(obj) to load data into fields x,y,z of obj. Based on 
the example above and by experimenting, it appears that at least 
for dmd running on Linux, that the fields returned by tupleof are 
indeed in lexical order.  That allowed me to have a  default 
for the string of field names which indicates that all the fields 
should be loaded. I.e., I have scan!(obj), which can be written 
scan(obj). Again, it seems to work for simple classes and structs 
with Dmd on Ubuntu.


Don't get me wrong -- I'll be happy without the default version 
if that is the answer. I'm not suggesting any changes.






Re: Reordered class fields?

2012-10-31 Thread Jacob Carlborg

On 2012-10-31 09:14, Peter Summerland wrote:


Thanks for the help.

Should the the following example, taken from the D Language Reference,
be considered incorrect or at least misleading? It clearly depends on
lexical ordering of the returned fields:

Class Properties

The .tupleof property returns an ExpressionTuple of all the fields in
the class, excluding the hidden fields and the fields in the base class.

class Foo { int x; long y; }
void test(Foo foo) {
   foo.tupleof[0] = 1; // set foo.x to 1
   foo.tupleof[1] = 2; // set foo.y to 2
   foreach (x; foo.tupleof)
 writef(x);// prints 12
}


I would at least consider it bad practice. Even if the compiler 
guarantees a specific order it's quite easy for the developer to change 
the order of the fields in Foo and then have test break.


I would suggest one always access the fields by name. Example:

https://github.com/jacob-carlborg/orange/blob/master/orange/serialization/Serializer.d#L1448

https://github.com/jacob-carlborg/orange/blob/master/orange/util/Reflection.d#L260


It would be nice if the Language Reference was specific on this point.
I am aware that the order of the members returned by
__traits(allMembers, D) is not defined (per the LR). But that is a
larger, more complex list.

I am just beginning with D, but I think having the tupleof property for
classes and structs return their fields in lexical order might be useful.


1. It wouldn't hurt if it was clearly specified in the language 
specification.

2. You can always sort the list
3. I wouldn't count on the order regardless, see above


E.g., I have written a scan function to load up a struct or class from
a row returned by a database query. I have, say, scan!x,y,z(obj) to
load data into fields x,y,z of obj. Based on the example above and by
experimenting, it appears that at least for dmd running on Linux, that
the fields returned by tupleof are indeed in lexical order.  That
allowed me to have a  default for the string of field names which
indicates that all the fields should be loaded. I.e., I have
scan!(obj), which can be written scan(obj). Again, it seems to work
for simple classes and structs with Dmd on Ubuntu.


Indeed, DMD seems to return them in lexical order, but again, I wouldn't 
rely on the, see above.



Don't get me wrong -- I'll be happy without the default version if that
is the answer. I'm not suggesting any changes.




--
/Jacob Carlborg


Re: Reordered class fields?

2012-10-31 Thread bearophile

Peter Summerland:

The order of the fields is rearranged for packing. Does that 
affect the tupleof property? The example in 
http://dlang.org/class.html for Class properties tulpleof seems 
to implie that the the fields the returned Expression Tuple are 
arranged in lexical order (i.e., as defined by the programmer 
in the class definition). Is this always true for classes?


I have added your question here:
http://d.puremagic.com/issues/show_bug.cgi?id=8873



What about structs?


D structs are almost PODs (if they are nested inside a function 
and they are not defined as static they have one more field at 
the beginning), so tupleof for structs gives the fields in 
definition order.


Bye,
bearophile


Re: getters and setters not an lvalue

2012-10-31 Thread bearophile

maarten van damme:


Is there a rationale behind this decision of not translating
test.value+=1 to test.value= test.value +1 ?


I think it's a temporary limit, meant to be removed/fixed.

Bye,
bearophile


Re: getters and setters not an lvalue

2012-10-31 Thread maarten van damme
Ok, looking forward to the fix :)

Btw, I have a foreach loop and in that foreach loop I want to decide
if the current element can stay and if not, I want to remove it. If
removing it yields an empty range in the foreach loop, it crashes.
What's the sane way to do this?


Re: getters and setters not an lvalue

2012-10-31 Thread Regan Heath
On Wed, 31 Oct 2012 14:08:18 -, maarten van damme  
maartenvd1...@gmail.com wrote:



Ok, looking forward to the fix :)

Btw, I have a foreach loop and in that foreach loop I want to decide
if the current element can stay and if not, I want to remove it. If
removing it yields an empty range in the foreach loop, it crashes.
What's the sane way to do this?


Altering the thing you're foreaching over is generally frowned upon  
because it causes issues like this.  Ideally D would const-ify the thing  
you're foreaching inside the body of the foreach to prevent it.  Usually  
you end up using for and an index value instead.


R

--
Using Opera's revolutionary email client: http://www.opera.com/mail/


Re: getters and setters not an lvalue

2012-10-31 Thread Jacob Carlborg

On 2012-10-31 13:46, maarten van damme wrote:

In my current code I'd like to do something ala:

void main(){
getsettest test=new getsettest();

test.value+=1;
}

class getsettest{
int myvalue;

this(){
}

@property{

int value(){
return myvalue;
}

void value(int value){
myvalue=value;
}
}
}

but this gives the following error:
test.d(4): Error: test.value() is not an lvalue

Is there a rationale behind this decision of not translating
test.value+=1 to test.value= test.value +1 ?


I think we need implement property rewrite to properly handle this.

--
/Jacob Carlborg


Re: Reordered class fields?

2012-10-31 Thread Peter Summerland
On Wednesday, 31 October 2012 at 08:23:26 UTC, Jacob Carlborg 
wrote:

On 2012-10-31 09:14, Peter Summerland wrote:


Thanks for the help.

Should the the following example, taken from the D Language 
Reference,
be considered incorrect or at least misleading? It clearly 
depends on

lexical ordering of the returned fields:

Class Properties

The .tupleof property returns an ExpressionTuple of all the 
fields in
the class, excluding the hidden fields and the fields in the 
base class.


class Foo { int x; long y; }
void test(Foo foo) {
  foo.tupleof[0] = 1; // set foo.x to 1
  foo.tupleof[1] = 2; // set foo.y to 2
  foreach (x; foo.tupleof)
writef(x);// prints 12
}


I would at least consider it bad practice. Even if the compiler 
guarantees a specific order it's quite easy for the developer 
to change the order of the fields in Foo and then have test 
break.




I would suggest one always access the fields by name. Example:

https://github.com/jacob-carlborg/orange/blob/master/orange/serialization/Serializer.d#L1448

https://github.com/jacob-carlborg/orange/blob/master/orange/util/Reflection.d#L260



Thanks for the links. I can probably use some of the Reflection 
module in my code. I am making a very minimal sqlite3 library, 
which mostly just manages connections and statements to ensure 
they are closed and finalized automatically. I did add bind, step 
and scan methods to the Sqlite3Stmt struct but that's about it. 
Other than that you have to use the native c interface.


More importantly, I think that it is really very instructive to 
read over your code.


Re breaking test. You are right of course. But in my case the POD 
object is meant only to be used to package a row of data. The 
client cannot change it. Here is an example of how I might make a 
function to query a database


// POD structure to package rows returned by query
struct Employee
{
  int id_num;
  string name;
  int rank;
}

// returns an array of Employee objs for employees with given rank
Employee[] getEmployees(Sqlite3 db, int rank)
{
  static string query =
select e_num, e_name, e_rank from employee where e_rank = ?;

  auto app = appender!(Employee[]);
  auto stmt = db.prepare(query);
  stmt.bind(rank);
  stmt.scanFields!(id_num,name,rank)(app); // SAFE
  //stmt.scanFields(app);  // WORKS FOR POD STRUCTS LIKE EMPLOYEE
  return app.data;
}

It's not the greatests: You have to change the query if the 
database changes or if you want to change Employee, etc. But at 
least the query and Employee are defined locally in your code.


It would be nice if the Language Reference was specific on 
this point.

I am aware that the order of the members returned by
__traits(allMembers, D) is not defined (per the LR). But that 
is a

larger, more complex list.

I am just beginning with D, but I think having the tupleof 
property for
classes and structs return their fields in lexical order might 
be useful.


1. It wouldn't hurt if it was clearly specified in the language 
specification.

2. You can always sort the list
3. I wouldn't count on the order regardless, see above

E.g., I have written a scan function to load up a struct or 
class from
a row returned by a database query. I have, say, 
scan!x,y,z(obj) to
load data into fields x,y,z of obj. Based on the example above 
and by
experimenting, it appears that at least for dmd running on 
Linux, that
the fields returned by tupleof are indeed in lexical order.  
That
allowed me to have a  default for the string of field names 
which

indicates that all the fields should be loaded. I.e., I have
scan!(obj), which can be written scan(obj). Again, it seems 
to work

for simple classes and structs with Dmd on Ubuntu.


Indeed, DMD seems to return them in lexical order, but again, I 
wouldn't rely on the, see above.


Don't get me wrong -- I'll be happy without the default 
version if that

is the answer. I'm not suggesting any changes.





Re: getters and setters not an lvalue

2012-10-31 Thread Maxim Fomin

On Wednesday, 31 October 2012 at 12:46:12 UTC, maarten van damme
wrote:

In my current code I'd like to do something ala:

void main(){
getsettest test=new getsettest();

test.value+=1;
}

class getsettest{
int myvalue;

this(){
}

@property{

int value(){
return myvalue;
}

void value(int value){
myvalue=value;
}
}
}

but this gives the following error:
test.d(4): Error: test.value() is not an lvalue



You can make int value() to return by reference.


Re: getters and setters not an lvalue

2012-10-31 Thread Maxim Fomin
On Wednesday, 31 October 2012 at 12:46:12 UTC, maarten van damme 
wrote:

Is there a rationale behind this decision of not translating
test.value+=1 to test.value= test.value +1 ?


Probably there were no such decision at all and you just ran into 
issue which has never worked. BTW properties are syntax construct 
which allows to omit braces when calling functions. You actually 
call value function which doesn't return value by reference.


Re: getters and setters not an lvalue

2012-10-31 Thread monarch_dodra
On Wednesday, 31 October 2012 at 12:46:12 UTC, maarten van damme 
wrote:

In my current code I'd like to do something ala:

void main(){
getsettest test=new getsettest();

test.value+=1;
}

class getsettest{
int myvalue;

this(){
}

@property{

int value(){
return myvalue;
}

void value(int value){
myvalue=value;
}
}
}

but this gives the following error:
test.d(4): Error: test.value() is not an lvalue

Is there a rationale behind this decision of not translating
test.value+=1 to test.value= test.value +1 ?


It's not that simple as test.value is not an LValue, so from 
the compiler's perspective test.value = test.value + 1 calls 
two different functions, that may or may not have anything to do 
with each other.


The expansion ++ = +=1 = a = a + 1 works if there is only 1 
lvalue the whole chain through.


Can the compiler really assume it can do that? And is it a smart 
move to allow it to make that assumption. What you have there is 
basically an encapsulated field, that does not leak its address:


You can take the filed, you can update it with a new value, but 
you can't modify it.


If you allow test.value+=1, then where does it end?

Is this legal?
//
void foo(int a) {...}
foo(test.value);
//

Would you want the compiler to expand it into:
//
void foo(int a) {...}

//scope for __temp
{
  auto __temp = test.value;
  foo(temp);
  test.value = temp;
}
//


IMO, if you take the time to write both functions, instead of 
just:

//
@property ref int front(){return myvalue;}
//
Then the compiler must assume you did it for a reason, and not 
mess with your code.


cast question

2012-10-31 Thread Dan

Why do the commented out calls to goo fail?

Thanks
Dan

-
import std.stdio;
struct S {
}
void goo(const ref S s) {
  writeln(s);
}
struct T {
  S s;
  void foo(const ref T other) const {
goo(s);
// Error: function fdsaf.goo (ref const(S) s) is
//not callable using argument types (S)
// goo(cast(S)s);
// goo(cast()s);   // same error
writeln(typeid(S),  , typeid(s),  ,
typeid(cast()s),  , typeid(cast(S)s));

  }
}
void main() {
  T t;
  t.foo(t);
  const S s1;
  S s2;
  goo(s1);
  goo(s2);
  goo(cast(S) s2);
  // goo(cast(S) s1); Also fails
}



Re: cast question

2012-10-31 Thread Tobias Pankrath

On Wednesday, 31 October 2012 at 16:59:14 UTC, Dan wrote:

Why do the commented out calls to goo fail?

Thanks
Dan



Compiles fine with git-head.


Re: getters and setters not an lvalue

2012-10-31 Thread maarten van damme
Ok, makes sense now :)

2012/10/31 monarch_dodra monarchdo...@gmail.com:
 On Wednesday, 31 October 2012 at 12:46:12 UTC, maarten van damme wrote:

 In my current code I'd like to do something ala:

 void main(){
 getsettest test=new getsettest();

 test.value+=1;
 }

 class getsettest{
 int myvalue;

 this(){
 }

 @property{

 int value(){
 return myvalue;
 }

 void value(int value){
 myvalue=value;
 }
 }
 }

 but this gives the following error:
 test.d(4): Error: test.value() is not an lvalue

 Is there a rationale behind this decision of not translating
 test.value+=1 to test.value= test.value +1 ?


 It's not that simple as test.value is not an LValue, so from the
 compiler's perspective test.value = test.value + 1 calls two different
 functions, that may or may not have anything to do with each other.

 The expansion ++ = +=1 = a = a + 1 works if there is only 1 lvalue the
 whole chain through.

 Can the compiler really assume it can do that? And is it a smart move to
 allow it to make that assumption. What you have there is basically an
 encapsulated field, that does not leak its address:

 You can take the filed, you can update it with a new value, but you can't
 modify it.

 If you allow test.value+=1, then where does it end?

 Is this legal?
 //
 void foo(int a) {...}
 foo(test.value);
 //

 Would you want the compiler to expand it into:
 //
 void foo(int a) {...}

 //scope for __temp
 {
   auto __temp = test.value;
   foo(temp);
   test.value = temp;
 }
 //

 
 IMO, if you take the time to write both functions, instead of just:
 //
 @property ref int front(){return myvalue;}
 //
 Then the compiler must assume you did it for a reason, and not mess with
 your code.


Re: cast question

2012-10-31 Thread Dan
On Wednesday, 31 October 2012 at 17:11:47 UTC, Tobias Pankrath 
wrote:

On Wednesday, 31 October 2012 at 16:59:14 UTC, Dan wrote:

Why do the commented out calls to goo fail?

Thanks
Dan



Compiles fine with git-head.


I did git clone: git clone 
https://github.com/D-Programming-Language/dmd.git

The top of history is:
-
Commits in HEAD
1e720552 * origin/master origin/HEAD master
 | Author: Walter Bright wal...@walterbright.com
 | Date:   Wed Oct 31 02:33:17 2012 -0700
-
Then I built only dmd per instructions here 
http://xtzgzorex.wordpress.com/2011/07/31/d-building-dmd-and-phobos-on-linux/


dmd -v
DMD64 D Compiler v2.061

I assume that is all that is necessary. I ran this dmd on the 
code (with comments removed of course) and got the same error:


dmd  -g -w -property  /.../tmp/fdsaf.d
/.../tmp/fdsaf.d(11): Error: function fdsaf.goo (ref const(S) s) 
is not callable using argument types (S)
/.../tmp/fdsaf.d(12): Error: function fdsaf.goo (ref const(S) s) 
is not callable using argument types (S)
/.../tmp/fdsaf.d(26): Error: function fdsaf.goo (ref const(S) s) 
is not callable using argument types (S)


Any suggestions?

Thanks
Dan



Re: getters and setters not an lvalue

2012-10-31 Thread Michael

but this gives the following error:
test.d(4): Error: test.value() is not an lvalue

Is there a rationale behind this decision of not translating
test.value+=1 to test.value= test.value +1 ?


http://forum.dlang.org/thread/xcbweciovapinaicx...@forum.dlang.org

and

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




Re: cast question

2012-10-31 Thread Tobias Pankrath
Ah, okay. I just dumped it into a file and ran dmd before leaving 
the office.


This looks like a compiler bug to me. The struct should be 
implicitly convertable to const(S)




Re: getters and setters not an lvalue

2012-10-31 Thread Andrej Mitrovic
On 10/31/12, Michael p...@m1xa.com wrote:
 http://d.puremagic.com/issues/show_bug.cgi?id=8006

I wonder if this is low-hanging fruit to implement in the DMD
frontend. Could we really just implement var.property += 5; to
var.property = var.property + 5; or is it much more complicated than
that..

I might have a go at this soon.


Re: getters and setters not an lvalue

2012-10-31 Thread Adam D. Ruppe
On Wednesday, 31 October 2012 at 22:46:17 UTC, Andrej Mitrovic 
wrote:

I wonder if this is low-hanging fruit to implement in the DMD
frontend.


I tried it and found getting almost there is easy... but getting 
it

to work in a bunch of edge cases is incredibly difficult.


Re: getters and setters not an lvalue

2012-10-31 Thread Andrej Mitrovic
On 10/31/12, Adam D. Ruppe destructiona...@gmail.com wrote:
 On Wednesday, 31 October 2012 at 22:46:17 UTC, Andrej Mitrovic
 wrote:
 I wonder if this is low-hanging fruit to implement in the DMD
 frontend.

 I tried it and found getting almost there is easy... but getting
 it
 to work in a bunch of edge cases is incredibly difficult.


Could you share the failing test-cases? The patches would be welcome too! :]


modules in other directory trees

2012-10-31 Thread dsmith
What is your way to import modules from other directory trees?  
Here is my (incorrect?) ideal:


Given:
/home/user/library_directory/

Containing:
lib_one.d
lib_two.d
lib_interface.d

lib_interface.d source:
module lib_interface;
public import lib_one, lib_two;

Implementation in program /home/user/programs/main.d:
cd /home/user/programs
ln -s /home/user/library_directory/lib_interface.d
// or include in dmd.conf: -I/path_to/library_directory

main.d source:
import lib_interface;
...

Compile program:
dmd main.d lib_interface.d



Ranges and Library and toir.c internal error

2012-10-31 Thread StupidIsAsStupidDoes


There may be a better way to solve this but I'm trying to learn 
Phobos and parameter typing and anonymous function, etc.  So this 
is probably more of an academic question but I've got the 
following code:


int countBetween(T)(T[] x, T low, T high)
{
   auto k = count!( (x){return ((x = low)  (x = high));} ) 
(x);

   return k;
}

int[] a = [ 9, 77, 1, 13, 76, 17, 4, 27, 99, 5 ];

auto m = countBetween!(int)(a, 1, 25);  // works!


char[] b = ['h', 'e', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd'];

auto n = countBetween!(char)(b, 'c', 'k');  // fails



The integer call compiles and runs correctly.

The char call doesn't compile and I get a toir.c internal error.


The library definition says count is
size_t count(alias pred = true, Range)(Range r);


I'm still trying to get my head around Ranges. Is a int array a 
valid range but a character array not?


Any enlightenment is welcome.




Re: Ranges and Library and toir.c internal error

2012-10-31 Thread bearophile

StupidIsAsStupidDoes:


The char call doesn't compile and I get a toir.c internal error.


Such internal errors are compiler bugs that should be added to 
Bugzilla.


But I have compiled the following program with the latest DMD 
GIT-head 32 bit Windows, and I see no compiler bugs:



import std.algorithm: count;

int countBetween(T)(T[] x, T low, T high) {
return x.count!(x = x = low  x = high)();
}

void main() {
int[] a = [9, 77, 1, 13, 76, 17, 4, 27, 99, 5];
auto m = countBetween(a, 1, 25);

char[] b = ['h', 'e', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd'];
auto n = countBetween(b, 'c', 'k');
}

Bye,
bearophile


Re: Ranges and Library and toir.c internal error

2012-10-31 Thread Ellery Newcomer

On 10/31/2012 04:35 PM, StupidIsAsStupidDoes wrote:


The char call doesn't compile and I get a toir.c internal error.



On a recent dmd  build from github, I don't get any ICE, so it may have 
been fixed. I do get some disconcerting type deduction failures, though...



I'm still trying to get my head around Ranges. Is a int array a valid
range but a character array not?


All arrays are valid ranges, but char[], wchar[], and const variations 
thereof are special. They are treated as ranges of dchar so that you are 
guaranteed to get complete unicode characters out of them.


your code, modified:

import std.traits;

size_t countBetween(Range)(Range arr, ElementType!Range low, 
ElementType!Range high) {

return count!( (x){return ((x = low)  (x = high)); })(arr);
}

ought to handle both int[] and char[] properly.