www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Some quick questions

reply =?UTF-8?B?TcOhcmNpbyBGYXVzdGlubw==?= <m.faustino no.spam.gmail.com> writes:
Hi, I have some quick questions:

(1.) Why does version 2.0 of the compiler doesn't allow changing the 
index of a foreach loop? For example:

;string format = "%s";
;
;foreach (i, c; format) {
;	if (c != '%') {
;		// ...
;		continue;
;	}
;	
;	switch (format[++i]) {
;	case 's':
;		// ...
;		break;
;	// ...
;	}
;}

Instead of the (more tedious):

;string format = "%s";
;bool was_escape = false;
;
;foreach (i, c; format) {
;	if (was_escape) {
;		was_escape = false;
;		continue;
;	}
;	if (c != '%') {
;		// ...
;		continue;
;	}
;	
;	was_escape = true;
;	switch (format[++i]) {
;	case 's':
;		// ...
;		break;
;	// ...
;	}
;}


(2.) What's the rationale for opEquals returning an int, given that we 
have a bool data type? (And it clearly returns a boolean value.)

(3.) Shouldn't the toHash method of the Object class return 
"cast(hash_t) cast(void*) this" instead of "cast(uint) cast(void*) 
this", since the hash_t type is defined differently for x86 and x64?

(4.) Shouldn't the equals method of the TypeInfo_i class use casts to 
int's instead of uint's, since that TypeInfo class is for int's?

Thanks!
Aug 07 2007
next sibling parent Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
Márcio Faustino wrote:
 Hi, I have some quick questions:
 
 (1.) Why does version 2.0 of the compiler doesn't allow changing the 
 index of a foreach loop? For example:
 
 ;string format = "%s";
 ;
 ;foreach (i, c; format) {
 ;    if (c != '%') {
 ;        // ...
 ;        continue;
 ;    }
 ;   
 ;    switch (format[++i]) {
 ;    case 's':
 ;        // ...
 ;        break;
 ;    // ...
 ;    }
 ;}
 
 Instead of the (more tedious):
 
 ;string format = "%s";
 ;bool was_escape = false;
 ;
 ;foreach (i, c; format) {
 ;    if (was_escape) {
 ;        was_escape = false;
 ;        continue;
 ;    }
 ;    if (c != '%') {
 ;        // ...
 ;        continue;
 ;    }
 ;   
 ;    was_escape = true;
 ;    switch (format[++i]) {
 ;    case 's':
 ;        // ...
 ;        break;
 ;    // ...
 ;    }
 ;}

I remember there being a reason... darned if I recall it exactly, though. And actually I think the reasoning had mainly to do with inout indices, as changing them potentially leads to undefined behavior. (Just like modifying an array while foreach'ing over it is a problem.) Times like this I wish there was a 'skip' command for loops, or at least some reasonable allowances.
 
 (2.) What's the rationale for opEquals returning an int, given that we 
 have a bool data type? (And it clearly returns a boolean value.)

Historical reasons. Although, you actually /can/ define it as returning bool and nothing will break -- D's bool and int types are the same under the hood, and implicitly cast.
 (3.) Shouldn't the toHash method of the Object class return 
 "cast(hash_t) cast(void*) this" instead of "cast(uint) cast(void*) 
 this", since the hash_t type is defined differently for x86 and x64?

Yes. Yes it should. :)
 (4.) Shouldn't the equals method of the TypeInfo_i class use casts to 
 int's instead of uint's, since that TypeInfo class is for int's?

Possibly. Unless there's some tiny gain in casting to an unsigned type over a signed? (I really doubt it.) -- Chris Nicholson-Sauls
Aug 07 2007
prev sibling next sibling parent reply BCS <ao pathlink.com> writes:
Reply to Márcio,

 Hi, I have some quick questions:
 
 (1.) Why does version 2.0 of the compiler doesn't allow changing the
 index of a foreach loop? For example:
 
 ;string format = "%s";
 ;
 ;foreach (i, c; format) {
 ;	if (c != '%') {
 ;		// ...
 ;		continue;
 ;	}
 ;
 ;	switch (format[++i]) {
 ;	case 's':
 ;		// ...
 ;		break;
 ;	// ...
 ;	}
 ;}

every time I see the index changed my toes curl. It just seems wrong. I'd do this: ;string format = "%s"; ;int next = 0; ;foreach (i, c; format) ;{ ; if(i != next) continue; ; if (c != '%') ; { ; // ... ; continue; ; } ; next = i + 1; ; switch (format[next]) ; { ; case 's': ; // ... ; break; ; // ... ; } ;}
Aug 07 2007
parent reply Regan Heath <regan netmail.co.nz> writes:
BCS wrote:
 Reply to Márcio,
 
 Hi, I have some quick questions:

 (1.) Why does version 2.0 of the compiler doesn't allow changing the
 index of a foreach loop? For example:

 ;string format = "%s";
 ;
 ;foreach (i, c; format) {
 ;    if (c != '%') {
 ;        // ...
 ;        continue;
 ;    }
 ;
 ;    switch (format[++i]) {
 ;    case 's':
 ;        // ...
 ;        break;
 ;    // ...
 ;    }
 ;}

every time I see the index changed my toes curl. It just seems wrong. I'd do this: ;string format = "%s"; ;int next = 0; ;foreach (i, c; format) ;{ ; if(i != next) continue; ; if (c != '%') ; { ; // ... ; continue; ; } ; next = i + 1; ; switch (format[next]) ; { ; case 's': ; // ... ; break; ; // ... ; } ;}

I'd use a for loop. That said it would be nice if there was a nicer way to do this with foreach as it's the only 'container agnostic' way of iterating, right? Regan
Aug 08 2007
parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Regan Heath" <regan netmail.co.nz> wrote in message 
news:f9btus$2oqv$1 digitalmars.com...
 I'd use a for loop.  That said it would be nice if there was a nicer way 
 to do this with foreach as it's the only 'container agnostic' way of 
 iterating, right?

Of course, depending on the container, changing the index may or may not make any sense. Arrays are linear, maps are not. So if you have a foreach loop that could skip elements, it would only be useful on those containers where skipping ahead made sense (you lose one element of that agnosticity (if that's even a word (which I doubt it is :X ))). I'd say when you start needing to change the index, use a for loop; that's what it's there for.
Aug 08 2007
prev sibling parent reply =?UTF-8?B?TcOhcmNpbyBGYXVzdGlubw==?= <m.faustino no.spam.gmail.com> writes:
Thanks for all your replies. I have one more quick question: how do I 
access union's members, inside a struct? For example:

;struct S {
;	union u {
;		ubyte b;
;		uint i;
;	}
;}
;S s;
;ubyte b = s.u.b;    // Error: need 'this' to access member b

Thanks!
Aug 08 2007
parent reply BCS <ao pathlink.com> writes:
Reply to Márcio,

 Thanks for all your replies. I have one more quick question: how do I
 access union's members, inside a struct? For example:
 
 ;struct S {
 ;	union u {
 ;		ubyte b;
 ;		uint i;
 ;	}
 ;}
 ;S s;
 ;ubyte b = s.u.b;    // Error: need 'this' to access member b
 Thanks!
 

;struct S { ; union u { ; ubyte b; ; uint i; ; } ;} ;S s; ;ubyte b = s.u.b; // Error: need 'this' to access member b The reason that doesn’t work is that the uses of union there is a type deceleration, not a member declaration. So you get a struct without any content. option 1 use anonymous unions ;struct S { ; union { ; ubyte b; ; uint i; ; } ;} ;S s; ;ubyte b = s.b; option 2: ;struct S { ; union U { ; ubyte b; ; uint i; ; } ; U u; ;} ;S s; ;ubyte b = s.u.b;
Aug 08 2007
parent reply =?UTF-8?B?TcOhcmNpbyBGYXVzdGlubw==?= <m.faustino no.spam.gmail.com> writes:
BCS wrote:
 The reason that doesn’t work is that the uses of union there is a type 
 deceleration, not a member declaration. So you get a struct without any 
 content.
 
 (...)

How dumb of me :-| sorry. Here's another question, given these 2 files: // F1.d ------------------------- module F1; import F2; void f(int i, int j) {} void main() { f(1); } // F2.d ------------------------- module F2; void f(int i) {} Why does the compiler says: function F1.f (int,int) does not match parameter types (int) Error: expected 2 arguments, not 1 Looks like the import of F2 isn't working, because if I replace f(1) with F2.f(1), it works ok. Thanks!
Aug 08 2007
parent reply Carlos Santander <csantander619 gmail.com> writes:
Márcio Faustino escribió:
 BCS wrote:
 The reason that doesn’t work is that the uses of union there is a type 
 deceleration, not a member declaration. So you get a struct without 
 any content.

 (...)

How dumb of me :-| sorry. Here's another question, given these 2 files: // F1.d ------------------------- module F1; import F2;

alias F2.f f;
 void f(int i, int j) {}
 void main() { f(1); }
 
 // F2.d -------------------------
 module F2;
 
 void f(int i) {}
 
 Why does the compiler says:
 function F1.f (int,int) does not match parameter types (int)
 Error: expected 2 arguments, not 1
 
 Looks like the import of F2 isn't working, because if I replace f(1) 
 with F2.f(1), it works ok.
 
 Thanks!

This is normal D behavior due to its look-up rules. I'm sure someone else will give you a more detailed explanation. -- Carlos Santander Bernal
Aug 08 2007
parent reply =?UTF-8?B?TcOhcmNpbyBGYXVzdGlubw==?= <m.faustino no.spam.gmail.com> writes:
Carlos Santander wrote:
 This is normal D behavior due to its look-up rules. I'm sure someone 
 else will give you a more detailed explanation.

Didn't know that, thanks. Another question, why pointers to structs are automatically dereferenced when accessing members, but I cannot use them in "with" statements? For example: struct S { int i; char c; } S s; S* ps = &s; with (s) {} with (*ps) {} // Would also be nice if I could do: with (ps)
Aug 09 2007
parent reply Carlos Santander <csantander619 gmail.com> writes:
Márcio Faustino escribió:
 
 Another question, why pointers to structs are automatically dereferenced 
 when accessing members, but I cannot use them in "with" statements? For 
 example:
 
 struct S {
     int i;
     char c;
 }
 
 S s;
 S* ps = &s;
 
 with (s) {}
 with (*ps) {}    // Would also be nice if I could do: with (ps)

Good question. It has been in the issue database for a while now (http://d.puremagic.com/issues/show_bug.cgi?id=658), but Walter hasn't said anything about it. -- Carlos Santander Bernal
Aug 09 2007
parent reply =?UTF-8?B?TcOhcmNpbyBGYXVzdGlubw==?= <m.faustino no.spam.gmail.com> writes:
Hi,

Does someone knows why isn't possible to do something like this:

//-------------------------------------------
import std.regexp;

class A {
	RegExp pattern = new RegExp(".*");
}

RegExp[] patterns = [new RegExp(".*")];
//-------------------------------------------

Thanks,
Aug 22 2007
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Márcio Faustino" <m.faustino no.spam.gmail.com> wrote in message 
news:fah26g$2ctr$1 digitalmars.com...
 Hi,

 Does someone knows why isn't possible to do something like this:

 //-------------------------------------------
 import std.regexp;

 class A {
 RegExp pattern = new RegExp(".*");
 }

 RegExp[] patterns = [new RegExp(".*")];
 //-------------------------------------------

 Thanks,

Because those expressions aren't constant. Hate to sound obvious XD You can't use non-constant expressions (like function calls (well.... because of CTFE sometimes those are legal), 'new') as the initializer to globals or class members because the compiler builds up their initializers in the static data segment. Fortunately there are ways to do this: class A { RegExp pattern; this() { // Initialize dynamic members in the constructor. pattern = new RegExp(".*"); } } RegExp[] patterns; static this() { // Initialize dynamic globals in a static constructor. patterns = [new RegExp(".*")]; }
Aug 22 2007
parent =?UTF-8?B?TcOhcmNpbyBGYXVzdGlubw==?= <m.faustino no.spam.gmail.com> writes:
Jarrett Billingsley wrote:
 Because those expressions aren't constant.  Hate to sound obvious XD
 
 You can't use non-constant expressions (like function calls (well.... 
 because of CTFE sometimes those are legal), 'new') as the initializer to 
 globals or class members because the compiler builds up their initializers 
 in the static data segment.  Fortunately there are ways to do this:
 
 (...)
 

Thanks! ;-)
Aug 22 2007