Re: %x and floats

2011-02-25 Thread Lars T. Kyllingstad
On Thu, 24 Feb 2011 13:27:39 -0500, Trass3r wrote:

> Why doesn't this work:
> 
> import std.stdio;
> void main()
> {
>   float a,b=0;
>   writefln("%x %x", a, b);
> }
> 
> std.format.FormatError: std.format floating

That is because %x is for formatting integers.  If you want a hex 
representation of a floating-point number, use %a.

http://www.digitalmars.com/d/2.0/phobos/std_format.html

-Lars


override to!string

2011-02-25 Thread spir

Hello,

Imagine I have the following custom type:
alias float[] Numbers;

Is it possible to override to!string for Numbers so that it outputs eg like;
(1.1 2.2 3.3)
?

I can indeed override/specialise toImpl or formatValue for the custom type, but 
those overrides are simply ignored (tested).


Denis
--
_
vita es estrany
spir.wikidot.com



implicite deref on array element access? (indexing)

2011-02-25 Thread spir

Hello,

I thought it worked, just like implicite deref on (struct, class) member 
access. But I cannot have it work:


auto a = [1,2,3];
auto pa = &a;
writeln((*pa)[2]);  // ok
writeln(pa[2]); // segfault

Denis
--
_
vita es estrany
spir.wikidot.com



Re: rdmd problems (OS X Leopard, DMD 2.052)

2011-02-25 Thread Magnus Lie Hetland

On 2011-02-22 22:46:41 +0100, Paolo Invernizzi said:


Hi Magnus,

This is sligthly OT, but... How I loved AnyGui!


Haha, cool :D Yeah, too bad the project died. Oh, well -- at least we tried :)


It's nice to see you here, in the D bandwagon...


Yeah, I've been looking for a more "close to the metal" language to 
complement Python for a looong time (using C and C++ when I had to -- 
and sometimes Java or Cython and what-have-you). At the moment I'm 
hopeful that D might be what I've been looking for. Loving it so far :)


(Still using Python, though. Just came out with a new Python book, 
"Python Algorithms", last fall ;)




--
Magnus Lie Hetland
http://hetland.org



Re: implicite deref on array element access? (indexing)

2011-02-25 Thread Andrej Mitrovic
This should explain everything:

auto a = [1,2,3];
auto pa = &a;
writeln(&pa);
writeln(&pa+1);

Do the math!


Re: override to!string

2011-02-25 Thread Jesse Phillips
spir Wrote:

> Hello,
> 
> Imagine I have the following custom type:
>   alias float[] Numbers;
> 
> Is it possible to override to!string for Numbers so that it outputs eg like;
>   (1.1 2.2 3.3)
> ?

No, this is one reason for writeTo replacing toString, or whatever the name. It 
would allow a formatter specified. I don't really know how to! would be changed 
to fit into that.


> I can indeed override/specialise toImpl or formatValue for the custom type, 
> but 
> those overrides are simply ignored (tested).

Right, that would be anti-hijacking at work. Don't want behavior changed 
because you imported a module. You might be able to override to itself though.

Otherwise you can use format specifiers from std.string.format.


Re: implicite deref on array element access? (indexing)

2011-02-25 Thread Andrej Mitrovic
Actually that doesn't explain anything!

What I mean is, arrays in D are not the same as arrays in C.

auto a = [1, 2, 3];
auto pa = &a;

writeln(&a[0]);
writeln(&a[1]);
writeln(&a[2]);

writeln(&pa[0]);
writeln(&pa[1]);
writeln(&pa[2]);

9A2E40
9A2E44
9A2E48
12FE34
12FE3C
12FE44

Afaik D arrays have a length and then a pointer to the contents of the
array (someone correct me on this if I'm wrong?).


Re: rdmd problems (OS X Leopard, DMD 2.052)

2011-02-25 Thread Magnus Lie Hetland

On 2011-02-21 15:17:44 +0100, Jacob Carlborg said:


On 2011-02-21 14:16, Lars T. Kyllingstad wrote:


Say you have a file "myscript", that starts with the line

#!/path/to/interpreter --foo --bar

If you run this as

./myscript --hello --world

then the args[] received by the interpreter program looks like this:

args[0] = "/path/to/interpreter"
args[1] = "--foo --bar"
args[2] = "./myscript"
args[3] = "--hello"
args[4] = "--world"

This is the case on every shell I've tried on Linux, at least.


Let me first clarify: By "nothing happens", I really mean that. When I 
supply --shebang, the code isn't compiled, and nothing is run. Running 
the script becomes a no-op.


As for your example: The switches to rdmd *don't* appear in args for 
me. So for example, if I have


#!/path/to/rdmd -unittest

... as the shebang line, rdmd finds and passes the -unittest switch to 
dmd (my unit tests work). I get no problems when I add more switches 
either (i.e., rdmd doesn't complain). But, as far as I can see, none of 
these end up in args. (Or are we talking about different things here?)


Instead, args[0] contains the full path to the temporary executable 
built and run by rdmd, and args[1..$] contain any arguments I supplied 
when running the script.


The fact that --shebang borks the whole execution seems like it must be 
a bug. As for the rest of the behavior, it seems pretty useful to me, 
but perhaps OS X-specific? (That would be odd, but who knows...)


--
Magnus Lie Hetland
http://hetland.org



Re: implicite deref on array element access? (indexing)

2011-02-25 Thread Andrej Mitrovic
P.S. I got bitten by this when I was interfacing with C. Only in my
case I used multidimensional arrays. I just assumed they were the same
thing as in C, but I was wrong.


How do you test pre-/post-conditions and invariants?

2011-02-25 Thread Magnus Lie Hetland
Or, more generally, how do you test asserts (which is what I'm using in 
my preconditions etc.)?


As far as I can see, collectException() won't collect errors, which is 
what assert() throws -- so what's the standard way of writing unit 
tests for preconditions that use assert? (I.e., test that they will, in 
fact, throw when you break them.)


--
Magnus Lie Hetland
http://hetland.org



Re: implicite deref on array element access? (indexing)

2011-02-25 Thread Jesse Phillips
spir Wrote:

> Hello,
> 
> I thought it worked, just like implicite deref on (struct, class) member 
> access. But I cannot have it work:
> 
>  auto a = [1,2,3];
>  auto pa = &a;
>  writeln((*pa)[2]);  // ok
>  writeln(pa[2]); // segfault

You aren't making a pointer to the data, only the array. I probably would have 
made the same mistake, but I think you want to use:

auto pa = a.ptr;

Don't know if there is a ptr property for array.


Re: implicite deref on array element access? (indexing)

2011-02-25 Thread Steven Schveighoffer

On Fri, 25 Feb 2011 10:15:52 -0500, spir  wrote:


Hello,

I thought it worked, just like implicite deref on (struct, class) member  
access. But I cannot have it work:


 auto a = [1,2,3];
 auto pa = &a;
 writeln((*pa)[2]);  // ok
 writeln(pa[2]); // segfault


Because indexing a pointer like ptr[n] is the equivalent of *(ptr + n).

This is how it is in C.

Fun fact, you can avoid array bounds checks (if you know the index is  
valid) by doing arr.ptr[n]


-Steve


Re: implicite deref on array element access? (indexing)

2011-02-25 Thread Andrej Mitrovic
On 2/25/11, Steven Schveighoffer  wrote:
> Fun fact, you can avoid array bounds checks (if you know the index is
> valid) by doing arr.ptr[n]

Can't you do the same with -noboundscheck ?


Re: implicite deref on array element access? (indexing)

2011-02-25 Thread Steven Schveighoffer
On Fri, 25 Feb 2011 10:58:49 -0500, Andrej Mitrovic  
 wrote:



On 2/25/11, Steven Schveighoffer  wrote:

Fun fact, you can avoid array bounds checks (if you know the index is
valid) by doing arr.ptr[n]


Can't you do the same with -noboundscheck ?


No, -noboundscheck stops bounds checking everywhere.  arr.ptr[n] stops  
bounds checking for that one statement.  It's a lot easier to prove that  
one time that bounds checking is not necessary than it is to prove that no  
bounds checking is necessary anywhere.


Plus, you can't always control the command line.

-Steve


Re: override to!string

2011-02-25 Thread Dmitry Olshansky

On 25.02.2011 17:28, spir wrote:

Hello,

Imagine I have the following custom type:
alias float[] Numbers;

Is it possible to override to!string for Numbers so that it outputs eg 
like;

(1.1 2.2 3.3)
?

I can indeed override/specialise toImpl or formatValue for the custom 
type, but those overrides are simply ignored (tested).


Denis


First things first, it's just an alias and not a custom type. So 
compiler won't distinguish between float[] and Numbers at all.
The obvious way around is make your own thin wrapper, but yeah, it won't 
get format specifiers until writeTo or similar proposal implemented.


import std.stdio,std.conv;
struct Numbers{
float[] data;
string  toString(){
string result = "(";
foreach(val;data[0..$-1]){
result ~= to!string(val);
result ~= ' ';
}
result ~= to!string(data[$-1]);
result ~= ')';
return result;
}
alias data this;
}

Usage:
void main(){
Numbers nums = Numbers([1.1,2.2,3.3]);
writefln("%s",nums);
nums[0] = 4.4;
writefln("%s",nums);
}

--
Dmitry Olshansky



Re: How do you test pre-/post-conditions and invariants?

2011-02-25 Thread spir

On 02/25/2011 04:30 PM, Magnus Lie Hetland wrote:

Or, more generally, how do you test asserts (which is what I'm using in my
preconditions etc.)?

As far as I can see, collectException() won't collect errors, which is what
assert() throws -- so what's the standard way of writing unit tests for
preconditions that use assert? (I.e., test that they will, in fact, throw when
you break them.)


See the page on DbC: http://www.digitalmars.com/d/2.0/dbc.html.

Denis
--
_
vita es estrany
spir.wikidot.com



Re: implicite deref on array element access? (indexing)

2011-02-25 Thread spir

On 02/25/2011 04:43 PM, Steven Schveighoffer wrote:

On Fri, 25 Feb 2011 10:15:52 -0500, spir  wrote:


Hello,

I thought it worked, just like implicite deref on (struct, class) member
access. But I cannot have it work:

auto a = [1,2,3];
auto pa = &a;
writeln((*pa)[2]); // ok
writeln(pa[2]); // segfault


Because indexing a pointer like ptr[n] is the equivalent of *(ptr + n).

This is how it is in C.

Fun fact, you can avoid array bounds checks (if you know the index is valid) by
doing arr.ptr[n]


All right! This is what I did not get. Thank you, Steve.
Too bad. Anyway, in the meanwhile I have opted for another approach. (FWIW, in 
Oberon implicite deref works on array indexing just like on struct [record] 
member access.)


Denis
--
_
vita es estrany
spir.wikidot.com



Re: How do you test pre-/post-conditions and invariants?

2011-02-25 Thread Ary Manzana

On 2/25/11 1:48 PM, spir wrote:

On 02/25/2011 04:30 PM, Magnus Lie Hetland wrote:

Or, more generally, how do you test asserts (which is what I'm using
in my
preconditions etc.)?

As far as I can see, collectException() won't collect errors, which is
what
assert() throws -- so what's the standard way of writing unit tests for
preconditions that use assert? (I.e., test that they will, in fact,
throw when
you break them.)


See the page on DbC: http://www.digitalmars.com/d/2.0/dbc.html.

Denis


By the way, the link to "Adding Contracts to Java" at the bottom of the 
page is broken.


Re: How do you test pre-/post-conditions and invariants?

2011-02-25 Thread Jesse Phillips
Magnus Lie Hetland Wrote:

> Or, more generally, how do you test asserts (which is what I'm using in 
> my preconditions etc.)?
> 
> As far as I can see, collectException() won't collect errors, which is 
> what assert() throws -- so what's the standard way of writing unit 
> tests for preconditions that use assert? (I.e., test that they will, in 
> fact, throw when you break them.)

There has been talk of a std.unittest that would help with this, but for now:

unittest {
try {
 callMeWrong(wrong);
 assert(0);
catch(AssertError e) {
}
}

}


Foreach with byte problems

2011-02-25 Thread Andrej Mitrovic
So I'd like to print all values storable in a byte in hex representation:

import std.stdio;
void main()
{
int counter;
foreach (byte index; byte.min..byte.max)
{
if (!(counter % 4))
writeln();

writef("%#.2x, ", index);
counter++;
}
}

If you run this, you'll realize that it doesn't print the final 0x7F. This is 
because in a foreach range literal (is that the correct term?), the left side 
is inclusive, but the right side isn't. 

Hence this will run the foreach from 0 to 9:
foreach (index; 0..10) { }

So I figured I'd just add a +1 at the end, but then I get an error:
foreach (byte index; byte.min..byte.max+1)
{
}

Error: cannot implicitly convert expression (128) of type int to
byte. 

Of course 128 can't fit in a byte. But how am I supposed to print out the last 
value if the right hand side of a range literal is non-inclusive?

This behavior is kind of odd, don't you think?

byte.max is 127, but due to the way foreach works, the last value assigned to 
index is 126. If I was allowed to add +1 for RHS, the last value stored to 
index would be 127 due to the non-inclusive right side, which is completely 
legal. Yet DMD complains that I'm trying to store 128 to index.

I guess DMD first checks if the value on the RHS of the range literal can fit 
to a byte before it cuts one off due to the way range literals work. So how do 
I work around this?


Re: Foreach with byte problems

2011-02-25 Thread Steven Schveighoffer

On Fri, 25 Feb 2011 13:52:53 -0500, Andrej Mitrovic  wrote:


So I'd like to print all values storable in a byte in hex representation:

import std.stdio;
void main()
{
int counter;
foreach (byte index; byte.min..byte.max)
{
if (!(counter % 4))
writeln();
   writef("%#.2x, ", index);
counter++;
}
}

If you run this, you'll realize that it doesn't print the final 0x7F.  
This is because in a foreach range literal (is that the correct term?),  
the left side is inclusive, but the right side isn't.


Hence this will run the foreach from 0 to 9:
foreach (index; 0..10) { }

So I figured I'd just add a +1 at the end, but then I get an error:
foreach (byte index; byte.min..byte.max+1)
{
}

Error: cannot implicitly convert expression (128) of type int to
byte.

Of course 128 can't fit in a byte. But how am I supposed to print out  
the last value if the right hand side of a range literal is  
non-inclusive?


foreach(int index; byte.min..byte.max + 1)

The truth is, you don't want to use byte to represent your comparisons,  
because byte.max + 1 isn't a valid byte.


And instead of counter, you can use a formula instead:

if((index - byte.min) % 4 == 0)
   writeln();

-Steve


Re: How do you test pre-/post-conditions and invariants?

2011-02-25 Thread Jonathan M Davis
On Friday, February 25, 2011 07:30:50 Magnus Lie Hetland wrote:
> Or, more generally, how do you test asserts (which is what I'm using in
> my preconditions etc.)?
> 
> As far as I can see, collectException() won't collect errors, which is
> what assert() throws -- so what's the standard way of writing unit
> tests for preconditions that use assert? (I.e., test that they will, in
> fact, throw when you break them.)

I think that the reality of the matter is the most of the time people _don't_ 
check them. And on some level, it doesn't make sense to. It's kind of like 
asking how people test their unit tests. Unit tests are already testing code. 
Do 
you want to be testing them on top of that? And if you do, do you test _that_ 
code? Where do you stop?

Pre-conditions, post-conditions, and invariants are testing the class or struct 
that they're on, and to some extent, the code that uses them. So, if you're 
looking to test them, you're looking to test test code.

And testing post-conditions and invariants in the manner that you're trying to 
do borders on impossible. What are you going to do, repeat the post-condition 
or 
invariant test on the result of the function or on the state of the object that 
the function was called on after the function was called? That's just doing the 
test twice. You might as well just re-read the post-conditions and invariants 
to 
make sure that you wrote them correctly.

I do see value in testing pre-conditions if you're using exceptions rather than 
assertions (which means that you're not use in blocks). In that case, you're 
testing the API to make sure that it does what it's supposed to do. But if 
you're dealing with assertions, then it's really test code as opposed to API 
code, and I don't see the same value in testing that. You'd just be testing 
test 
code.

Now, assuming that you _do_ want to test that sort of thing (as you obviously 
want to), some new unit testing functions which would help were recently 
reviewed on the D newsgroup and voted for inclusion in Phobos. There's a pull 
request for them, but they haven't been merged in yet, and unless you use the 
development version of Phobos from git, you'll have to wait for the next 
release 
regardless. Those changes _do_ make it so that you can use collectException to 
collect an Error (though it defaults to catching Exceptions only), but they 
also 
include assertThrown and assertNotThrown which effectively assert that the 
Exception or Error that you expected to be thrown (or not) from a particular 
expression or function call was indeed thrown (or not). So, you _can_ use that 
with AssertError to verify your pre-conditions.

However, I would point out that catching Errors is generally a _bad_ idea. If 
you're careful in unit testing code, you should be okay, but _don't_ do it in 
normal code, and if you're not careful, you'll still get into trouble with unit 
testing code. Unlike with Exceptions, when an Error is thrown, scope statements 
and finally blocks do not run. I don't believe that destructors are run either. 
It's pretty much assumed that you can't recover from an Error, so no attempt to 
recover is made. Your program runs a high risk of being in an invalid state 
after an Error is thrown - AssertError included. In a unit test, if you're 
dealing with simple stuff, then you're probably okay, but if you have any code 
in 
there that would be affected by scope statements, finally blocks, destructors, 
etc. not running, then you don't want to be catching any Errors and then trying 
to continue.

So, functions which will help you with such testing are on their way, but they 
weren't released with the latest release of dmd, and once they have been 
released, you're going to need to be careful if you use them to test 
AssertErrors or any other kind of Error.

- Jonathan M Davis


Re: Foreach with byte problems

2011-02-25 Thread Andrej Mitrovic
Maybe it's best to let D do type infering for me. This works ok:

foreach (index; byte.min..byte.max+1)
{
if((index - byte.min) % 4 == 0)
writeln();

writef("%#.2x, ", index);
}

I'm fine with that.

Now, what's wrong with this code:

auto foo = iota(byte.min, byte.max-1);  // ok
// foo = [0, 1, .., 124, 125]

auto bar = iota(byte.min, byte.max);  // fails
// Errors:
// D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\range.d(3868):
Error: cannot implicitly convert expression (cast(int)pastLast - 1) of
type int to byte
// D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\range.d(3873):
Error: cannot implicitly convert expression (cast(int)pastLast + 1) of
type int to byte
// D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\range.d(3890):
Error: cannot implicitly convert expression
(cast(uint)cast(int)this.pastLast - this.step) of type uint to byte


array idioms

2011-02-25 Thread spir

Hello,

What's the idiomatic way to:

* delete an element in an associative array
* delete an element in a dyn array
* insert an element in a dyn array

Thank you,

Denis
--
_
vita es estrany
spir.wikidot.com



Re: Foreach with byte problems

2011-02-25 Thread Andrej Mitrovic
Can this be simplified?:

byte[] arr = to!(byte[])(array(iota(byte.min, byte.max+1)));

The +1 turns byte.max into an int that can store 128. So when I call
array on an iota, I'll get back an int[] of [-128, ..., 127]. And I
have to convert that to a byte[].


Re: Foreach with byte problems

2011-02-25 Thread spir

On 02/25/2011 07:52 PM, Andrej Mitrovic wrote:

So I'd like to print all values storable in a byte in hex representation:

import std.stdio;
void main()
{
 int counter;
 foreach (byte index; byte.min..byte.max)
 {
 if (!(counter % 4))
 writeln();

 writef("%#.2x, ", index);
 counter++;
 }
}

If you run this, you'll realize that it doesn't print the final 0x7F. This is 
because in a foreach range literal (is that the correct term?), the left side 
is inclusive, but the right side isn't.

Hence this will run the foreach from 0 to 9:
foreach (index; 0..10) { }

So I figured I'd just add a +1 at the end, but then I get an error:
 foreach (byte index; byte.min..byte.max+1)
 {
 }

Error: cannot implicitly convert expression (128) of type int to
byte.

Of course 128 can't fit in a byte. But how am I supposed to print out the last 
value if the right hand side of a range literal is non-inclusive?

This behavior is kind of odd, don't you think?

byte.max is 127, but due to the way foreach works, the last value assigned to 
index is 126. If I was allowed to add +1 for RHS, the last value stored to 
index would be 127 due to the non-inclusive right side, which is completely 
legal. Yet DMD complains that I'm trying to store 128 to index.

I guess DMD first checks if the value on the RHS of the range literal can fit 
to a byte before it cuts one off due to the way range literals work. So how do 
I work around this?


lol! One more source of fun in using half-open intervals :-)

Denis
--
_
vita es estrany
spir.wikidot.com



Re: Foreach with byte problems

2011-02-25 Thread Steven Schveighoffer
On Fri, 25 Feb 2011 14:15:52 -0500, Andrej Mitrovic  
 wrote:



Maybe it's best to let D do type infering for me. This works ok:

foreach (index; byte.min..byte.max+1)
{
if((index - byte.min) % 4 == 0)
writeln();

writef("%#.2x, ", index);
}

I'm fine with that.

Now, what's wrong with this code:

auto foo = iota(byte.min, byte.max-1);  // ok
// foo = [0, 1, .., 124, 125]

auto bar = iota(byte.min, byte.max);  // fails
// Errors:
// D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\range.d(3868):
Error: cannot implicitly convert expression (cast(int)pastLast - 1) of
type int to byte
// D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\range.d(3873):
Error: cannot implicitly convert expression (cast(int)pastLast + 1) of
type int to byte
// D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\range.d(3890):
Error: cannot implicitly convert expression
(cast(uint)cast(int)this.pastLast - this.step) of type uint to byte


IFTI is interpreting the element type of iota to byte.

You need to either explicitly instantiate iota (don't recommend this) or  
cast one of your args to int.


auto bar = iota(cast(int)byte.min, byte.max);

a dirty trick you could do is add 0, which should promote the arg to int.

-Steve


Re: Foreach with byte problems

2011-02-25 Thread Steven Schveighoffer
On Fri, 25 Feb 2011 14:34:35 -0500, Andrej Mitrovic  
 wrote:



Can this be simplified?:

byte[] arr = to!(byte[])(array(iota(byte.min, byte.max+1)));

The +1 turns byte.max into an int that can store 128. So when I call
array on an iota, I'll get back an int[] of [-128, ..., 127]. And I
have to convert that to a byte[].


This is a good puzzle.  You may have to do something with map and casting,  
but I don't see how it can be done with iota without a cast.


The right thing to do would be this:

for(byte i = -127; i < byte.max + 1; i++)
  arr ~= i;

which does everything as a byte, but does the comparisons as ints.

But I don't know how to make iota do this.

-Steve


Re: Foreach with byte problems

2011-02-25 Thread Andrej Mitrovic
On 2/25/11, Steven Schveighoffer  wrote:
> a dirty trick you could do is add 0, which should promote the arg to int.

Cool. I've almost used +1-1, LOL!

Well, I thought DMD would simply ignore +0 (dead code elimination?),
but apparently this is a cool shorthand for casting literals? Nice.


Re: array idioms

2011-02-25 Thread Andrej Mitrovic
On 2/25/11, spir  wrote:
> * delete an element in an associative array

Just use .remove?

void main()
{
auto var = ["a" : 1];
var.remove("b");// nothing happens
var.remove("a");// "a" key is gone

assert(!var.length);  // empty
}


Re: array idioms

2011-02-25 Thread Jonathan M Davis
On Friday, February 25, 2011 11:30:28 spir wrote:
> Hello,
> 
> What's the idiomatic way to:
> 
> * delete an element in an associative array

If you have the key, then just use remove. The online documentation for 
asseciative array discusses it. e.g.

b.remove("hello");

If you're looking to remove by value, however, you're going to have to figure 
out 
what its key is. And if you want to remove _all_ elements with the same value, 
then you're going to need to find _all_ of their keys. The best way to do that 
would probably just be to use a foreach loop:

foreach(k, v; aa)
{
if(v == value)
aa.remove(k);
}

I'm not sure if there are any problems with removing from an associative array 
while iterating over it though. I wouldn't think so, but I don't know so. Worst 
case though, you save the list of keys to remove and then remove them all once 
you have them all.

> * delete an element in a dyn array

I don't think that there is one right now. There should probably be a function 
in std.array which does what remove in std.container would do, but I don't 
believe that there's a function for it right now. So, the simplest way at the 
moment (albeit not the most efficient) would probably do to something like

auto found = findSplit(arr, value);
auto newArr = array(chain(found[0], found[2]));

The efficient way to do it, however, would involve shifting all of the elements 
in 
the array, which is more complicated and not the kind of code that you really 
want to be rewriting every time that you need to remove an element. But you 
_do_ 
need to remember that removing an arbitrary element from an array is _not_ 
cheap, because even in the most efficient case, that means moving a potentially 
large number of elements in the array - unlike a linked list where removal is 
cheap.

Of course, popFront and popBack would be the best way to remove from the ends 
of 
an array, and _that_ is efficient.

> * insert an element in a dyn array

Same as remove. There's no function for doing it at the moment. The best way at 
present would probably be to just concatenate the slices.

auto newArr = arr[0 .. i] ~ [value] ~ [i .. $];

But again, that's not particularly efficient. What you'd really want to do 
would 
be increase the size of the array by one, shift all of the elements after the 
insertion point over by one, and then set the element at the insertion point to 
the value that you're inserting. And of course, if appending to the array, ~= 
would be the best way to do it.

And again, inserting into arrays is _not_ efficient regardless, so if you're 
doing 
that sort of thing a lot, you probably should be using a different type of 
container.

- Jonathan M Davis


Re: Foreach with byte problems

2011-02-25 Thread Steven Schveighoffer
On Fri, 25 Feb 2011 14:51:18 -0500, Andrej Mitrovic  
 wrote:



On 2/25/11, Steven Schveighoffer  wrote:
a dirty trick you could do is add 0, which should promote the arg to  
int.


Cool. I've almost used +1-1, LOL!

Well, I thought DMD would simply ignore +0 (dead code elimination?),
but apparently this is a cool shorthand for casting literals? Nice.


No code is generated to add 0, but it does affect the type.

-Steve


Re: std.xml empty element

2011-02-25 Thread Tom

El 24/02/2011 19:40, Tom escribió:

El 24/02/2011 09:51, Jacob Carlborg escribió:

On 2011-02-24 06:48, Tom wrote:

Hi, how can I create an empty element with current D2 std.xml Element
implementation?

stdout.writeln(new Element("foo")); // Shields  instead of


Thanks in advance,
Tom;


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



I see :(
Thanks...


Lucky me, 2.052 solves this bug and doesn't break anything.

Tom;


Re: array idioms

2011-02-25 Thread Steven Schveighoffer
On Fri, 25 Feb 2011 15:09:44 -0500, Jonathan M Davis   
wrote:



On Friday, February 25, 2011 11:30:28 spir wrote:

Hello,

What's the idiomatic way to:

* delete an element in an associative array


If you have the key, then just use remove. The online documentation for
asseciative array discusses it. e.g.

b.remove("hello");

If you're looking to remove by value, however, you're going to have to  
figure out
what its key is. And if you want to remove _all_ elements with the same  
value,
then you're going to need to find _all_ of their keys. The best way to  
do that

would probably just be to use a foreach loop:

foreach(k, v; aa)
{
if(v == value)
aa.remove(k);
}

I'm not sure if there are any problems with removing from an associative  
array
while iterating over it though. I wouldn't think so, but I don't know  
so. Worst
case though, you save the list of keys to remove and then remove them  
all once

you have them all.


It is illegal to remove from an AA you are iterating.  I've learned first  
hand that this causes subtle memory bugs.  Do not do this.


However, dcollections supports this idiom via the purge operation:

foreach(ref doPurge, v; &mymap.purge)
   doPurge = (v == value);

-Steve


Re: array idioms

2011-02-25 Thread Andrej Mitrovic
On 2/25/11, Jonathan M Davis  wrote:
>
>> * insert an element in a dyn array
>
> Same as remove. There's no function for doing it at the moment.

std.array.insert:

int[] a = [ 1, 2, 3, 4 ];
a.insert(2, [ 1, 2 ]);
assert(a == [ 1, 2, 1, 2, 3, 4 ]);

afaik insert was missing from the documentation in the last release
(I've reported it), but now it's back in. So maybe that's why nobody
knew about it.


Re: array idioms

2011-02-25 Thread Jonathan M Davis
On Friday 25 February 2011 12:16:19 Steven Schveighoffer wrote:
> On Fri, 25 Feb 2011 15:09:44 -0500, Jonathan M Davis 
> 
> wrote:
> > On Friday, February 25, 2011 11:30:28 spir wrote:
> >> Hello,
> >> 
> >> What's the idiomatic way to:
> >> 
> >> * delete an element in an associative array
> > 
> > If you have the key, then just use remove. The online documentation for
> > asseciative array discusses it. e.g.
> > 
> > b.remove("hello");
> > 
> > If you're looking to remove by value, however, you're going to have to
> > figure out
> > what its key is. And if you want to remove _all_ elements with the same
> > value,
> > then you're going to need to find _all_ of their keys. The best way to
> > do that
> > would probably just be to use a foreach loop:
> > 
> > foreach(k, v; aa)
> > {
> > 
> > if(v == value)
> > 
> > aa.remove(k);
> > 
> > }
> > 
> > I'm not sure if there are any problems with removing from an associative
> > array
> > while iterating over it though. I wouldn't think so, but I don't know
> > so. Worst
> > case though, you save the list of keys to remove and then remove them
> > all once
> > you have them all.
> 
> It is illegal to remove from an AA you are iterating.  I've learned first
> hand that this causes subtle memory bugs.  Do not do this.

Good to know. I was wondering. It's simple enough though to just make a list of 
the keys to remove and then remove them afterwords.

- Jonathan M Davis


Re: array idioms

2011-02-25 Thread Jonathan M Davis
On Friday 25 February 2011 12:09:44 Jonathan M Davis wrote:
> On Friday, February 25, 2011 11:30:28 spir wrote:
> > * delete an element in a dyn array
> 
> I don't think that there is one right now. There should probably be a
> function in std.array which does what remove in std.container would do,
> but I don't believe that there's a function for it right now. So, the
> simplest way at the moment (albeit not the most efficient) would probably
> do to something like
> 
> auto found = findSplit(arr, value);
> auto newArr = array(chain(found[0], found[2]));
> 
> The efficient way to do it, however, would involve shifting all of the
> elements in the array, which is more complicated and not the kind of code
> that you really want to be rewriting every time that you need to remove an
> element. But you _do_ need to remember that removing an arbitrary element
> from an array is _not_ cheap, because even in the most efficient case,
> that means moving a potentially large number of elements in the array -
> unlike a linked list where removal is cheap.
> 
> Of course, popFront and popBack would be the best way to remove from the
> ends of an array, and _that_ is efficient.

Actually, on reflection, we probably _don't_ want a remove like std.container 
uses. What we probably want is something like remove and removeInPlace. The 
fact 
that dynamic arrays are really ranges rather than containers makes removing in 
place _far_ less desirable in many cases, and it's not necessarily a good idea 
to treat an array like a container in std.container.

- Jonathan M Davis


Re: array idioms

2011-02-25 Thread Jonathan M Davis
On Friday 25 February 2011 12:30:00 Andrej Mitrovic wrote:
> On 2/25/11, Jonathan M Davis  wrote:
> >> * insert an element in a dyn array
> > 
> > Same as remove. There's no function for doing it at the moment.
> 
> std.array.insert:
> 
> int[] a = [ 1, 2, 3, 4 ];
> a.insert(2, [ 1, 2 ]);
> assert(a == [ 1, 2, 1, 2, 3, 4 ]);
> 
> afaik insert was missing from the documentation in the last release
> (I've reported it), but now it's back in. So maybe that's why nobody
> knew about it.

Ah. Good to know. Its not the sort of thing that I'm generally looking to do, 
however, so I don't tend to think about it. I don't believe that I've ever seen 
the function in the docs before, so that would explain why didn't know about it.

- Jonathan M Davis


Re: array idioms

2011-02-25 Thread Andrej Mitrovic
I have asked for remove before, I got some responses here (in fact,
Jonathan made an enhancement request for it):

http://www.digitalmars.com/d/archives/digitalmars/D/learn/Removing_an_object_from_a_range_23212.html

The topic was derailed, but essentially you can provide a predicate as
a function literal to do the work:

import std.stdio;
import std.algorithm;

void main()
{
int[] elements = [1, 2, 3, 2, 4];
int needle = 2;

elements = remove!((item) {return item == needle;} )(elements);
assert(elements == [1, 3, 4]);
}


Re: array idioms

2011-02-25 Thread Jonathan M Davis
On Friday, February 25, 2011 12:51:53 Andrej Mitrovic wrote:
> I have asked for remove before, I got some responses here (in fact,
> Jonathan made an enhancement request for it):
> 
> http://www.digitalmars.com/d/archives/digitalmars/D/learn/Removing_an_objec
> t_from_a_range_23212.html
> 
> The topic was derailed, but essentially you can provide a predicate as
> a function literal to do the work:
> 
> import std.stdio;
> import std.algorithm;
> 
> void main()
> {
> int[] elements = [1, 2, 3, 2, 4];
> int needle = 2;
> 
> elements = remove!((item) {return item == needle;} )(elements);
> assert(elements == [1, 3, 4]);
> }

Actually, you can probably just use replace and give it an empty range for the 
third argument. Still, there should probably be a function in std.array which 
removes a value from an array based on its value. A function that's essentially 
identical to the version of replace which takes two ranges in addition to the 
array but doesn't take the range to replace with would probably do the trick:

R1 replace(R1, R2)(R1 subject,  R2 toRemove) if(...) {...}

- Jonathan M Davis


Re: Foreach with byte problems

2011-02-25 Thread Jonathan M Davis
On Friday, February 25, 2011 11:37:23 spir wrote:
> On 02/25/2011 07:52 PM, Andrej Mitrovic wrote:
> > So I'd like to print all values storable in a byte in hex representation:
> > 
> > import std.stdio;
> > void main()
> > {
> > 
> >  int counter;
> >  foreach (byte index; byte.min..byte.max)
> >  {
> >  
> >  if (!(counter % 4))
> >  
> >  writeln();
> >  
> >  writef("%#.2x, ", index);
> >  counter++;
> >  
> >  }
> > 
> > }
> > 
> > If you run this, you'll realize that it doesn't print the final 0x7F.
> > This is because in a foreach range literal (is that the correct term?),
> > the left side is inclusive, but the right side isn't.
> > 
> > Hence this will run the foreach from 0 to 9:
> > foreach (index; 0..10) { }
> > 
> > So I figured I'd just add a +1 at the end, but then I get an error:
> >  foreach (byte index; byte.min..byte.max+1)
> >  {
> >  }
> > 
> > Error: cannot implicitly convert expression (128) of type int to
> > byte.
> > 
> > Of course 128 can't fit in a byte. But how am I supposed to print out the
> > last value if the right hand side of a range literal is non-inclusive?
> > 
> > This behavior is kind of odd, don't you think?
> > 
> > byte.max is 127, but due to the way foreach works, the last value
> > assigned to index is 126. If I was allowed to add +1 for RHS, the last
> > value stored to index would be 127 due to the non-inclusive right side,
> > which is completely legal. Yet DMD complains that I'm trying to store
> > 128 to index.
> > 
> > I guess DMD first checks if the value on the RHS of the range literal can
> > fit to a byte before it cuts one off due to the way range literals work.
> > So how do I work around this?
> 
> lol! One more source of fun in using half-open intervals :-)

In the general case, having the first element of an interval be inclusive and 
the 
last one exclusive is perfect. That's how it works with iterators in C++. 
That's 
essentially how it works with array indices, since they start with 0 and their 
length is one greater than the last index. It's just plain nice and makes 
checking end conditions cleaner.

However, it is true that in this particular case, it's annoying. Still, in the 
general case, I do believe that it's definitely the right behavior.

- Jonathan M Davis


Re: Foreach with byte problems

2011-02-25 Thread Andrej Mitrovic
On 2/25/11, Jonathan M Davis  wrote:
> However, it is true that in this particular case, it's annoying. Still, in
> the
> general case, I do believe that it's definitely the right behavior.
>
> - Jonathan M Davis
>

I do agree it's the right thing to do, and I wouldn't want to change it.

But I'd like the compiler to be smart in this case and see that
there's no way 128 will ever be stored into a byte.

It's not some crucial piece of code that I need working. I just ran
into it by accident really.


Re: array idioms

2011-02-25 Thread spir

On 02/25/2011 08:55 PM, Andrej Mitrovic wrote:

On 2/25/11, spir  wrote:

* delete an element in an associative array


Just use .remove?

void main()
{
 auto var = ["a" : 1];
 var.remove("b");// nothing happens
 var.remove("a");// "a" key is gone

 assert(!var.length);  // empty
}


Sh*t, I have missed it. Sorry for the no*se. But where is this func 
implemented? I could not find it by browsing. (It's also not in object.d, 
apparently; while usually when I cannot find something, it's hidden in there ;-)


Denis
--
_
vita es estrany
spir.wikidot.com



Re: Foreach with byte problems

2011-02-25 Thread Ali Çehreli

On 02/25/2011 10:52 AM, Andrej Mitrovic wrote:

So I'd like to print all values storable in a byte in hex representation:

import std.stdio;
void main()
{
 int counter;
 foreach (byte index; byte.min..byte.max)
 {
 if (!(counter % 4))
 writeln();

 writef("%#.2x, ", index);
 counter++;
 }
}

If you run this, you'll realize that it doesn't print the final 0x7F. This is 
because in a foreach range literal (is that the correct term?), the left side 
is inclusive, but the right side isn't.


I've seen the same "problem" with enums.

import std.stdio;

enum E { x, y, z }

void main()
{
foreach (e; E.min .. E.max) {
writeln(e);
}
}

The value 2 is excluded. Of course it's rare to use enums like that in a 
foreach loop as their values are not always continuous.


I found out the better solution before sending this message:

foreach (e; __traits(allMembers, E)) {
writeln(e);
}

The difference is, the type of 'e' is string above. Finally, the 
following produces integer values:


foreach (e; __traits(allMembers, E)) {
writeln(to!E(e));
}

Ok, good... :)

Ali


Re: How do you test pre-/post-conditions and invariants?

2011-02-25 Thread Magnus Lie Hetland

On 2011-02-25 19:18:40 +0100, Jesse Phillips said:


There has been talk of a std.unittest that would help with this, but for now:



unittest {
try {
 callMeWrong(wrong);
 assert(0);
catch(AssertError e) {
}
}

}


Ah. I used something like...

auto thrown = 0;
try foo() catch (AssertError) thrown++;
...
assert(thrown == k);

I guess I could wrap it up a bit, or something.

--
Magnus Lie Hetland
http://hetland.org



Re: How do you test pre-/post-conditions and invariants?

2011-02-25 Thread Magnus Lie Hetland

On 2011-02-25 17:48:54 +0100, spir said:


On 02/25/2011 04:30 PM, Magnus Lie Hetland wrote:

Or, more generally, how do you test asserts (which is what I'm using in my
preconditions etc.)?

As far as I can see, collectException() won't collect errors, which is what
assert() throws -- so what's the standard way of writing unit tests for
preconditions that use assert? (I.e., test that they will, in fact, throw when
you break them.)


See the page on DbC: http://www.digitalmars.com/d/2.0/dbc.html.

Denis


Hm. I'm not sure how this answers my question. I know how 
pre/postconditions etc. work -- I was asking for how to test them in a 
unit test (i.e., ensure that they'll kick in if you provide faulty 
intput, for example). Maybe I'm missing something in the doc you 
referred me to?


--
Magnus Lie Hetland
http://hetland.org



Re: array idioms

2011-02-25 Thread Andrej Mitrovic
On 2/25/11, spir  wrote:
> But where is this func
> implemented?

DMD\dmd2\src\druntime\src\rt\aaA.d

_aaDel && _aaDelX

And then in object.d:
extern (C)
{
// from druntime/src/compiler/dmd/aaA.d
...
void _aaDel(void* p, TypeInfo keyti, ...);
...
}

I don't really know how it gets called since I don't see any explicit
calls to this function. This probably requires more insight into how
druntime and dmd work together.


Re: How do you test pre-/post-conditions and invariants?

2011-02-25 Thread Magnus Lie Hetland

On 2011-02-25 20:04:10 +0100, Jonathan M Davis said:


On Friday, February 25, 2011 07:30:50 Magnus Lie Hetland wrote:

Or, more generally, how do you test asserts (which is what I'm using in
my preconditions etc.)?

As far as I can see, collectException() won't collect errors, which is
what assert() throws -- so what's the standard way of writing unit
tests for preconditions that use assert? (I.e., test that they will, in
fact, throw when you break them.)


I think that the reality of the matter is the most of the time people _don't_
check them. And on some level, it doesn't make sense to. It's kind of like
asking how people test their unit tests. Unit tests are already testing 
code. Do

you want to be testing them on top of that? And if you do, do you test _that_
code? Where do you stop?


I guess so. But you could say the same thing about other cases where 
you throw an exception when you detect that something is wrong -- but 
those are normally tested, right? Also, the difference here is that the 
precondition is written as a general "test", whereas my actual test 
would have specific cases.


For example, I have a test that checks that I don't add the same object 
twice to some structure, and the check involves some traversal -- code 
that could potentially be wrong. I wanted to make sure that it wasn't 
by explicitly adding the same object twice -- code (i.e., my unit test) 
that most likely could not be wrong.


But I do see your point.

[snip]

And testing post-conditions and invariants in the manner that you're trying to
do borders on impossible. What are you going to do, repeat the 
post-condition or

invariant test on the result of the function or on the state of the object that
the function was called on after the function was called? That's just doing the
test twice.


Right.


You might as well just re-read the post-conditions and invariants to
make sure that you wrote them correctly.

I do see value in testing pre-conditions if you're using exceptions rather than
assertions (which means that you're not use in blocks). In that case, you're
testing the API to make sure that it does what it's supposed to do. But if
you're dealing with assertions, then it's really test code as opposed to API
code, and I don't see the same value in testing that. You'd just be 
testing test

code.


OK. For the practical reason, I refer you to my explanation above. But 
I guess it's a style issue -- and I'm fine with not testing these 
things, by all means.


[snip]

Those changes _do_ make it so that you can use collectException to
collect an Error (though it defaults to catching Exceptions only), but 
they also

include assertThrown and assertNotThrown which effectively assert that the
Exception or Error that you expected to be thrown (or not) from a particular
expression or function call was indeed thrown (or not).
So, you _can_ use that with AssertError to verify your pre-conditions.


OK, thanks.


However, I would point out that catching Errors is generally a _bad_ idea.

[snip lots of useful stuff]

Thanks for educating me :D

I guess the conclusion will be that I'll focus on keeping my 
preconditions really simple. (And any utility functions I use in them 
can then get unit tests of their own instead ;)


--
Magnus Lie Hetland
http://hetland.org



Re: array idioms

2011-02-25 Thread spir

On 02/25/2011 09:09 PM, Jonathan M Davis wrote:

On Friday, February 25, 2011 11:30:28 spir wrote:

Hello,

What's the idiomatic way to:

* delete an element in an associative array


If you have the key, then just use remove. The online documentation for
asseciative array discusses it. e.g.

b.remove("hello");

If you're looking to remove by value, however, you're going to have to figure 
out
what its key is. And if you want to remove _all_ elements with the same value,
then you're going to need to find _all_ of their keys. The best way to do that
would probably just be to use a foreach loop:

foreach(k, v; aa)
{
 if(v == value)
 aa.remove(k);
}

I'm not sure if there are any problems with removing from an associative array
while iterating over it though. I wouldn't think so, but I don't know so. Worst
case though, you save the list of keys to remove and then remove them all once
you have them all.


* delete an element in a dyn array


I don't think that there is one right now. There should probably be a function
in std.array which does what remove in std.container would do, but I don't
believe that there's a function for it right now. So, the simplest way at the
moment (albeit not the most efficient) would probably do to something like

auto found = findSplit(arr, value);
auto newArr = array(chain(found[0], found[2]));

The efficient way to do it, however, would involve shifting all of the elements 
in
the array, which is more complicated and not the kind of code that you really
want to be rewriting every time that you need to remove an element. But you _do_
need to remember that removing an arbitrary element from an array is _not_
cheap, because even in the most efficient case, that means moving a potentially
large number of elements in the array - unlike a linked list where removal is
cheap.

Of course, popFront and popBack would be the best way to remove from the ends of
an array, and _that_ is efficient.


* insert an element in a dyn array


Same as remove. There's no function for doing it at the moment. The best way at
present would probably be to just concatenate the slices.

auto newArr = arr[0 .. i] ~ [value] ~ [i .. $];

But again, that's not particularly efficient. What you'd really want to do would
be increase the size of the array by one, shift all of the elements after the
insertion point over by one, and then set the element at the insertion point to
the value that you're inserting. And of course, if appending to the array, ~=
would be the best way to do it.

And again, inserting into arrays is _not_ efficient regardless, so if you're 
doing
that sort of thing a lot, you probably should be using a different type of
container.


Thank you very much Jonathan. That's what I was afraid of (and why I asked): 
there is no builtin func for those operations because they cannot by simple & 
cheap. The issue, imo, by deletion or insertion (except at end) is we cannot 
even use something like memcopy because the source & target mem areas overlap 
(indeed). D also refuses idioms like (to delete 1 elem):

a[i..$-1]=a[i+1..$];
for the same reason.

Shifting elems by hand from insertion/deletion point is indeed not cheap, but 
avoids copying *all* (remaining) elements as is done by concat. I think there 
should be one builtin array-elem-shift functions that does that (also because 
it's easy to have wrong, since one must proceed backwards on insertion). The 
obvious process of the function (indicated by its name), and the fact that it 
is not called insert/delete, would clearly tell I guess that this is not cheap; 
while still providing the functionality.

What do you all think?

So, well, I'll just concatenate in the meantime.

Denis
--
_
vita es estrany
spir.wikidot.com



Re: array idioms

2011-02-25 Thread spir

On 02/25/2011 11:31 PM, Andrej Mitrovic wrote:

On 2/25/11, spir  wrote:

But where is this func
implemented?


DMD\dmd2\src\druntime\src\rt\aaA.d

_aaDel&&  _aaDelX

And then in object.d:
extern (C)
{
 // from druntime/src/compiler/dmd/aaA.d
 ...
 void _aaDel(void* p, TypeInfo keyti, ...);
 ...
}

I don't really know how it gets called since I don't see any explicit
calls to this function. This probably requires more insight into how
druntime and dmd work together.


Thanks, Andrej.

Denis
--
_
vita es estrany
spir.wikidot.com



Re: std.xml empty element

2011-02-25 Thread Jacob Carlborg

On 2011-02-25 21:11, Tom wrote:

El 24/02/2011 19:40, Tom escribió:

El 24/02/2011 09:51, Jacob Carlborg escribió:

On 2011-02-24 06:48, Tom wrote:

Hi, how can I create an empty element with current D2 std.xml Element
implementation?

stdout.writeln(new Element("foo")); // Shields  instead of


Thanks in advance,
Tom;


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



I see :(
Thanks...


Lucky me, 2.052 solves this bug and doesn't break anything.

Tom;


Really? Which changeset?

--
/Jacob Carlborg


Re: How do you test pre-/post-conditions and invariants?

2011-02-25 Thread spir

On 02/25/2011 11:20 PM, Magnus Lie Hetland wrote:

On 2011-02-25 17:48:54 +0100, spir said:


On 02/25/2011 04:30 PM, Magnus Lie Hetland wrote:

Or, more generally, how do you test asserts (which is what I'm using in my
preconditions etc.)?

As far as I can see, collectException() won't collect errors, which is what
assert() throws -- so what's the standard way of writing unit tests for
preconditions that use assert? (I.e., test that they will, in fact, throw when
you break them.)


See the page on DbC: http://www.digitalmars.com/d/2.0/dbc.html.

Denis


Hm. I'm not sure how this answers my question. I know how pre/postconditions
etc. work -- I was asking for how to test them in a unit test (i.e., ensure
that they'll kick in if you provide faulty intput, for example). Maybe I'm
missing something in the doc you referred me to?


No, sorry, /I/ read your post too superficially: Hadn't caught you wanted to 
"meta-check" the checks.


Denis
--
_
vita es estrany
spir.wikidot.com



Re: How do you test pre-/post-conditions and invariants?

2011-02-25 Thread spir

On 02/25/2011 11:33 PM, Magnus Lie Hetland wrote:

On 2011-02-25 20:04:10 +0100, Jonathan M Davis said:


On Friday, February 25, 2011 07:30:50 Magnus Lie Hetland wrote:

Or, more generally, how do you test asserts (which is what I'm using in
my preconditions etc.)?

As far as I can see, collectException() won't collect errors, which is
what assert() throws -- so what's the standard way of writing unit
tests for preconditions that use assert? (I.e., test that they will, in
fact, throw when you break them.)


I think that the reality of the matter is the most of the time people _don't_
check them. And on some level, it doesn't make sense to. It's kind of like
asking how people test their unit tests. Unit tests are already testing code. Do
you want to be testing them on top of that? And if you do, do you test _that_
code? Where do you stop?


I guess so. But you could say the same thing about other cases where you throw
an exception when you detect that something is wrong -- but those are normally
tested, right? Also, the difference here is that the precondition is written as
a general "test", whereas my actual test would have specific cases.

For example, I have a test that checks that I don't add the same object twice
to some structure, and the check involves some traversal -- code that could
potentially be wrong. I wanted to make sure that it wasn't by explicitly adding
the same object twice -- code (i.e., my unit test) that most likely could not
be wrong.

But I do see your point.



Now that you speak of it, I do agree with you. Just like for code paths or 
specific inputs that should throw an exception. I systematically check these 
bits in unittests. It's very easy to have them right, if only by distraction 
because they are not the points on which with we put most attention, and there 
often is a test invertion somewhere (and we don't watch them run). And 
actually, I often find an error somewhere in there.
What I do is trigger them in unitests, check all works as expected (ie an error 
is raised, and the message is sensible), then comment out but /keep/ the 
testing code.

Dunno if this makes sense for DbC checkings.


Denis
--
_
vita es estrany
spir.wikidot.com



Re: How do you test pre-/post-conditions and invariants?

2011-02-25 Thread Jonathan M Davis
On Friday, February 25, 2011 14:33:20 Magnus Lie Hetland wrote:
> On 2011-02-25 20:04:10 +0100, Jonathan M Davis said:
> > On Friday, February 25, 2011 07:30:50 Magnus Lie Hetland wrote:
> >> Or, more generally, how do you test asserts (which is what I'm using in
> >> my preconditions etc.)?
> >> 
> >> As far as I can see, collectException() won't collect errors, which is
> >> what assert() throws -- so what's the standard way of writing unit
> >> tests for preconditions that use assert? (I.e., test that they will, in
> >> fact, throw when you break them.)
> > 
> > I think that the reality of the matter is the most of the time people
> > _don't_ check them. And on some level, it doesn't make sense to. It's
> > kind of like asking how people test their unit tests. Unit tests are
> > already testing code. Do
> > you want to be testing them on top of that? And if you do, do you test
> > _that_ code? Where do you stop?
> 
> I guess so. But you could say the same thing about other cases where
> you throw an exception when you detect that something is wrong -- but
> those are normally tested, right? Also, the difference here is that the
> precondition is written as a general "test", whereas my actual test
> would have specific cases.
> 
> For example, I have a test that checks that I don't add the same object
> twice to some structure, and the check involves some traversal -- code
> that could potentially be wrong. I wanted to make sure that it wasn't
> by explicitly adding the same object twice -- code (i.e., my unit test)
> that most likely could not be wrong.
> 
> But I do see your point.
> 
> [snip]
> 
> > And testing post-conditions and invariants in the manner that you're
> > trying to do borders on impossible. What are you going to do, repeat the
> > post-condition or
> > invariant test on the result of the function or on the state of the
> > object that the function was called on after the function was called?
> > That's just doing the test twice.
> 
> Right.
> 
> > You might as well just re-read the post-conditions and invariants to
> > make sure that you wrote them correctly.
> > 
> > I do see value in testing pre-conditions if you're using exceptions
> > rather than assertions (which means that you're not use in blocks). In
> > that case, you're testing the API to make sure that it does what it's
> > supposed to do. But if you're dealing with assertions, then it's really
> > test code as opposed to API code, and I don't see the same value in
> > testing that. You'd just be testing test
> > code.
> 
> OK. For the practical reason, I refer you to my explanation above. But
> I guess it's a style issue -- and I'm fine with not testing these
> things, by all means.

When using assertions, you're checking the logic of your program and they 
should 
_always_ be true. When using exceptions, it's something that can conceivably 
fail at runtime. And if you view your function or class/struct as being part of 
an API, then you don't know who or what code will be using it, so it generally 
makes sense to use exceptions. If you use a pre-condition and assert that input 
is valid, then you're really testing the code that's calling your function, not 
the function itself. So, using such assertions makes good sense when you 
control 
both the caller and the callee and it's something that should never happen. 
However, if you don't necessarily control the caller or if it's something that 
_could_ happen at runtime (even if it shouldn't), then an exception makes a lot 
more sense.

I tend to view exceptions as part of the API and think that they should be 
tested. Assertions, on the other hand, aren't really part of the API, since 
they 
go away in release mode, and I therefore view them as test code. They're 
verifying that your logic is correct.

So, on some level, it is indeed a stylistic thing, but where you choose to use 
exceptions and where you choose to use assertions can have a big effect on code 
that uses your code.

> [snip]
> 
> > Those changes _do_ make it so that you can use collectException to
> > collect an Error (though it defaults to catching Exceptions only), but
> > they also
> > include assertThrown and assertNotThrown which effectively assert that
> > the Exception or Error that you expected to be thrown (or not) from a
> > particular expression or function call was indeed thrown (or not).
> > So, you _can_ use that with AssertError to verify your pre-conditions.
> 
> OK, thanks.
> 
> > However, I would point out that catching Errors is generally a _bad_
> > idea.
> 
> [snip lots of useful stuff]
> 
> Thanks for educating me :D
> 
> I guess the conclusion will be that I'll focus on keeping my
> preconditions really simple. (And any utility functions I use in them
> can then get unit tests of their own instead ;)

That's probably a good way to handle it. I find that I often tend to have 
helper 
functions like that simply because I end up testing the same thing in a variety 
of places, and I don't 

Interfacing with c and platform dependent sizes

2011-02-25 Thread simendsjo

C is not my strong side, so I'm having some problems wrapping some code.

I found a couple of sources on this:
1) http://www.digitalmars.com/d/2.0/htomodule.html
2) http://www.digitalmars.com/d/2.0/interfaceToC.html

1)
C's long is the same as D's int.
long long is long

2)
C 32bit's long long is D's long, C 64 bits long is D's long.

So.. A long in C is the same as the platform size? And long long doesn't 
exist in 64 bit?


Multiple assignment

2011-02-25 Thread bearophile
Is this program showing a bug in multiple assignments (DMD 2.052)?


void main() {
int i;
int[2] x;
i, x[i] = 1;
assert(x == [1, 0]); // OK

int j;
int[2] y;
y[j], j = 1;
assert(y == [0, 0]); // Not OK
}


At the end of the program I expect y to be [1,0] instead of [0,0].

Yet this C program with GCC:

#include "stdio.h"
int main() {
int i = 0;
int x[2] = {0, 0};
i, x[i] = 1;
printf("%d %d\n", x[0], x[1]);

int j = 0;
int y[2] = {0, 0};
y[j], j = 1;
printf("%d %d\n", y[0], y[1]);

return 0;
}


has the same output as DMD:
1 0
0 0

Bye,
bearophile


Re: Multiple assignment

2011-02-25 Thread simendsjo

On 26.02.2011 01:56, bearophile wrote:

Is this program showing a bug in multiple assignments (DMD 2.052)?


void main() {
 int i;
 int[2] x;
 i, x[i] = 1;
 assert(x == [1, 0]); // OK

 int j;
 int[2] y;
 y[j], j = 1;
 assert(y == [0, 0]); // Not OK
}


At the end of the program I expect y to be [1,0] instead of [0,0].

Yet this C program with GCC:

#include "stdio.h"
int main() {
 int i = 0;
 int x[2] = {0, 0};
 i, x[i] = 1;
 printf("%d %d\n", x[0], x[1]);

 int j = 0;
 int y[2] = {0, 0};
 y[j], j = 1;
 printf("%d %d\n", y[0], y[1]);

 return 0;
}


has the same output as DMD:
1 0
0 0

Bye,
bearophile


I couldn't find any info on the comma expression in the language 
reference, but this was my first google hit:

"""
A comma expression contains two operands of any type separated by a 
comma and has *left-to-right* associativity. The left operand is fully 
evaluated, possibly producing side effects, and its value, if there is 
one, is *discarded*. The right operand is then evaluated. The type and 
value of the result of a comma expression are those of its right 
operand, after the usual unary conversions

"""


Re: Interfacing with c and platform dependent sizes

2011-02-25 Thread bearophile
simendsjo:

> So.. A long in C is the same as the platform size? And long long doesn't 
> exist in 64 bit?

In D the size of int/uint is 32 bits and long/ulong is 64 bits.

In C the size of int, unsigned int, long, long long int, unsigned long long 
int, etc are not fixed, the change according to the CPU. sizeof(int) <= 
sizeof(long) <= sizeof(long long).

A help:
http://www.digitalmars.com/d/2.0/phobos/std_stdint.html

Bye,
bearophile


Re: Multiple assignment

2011-02-25 Thread Ali Çehreli

On 02/25/2011 04:56 PM, bearophile wrote:
> Is this program showing a bug in multiple assignments (DMD 2.052)?
>
>
> void main() {
>  int i;
>  int[2] x;
>  i, x[i] = 1;

I haven't heard about multiple assignments but that's the comma operator 
up there, separating (and sequencing) two expressions:


1) i
2) x[i] = 1

>  assert(x == [1, 0]); // OK
>
>  int j;
>  int[2] y;
>  y[j], j = 1;

Again, two expressions:

1) y[j]
2) j = 1

Only the second of both cases have an effect.

Ali

>  assert(y == [0, 0]); // Not OK
> }
>
>
> At the end of the program I expect y to be [1,0] instead of [0,0].
>
> Yet this C program with GCC:
>
> #include "stdio.h"
> int main() {
>  int i = 0;
>  int x[2] = {0, 0};
>  i, x[i] = 1;
>  printf("%d %d\n", x[0], x[1]);
>
>  int j = 0;
>  int y[2] = {0, 0};
>  y[j], j = 1;
>  printf("%d %d\n", y[0], y[1]);
>
>  return 0;
> }
>
>
> has the same output as DMD:
> 1 0
> 0 0
>
> Bye,
> bearophile



Re: Multiple assignment

2011-02-25 Thread bearophile
simendsjo:

> I couldn't find any info on the comma expression in the language 
> reference, but this was my first google hit:
> """
> A comma expression contains two operands of any type separated by a 
> comma and has *left-to-right* associativity. The left operand is fully 
> evaluated, possibly producing side effects, and its value, if there is 
> one, is *discarded*. The right operand is then evaluated. The type and 
> value of the result of a comma expression are those of its right 
> operand, after the usual unary conversions
> """

Right. But my code was wrong, I meant to write this:

void main() {
int i;
int[2] x;
i = x[i] = 1;
assert(x == [1, 0]); // OK

int j;
int[2] y;
y[j] = j = 1;
assert(y == [0, 1]); // Not OK
}

And I think it is working as you expect it to.

Thank you and sorry for the noise,
bearophile


Re: Interfacing with c and platform dependent sizes

2011-02-25 Thread simendsjo

On 26.02.2011 02:06, bearophile wrote:

simendsjo:


So.. A long in C is the same as the platform size? And long long doesn't
exist in 64 bit?


In D the size of int/uint is 32 bits and long/ulong is 64 bits.

In C the size of int, unsigned int, long, long long int, unsigned long long int, etc 
are not fixed, the change according to the CPU. sizeof(int)<= sizeof(long)<= 
sizeof(long long).

A help:
http://www.digitalmars.com/d/2.0/phobos/std_stdint.html

Bye,
bearophile


Ouch.. Any tips on porting C code that would work nicely with a 
transition to 64 bit?

Should I change all long and int to int_atleast_32_t and long long to 64?


Re: Interfacing with c and platform dependent sizes

2011-02-25 Thread Jonathan M Davis
On Friday, February 25, 2011 17:16:31 simendsjo wrote:
> On 26.02.2011 02:06, bearophile wrote:
> > simendsjo:
> >> So.. A long in C is the same as the platform size? And long long doesn't
> >> exist in 64 bit?
> > 
> > In D the size of int/uint is 32 bits and long/ulong is 64 bits.
> > 
> > In C the size of int, unsigned int, long, long long int, unsigned long
> > long int, etc are not fixed, the change according to the CPU.
> > sizeof(int)<= sizeof(long)<= sizeof(long long).
> > 
> > A help:
> > http://www.digitalmars.com/d/2.0/phobos/std_stdint.html
> > 
> > Bye,
> > bearophile
> 
> Ouch.. Any tips on porting C code that would work nicely with a
> transition to 64 bit?
> Should I change all long and int to int_atleast_32_t and long long to 64?

It depends entirely on what the code is doing. It could be completely safe to 
convert all ints, longs, and long longs to long to long. Or you may have to 
choose int or long depending on what system the code is supposed to be for.

In many cases, using a larger type wouldn't matter, since it can hold more than 
the smaller type, so whether the type in C/C++ was 32 bits or 64 bits is 
irrelevant. In other cases, the type needs to be an exact size, because the 
code 
is doing bit shifts or whatnot (in which case they _should_ have been using 
int32_t and int64_t on Linux and whatever the equivalent is on Windows, but 
unfortunately, many programmers don't). And if you're dealing with a struct, 
it's possible that that struct has to be an exact size (e.g. for some binary 
format), and using the wrong type in converting could make it the wrong size.

If you want to know what the appropriate D type is for the C/C++ code, you 
_need_ to know what it does.  Now, IIRC, int is almost guaranteed to be 32 bits 
at this point, and long long is essentially guaranteed to be 64 bits, but long 
varies from system to system - both in terms of OS and architecture. IIRC, long 
is 32 bits on Solaris and Windows - both on x86 and x86_64 - but it's 32 bits 
in 
x86 Linux and 64 bits in x86_64 Linux. So, if all the code uses is int and long 
long, then it's probably reasonably safe to use int for int and long for long 
long, but it's ultimately system dependent. Personally, I would argue that 
C/C++ 
code should use int when you don't care about the size of an integral type and 
use the intX_t types (where X is 8, 16, 32, or 64) when you _do_ care about the 
size, but there's no guarantee that programmers are going to be that 
disciplined 
about it.

In any case, if you really don't know the code and don't want to take the time 
to understand it, I'd use int for int, long for long long, and then if they 
have 
long, I'd do the research to figure out which OS and architecture the code is 
supposed to be for and use int if long long is 32 bits and long if it's 64 
bits. 
If you don't know what system it was built for, then I'd probably just use long 
and hoped that they weren't doing anything that made using an integral type 
which was too large a problem.

- Jonathan M Davis


Re: Multiple assignment

2011-02-25 Thread Ali Çehreli

On 02/25/2011 05:09 PM, bearophile wrote:

>  int j;
>  int[2] y;
>  y[j] = j = 1;

I think that's undefined behavior in C and C++. It is not defined 
whether j's previous or past value is used in y[j].


I would expect the situation be the same in D.

Ali



Re: Multiple assignment

2011-02-25 Thread Jonathan M Davis
On Friday, February 25, 2011 17:31:36 Ali Çehreli wrote:
> On 02/25/2011 05:09 PM, bearophile wrote:
>  >  int j;
>  >  int[2] y;
>  >  y[j] = j = 1;
> 
> I think that's undefined behavior in C and C++. It is not defined
> whether j's previous or past value is used in y[j].
> 
> I would expect the situation be the same in D.

No, that should be perfectly defined. What's undefined is when you do something 
like func(j, y[j]). The evaluation order of the function arguments is 
undefined. 
However,  the evaluation order when dealing with an assignment should be 
defined. 
I _could_ be wrong about that, but there's no question that the assignments 
themselves are guaranteed to be done in right-to-left order.

- Jonathan M Davis


Re: implicite deref on array element access? (indexing)

2011-02-25 Thread Jonathan M Davis
On Friday, February 25, 2011 07:15:52 spir wrote:
> Hello,
> 
> I thought it worked, just like implicite deref on (struct, class) member
> access. But I cannot have it work:
> 
>  auto a = [1,2,3];
>  auto pa = &a;
>  writeln((*pa)[2]);  // ok
>  writeln(pa[2]); // segfault
> 
> Denis

The _only_ time that dereferencing is done automatically in D is with the dot 
operator.

- Jonathan M Davis


Re: Interfacing with c and platform dependent sizes

2011-02-25 Thread Steven Schveighoffer
On Fri, 25 Feb 2011 20:06:04 -0500, bearophile   
wrote:



simendsjo:


So.. A long in C is the same as the platform size? And long long doesn't
exist in 64 bit?


In D the size of int/uint is 32 bits and long/ulong is 64 bits.

In C the size of int, unsigned int, long, long long int, unsigned long  
long int, etc are not fixed, the change according to the CPU.  
sizeof(int) <= sizeof(long) <= sizeof(long long).


It's *recommended* that ints be the size of a standard register.  So,  
those sizes do not have to follow the CPU architecture, and compilers  
could potentially use different sizes even on the same platform.


D (and most languages that came after C) did a much better job on this.

BTW, I think long long is a gnu extension, it's not standard C (I don't  
think long long exists in Visual C for instance).


-Steve


Re: Multiple assignment

2011-02-25 Thread Steven Schveighoffer
On Fri, 25 Feb 2011 21:10:59 -0500, Jonathan M Davis   
wrote:



On Friday, February 25, 2011 17:31:36 Ali Çehreli wrote:

On 02/25/2011 05:09 PM, bearophile wrote:
 >  int j;
 >  int[2] y;
 >  y[j] = j = 1;

I think that's undefined behavior in C and C++. It is not defined
whether j's previous or past value is used in y[j].

I would expect the situation be the same in D.


No, that should be perfectly defined. What's undefined is when you do  
something
like func(j, y[j]). The evaluation order of the function arguments is  
undefined.
However,  the evaluation order when dealing with an assignment should be  
defined.
I _could_ be wrong about that, but there's no question that the  
assignments

themselves are guaranteed to be done in right-to-left order.


Let me fix that for you:

func(j++, y[j])

-Steve


Re: Multiple assignment

2011-02-25 Thread Jonathan M Davis
On Friday, February 25, 2011 19:26:14 Steven Schveighoffer wrote:
> On Fri, 25 Feb 2011 21:10:59 -0500, Jonathan M Davis 
> 
> wrote:
> > On Friday, February 25, 2011 17:31:36 Ali Çehreli wrote:
> >> On 02/25/2011 05:09 PM, bearophile wrote:
> >>  >  int j;
> >>  >  int[2] y;
> >>  >  y[j] = j = 1;
> >> 
> >> I think that's undefined behavior in C and C++. It is not defined
> >> whether j's previous or past value is used in y[j].
> >> 
> >> I would expect the situation be the same in D.
> > 
> > No, that should be perfectly defined. What's undefined is when you do
> > something
> > like func(j, y[j]). The evaluation order of the function arguments is
> > undefined.
> > However,  the evaluation order when dealing with an assignment should be
> > defined.
> > I _could_ be wrong about that, but there's no question that the
> > assignments
> > themselves are guaranteed to be done in right-to-left order.
> 
> Let me fix that for you:
> 
> func(j++, y[j])

LOL. Yes. I forgot to alter j in the expression. Good catch.

- Jonathan M Davis


Re: Interfacing with c and platform dependent sizes

2011-02-25 Thread Jonathan M Davis
On Friday, February 25, 2011 17:35:02 Jonathan M Davis wrote:
> On Friday, February 25, 2011 17:16:31 simendsjo wrote:
> > On 26.02.2011 02:06, bearophile wrote:
> > > simendsjo:
> > >> So.. A long in C is the same as the platform size? And long long
> > >> doesn't exist in 64 bit?
> > > 
> > > In D the size of int/uint is 32 bits and long/ulong is 64 bits.
> > > 
> > > In C the size of int, unsigned int, long, long long int, unsigned long
> > > long int, etc are not fixed, the change according to the CPU.
> > > sizeof(int)<= sizeof(long)<= sizeof(long long).
> > > 
> > > A help:
> > > http://www.digitalmars.com/d/2.0/phobos/std_stdint.html
> > > 
> > > Bye,
> > > bearophile
> > 
> > Ouch.. Any tips on porting C code that would work nicely with a
> > transition to 64 bit?
> > Should I change all long and int to int_atleast_32_t and long long to 64?
> 
> It depends entirely on what the code is doing. It could be completely safe
> to convert all ints, longs, and long longs to long to long. Or you may
> have to choose int or long depending on what system the code is supposed
> to be for.
> 
> In many cases, using a larger type wouldn't matter, since it can hold more
> than the smaller type, so whether the type in C/C++ was 32 bits or 64 bits
> is irrelevant. In other cases, the type needs to be an exact size, because
> the code is doing bit shifts or whatnot (in which case they _should_ have
> been using int32_t and int64_t on Linux and whatever the equivalent is on
> Windows, but unfortunately, many programmers don't). And if you're dealing
> with a struct, it's possible that that struct has to be an exact size
> (e.g. for some binary format), and using the wrong type in converting
> could make it the wrong size.
> 
> If you want to know what the appropriate D type is for the C/C++ code, you
> _need_ to know what it does.  Now, IIRC, int is almost guaranteed to be 32
> bits at this point, and long long is essentially guaranteed to be 64 bits,
> but long varies from system to system - both in terms of OS and
> architecture. IIRC, long is 32 bits on Solaris and Windows - both on x86
> and x86_64 - but it's 32 bits in x86 Linux and 64 bits in x86_64 Linux.
> So, if all the code uses is int and long long, then it's probably
> reasonably safe to use int for int and long for long long, but it's
> ultimately system dependent. Personally, I would argue that C/C++ code
> should use int when you don't care about the size of an integral type and
> use the intX_t types (where X is 8, 16, 32, or 64) when you _do_ care
> about the size, but there's no guarantee that programmers are going to be
> that disciplined about it.
> 
> In any case, if you really don't know the code and don't want to take the
> time to understand it, I'd use int for int, long for long long, and then
> if they have long, I'd do the research to figure out which OS and
> architecture the code is supposed to be for and use int if long long is 32
> bits and long if it's 64 bits. If you don't know what system it was built
> for, then I'd probably just use long and hoped that they weren't doing
> anything that made using an integral type which was too large a problem.

Actually, I just realized that I was thinking in terms of porting C++ code to 
D. 
You're going to have to be more strict if you're just converting header files. 
However, what you can do is just compile something like this in C/C++ on your 
system:

printf("int -> %d bytes", sizeof(int));
printf("long -> %d bytes", sizeof(long));
printf("long long -> %d bytes", sizeof(long long));

Then you'll know what they are on your system, and you can convert them over 
just fine. You just have to remember to do the same on any other system that 
you 
compile your code on. Bleh. At least D went the route of standarizing the size 
of its primitive types.

- Jonathan M Davis


Re: std.xml empty element

2011-02-25 Thread Tom

El 25/02/2011 20:07, Jacob Carlborg escribió:

On 2011-02-25 21:11, Tom wrote:

El 24/02/2011 19:40, Tom escribió:

El 24/02/2011 09:51, Jacob Carlborg escribió:

On 2011-02-24 06:48, Tom wrote:

Hi, how can I create an empty element with current D2 std.xml Element
implementation?

stdout.writeln(new Element("foo")); // Shields  instead of


Thanks in advance,
Tom;


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



I see :(
Thanks...


Lucky me, 2.052 solves this bug and doesn't break anything.

Tom;


Really? Which changeset?



Not sure what you mean, but it seems it got fixed when 4069 was resolved...
http://d.puremagic.com/issues/show_bug.cgi?id=4069

Tom;


Re: Multiple assignment

2011-02-25 Thread Ali Çehreli

On 02/25/2011 06:10 PM, Jonathan M Davis wrote:

On Friday, February 25, 2011 17:31:36 Ali Çehreli wrote:

On 02/25/2011 05:09 PM, bearophile wrote:
  >   int j;
  >   int[2] y;
  >   y[j] = j = 1;

I think that's undefined behavior in C and C++. It is not defined
whether j's previous or past value is used in y[j].

I would expect the situation be the same in D.


No, that should be perfectly defined. What's undefined is when you do something
like func(j, y[j]). The evaluation order of the function arguments is undefined.
However,  the evaluation order when dealing with an assignment should be 
defined.
I _could_ be wrong about that, but there's no question that the assignments
themselves are guaranteed to be done in right-to-left order.

- Jonathan M Davis


Standard texts are very difficult to read. I found a 2005 draft of the 
C++ standard. 5 Expressions, paragraph 4:



Except where noted, the order of evaluation of operands of individual 
operators and subexpressions of individual expres-
sions, and the order in which side effects take place, is 
unspecified.58) Between the previous and next sequence point a
 scalar object shall have its stored value modified at most once by the 
evaluation of an expression. Furthermore, the prior
  value shall be accessed only to determine the value to be stored. The 
requirements of this paragraph shall be met for
 each allowable ordering of the subexpressions of a full expression; 
otherwise the behavior is undefined. [ Example:

i = v [ i ++]; / / the behavior is undefined
i = 7 , i ++ , i ++; / / i becomes 9
i = ++ i + 1; / / the behavior is undefined
i = i + 1; / / the value of i is incremented
— end example ]


To complete, footnote 58 is:


58)
The precedence of operators is not directly specified, but it can be 
derived from the syntax.



The section for the assignment operator does not mention anything to the 
contrary. According to my current understanding and my now-hazy 
recollections of old discussions on C++ news groups, in the following 
statement


  a() = b() = c();

the value of c() is assigned to b(), and the value of that expression is 
assigned to a(); but the order in which the three expressions are 
evaluated are unspecified.


Hence, if the code behaves contrary to 5.1 above, it has undefined behavior.

This was bearophile's statement:

  y[j] = j = 1;

The assignment operators do not introduce sequence points; there are 
only two: before and after the whole line above. The code does not obey 
"the prior value shall be accessed only to determine the value to be 
stored". Above, the prior value is used to determine which element of y 
is being assigned to.


Ali


Re: Multiple assignment

2011-02-25 Thread Jonathan M Davis
On Friday 25 February 2011 22:32:47 Ali Çehreli wrote:
> On 02/25/2011 06:10 PM, Jonathan M Davis wrote:
> > On Friday, February 25, 2011 17:31:36 Ali Çehreli wrote:
> >> On 02/25/2011 05:09 PM, bearophile wrote:
> >>   >   int j;
> >>   >   int[2] y;
> >>   >   y[j] = j = 1;
> >> 
> >> I think that's undefined behavior in C and C++. It is not defined
> >> whether j's previous or past value is used in y[j].
> >> 
> >> I would expect the situation be the same in D.
> > 
> > No, that should be perfectly defined. What's undefined is when you do
> > something like func(j, y[j]). The evaluation order of the function
> > arguments is undefined. However,  the evaluation order when dealing with
> > an assignment should be defined. I _could_ be wrong about that, but
> > there's no question that the assignments themselves are guaranteed to be
> > done in right-to-left order.
> > 
> > - Jonathan M Davis
> 
> Standard texts are very difficult to read. I found a 2005 draft of the
> C++ standard. 5 Expressions, paragraph 4:
> 
> 
> Except where noted, the order of evaluation of operands of individual
> operators and subexpressions of individual expres-
> sions, and the order in which side effects take place, is
> unspecified.58) Between the previous and next sequence point a
>   scalar object shall have its stored value modified at most once by the
> evaluation of an expression. Furthermore, the prior
>value shall be accessed only to determine the value to be stored. The
> requirements of this paragraph shall be met for
>   each allowable ordering of the subexpressions of a full expression;
> otherwise the behavior is undefined. [ Example:
> i = v [ i ++]; / / the behavior is undefined
> i = 7 , i ++ , i ++; / / i becomes 9
> i = ++ i + 1; / / the behavior is undefined
> i = i + 1; / / the value of i is incremented
> — end example ]
> 
> 
> To complete, footnote 58 is:
> 
> 
> 58)
> The precedence of operators is not directly specified, but it can be
> derived from the syntax.
> 
> 
> The section for the assignment operator does not mention anything to the
> contrary. According to my current understanding and my now-hazy
> recollections of old discussions on C++ news groups, in the following
> statement
> 
>a() = b() = c();
> 
> the value of c() is assigned to b(), and the value of that expression is
> assigned to a(); but the order in which the three expressions are
> evaluated are unspecified.
> 
> Hence, if the code behaves contrary to 5.1 above, it has undefined
> behavior.
> 
> This was bearophile's statement:
> 
>y[j] = j = 1;
> 
> The assignment operators do not introduce sequence points; there are
> only two: before and after the whole line above. The code does not obey
> "the prior value shall be accessed only to determine the value to be
> stored". Above, the prior value is used to determine which element of y
> is being assigned to.

Bleh. Well, good to know. Walter wants to make the order such evaluations 
ordered in D at some point though, so eventually it won't be a problem in D - 
though it'll obviously still be a problem in C++. Regardless, avoiding to alter 
a variable and use it multiple times within the same statement or expression is 
a good idea.

- Jonathan M davis