Re: ddoc file on command line

2010-08-10 Thread Yao G.
I forgot to mention that I'm using the latest (beta) version of DMD 2 on  
Windows XP.


On Tue, 10 Aug 2010 20:52:18 -0500, Yao G.  wrote:

According to the DDOC spec (http://digitalmars.com/d/2.0/ddoc.html) if  
you want to redefine some macros, one way is to pass one file with the  
.ddoc extension to the command line, but it doesn't work in my setup.  
For example, suppose I have the file yao.date.calendar, and I want to  
generate the documentation, so I compile with:


% dmd.exe calendar.d docbook.ddoc -Dfcalendar.xml

And it doesn't work. Am I doing something wrong? Note that the file is  
generated correctly but the few macros that I redefine (DDOC,  
DDOC_SUMMARY, etc.) don't get replaced with the new ones. The  
docbook.ddoc is on the same directory where I have the *.d files (code).


Thanks in advance.



--
Yao G.


ddoc file on command line

2010-08-10 Thread Yao G.
According to the DDOC spec (http://digitalmars.com/d/2.0/ddoc.html) if you  
want to redefine some macros, one way is to pass one file with the .ddoc  
extension to the command line, but it doesn't work in my setup. For  
example, suppose I have the file yao.date.calendar, and I want to generate  
the documentation, so I compile with:


% dmd.exe calendar.d docbook.ddoc -Dfcalendar.xml

And it doesn't work. Am I doing something wrong? Note that the file is  
generated correctly but the few macros that I redefine (DDOC,  
DDOC_SUMMARY, etc.) don't get replaced with the new ones. The docbook.ddoc  
is on the same directory where I have the *.d files (code).


Thanks in advance.

--
Yao G.


Re: Is there a queue class in phobos?

2010-08-10 Thread Trass3r

Wouldn't a regular array with a couple of free functions work?


You will get a lot of reallocations. For non-trivial applications you need  
some more sophisticated approach to alter the size of the array and maybe  
also deterministic memory management.


A queue is a commonly used technique so so it's justified to have it in  
the standard library, just like lists, heaps etc.


Re: Sharing unlocked, unchanging data between threads?

2010-08-10 Thread Jonathan M Davis
On Tuesday, August 10, 2010 11:54:06 Jacob Carlborg wrote:
> I though immutable was supposed to be implicitly shared with no need for
> locks or read-write barriers (or what they're called).

Ah. I have no clue that D1 does. I only use D2. There's obviously nothing wrong 
with posting D1 questions here, but most of the discussion and questions around 
here are for D2, so it's probably a good idea to indicate that you're using D1 
when asking a D1-related question.

- Jonathan M Davis


Re: Is there a queue class in phobos?

2010-08-10 Thread Jonathan M Davis
On Tuesday, August 10, 2010 12:06:55 Mafi wrote:
> Am 10.08.2010 18:22, schrieb Trass3r:
> > Container has List, BinaryHeap etc. but no Queue. Is there anything like
> > that in Phobos?
> 
> Hi,
> I don't know if ther is one but I think D's arrays are powerful enough
> unless you avoid the GC.
> 
> 1. a.front() => a[0]
> 2. a.popFront() => a = a[1..$]
> 3. a.pushBack(x) => a ~= x
> 
> I think in phobos there must be front and popFront for arrays to make
> them ranges but I don't know where.

If you want to treat an array like a range, use the functions in std.array. 
That's not a terribly cheap way to do things though since you keep resizing the 
array and will likely get a lot of reallocations. If efficiency isn't an issue, 
then it could be a nice, clean solution, but if efficiency is a priority, then 
that's probably not a good way to go.

- Jonathan M Davis


Re: dsss build, tango, GC ?

2010-08-10 Thread Fred Burton
Still having that apparent GC problem (with Tango on my machine), does anyone 
have (some GC test code) that they
can recommend that I run so that I can confirm that my GC is / is not working?


Re: Is there a queue class in phobos?

2010-08-10 Thread Mafi

Am 10.08.2010 18:22, schrieb Trass3r:

Container has List, BinaryHeap etc. but no Queue. Is there anything like
that in Phobos?

Hi,
I don't know if ther is one but I think D's arrays are powerful enough 
unless you avoid the GC.


1. a.front() => a[0]
2. a.popFront() => a = a[1..$]
3. a.pushBack(x) => a ~= x

I think in phobos there must be front and popFront for arrays to make 
them ranges but I don't know where.


Re: Sharing unlocked, unchanging data between threads?

2010-08-10 Thread Jacob Carlborg

On 2010-08-10 20:40, Jonathan M Davis wrote:

On Tuesday, August 10, 2010 10:45:03 Chris Williams wrote:

I'm writing a fairly large, multithreaded application and some part
of it is causing periodic access errors.

Say that I have an associative array like:

uint[ char[] ] nameToId;

If I set all values before I start my threads going and never change
anything after that point -- all access is read only -- is there any
way that having multiple threads access it at the same time would
mess anything up? I'm doing this in several places as locking a
read-only data structure doesn't strike me as something which should
be necessary. I don't know what D's associative arrays look like
internally though, so perhaps it is dangerous to do. It would be a
major hassle to port it all over to locking everything, to test if
it fixes the problem. So, hopefully someone can say whether this is
worth checking.


Well, unless it's declared shared, it's going to be thread-local, and then each
thread is going to have their own copy. Now, if it were declared shared and you
never changed it after initially setting all of its values, then you shouldn't
have any problems as far as I'm aware. Just accessing an associative array
shouldn't change it.

- Jonathan M Davis


I though immutable was supposed to be implicitly shared with no need for 
locks or read-write barriers (or what they're called).


--
/Jacob Carlborg


Re: Sharing unlocked, unchanging data between threads?

2010-08-10 Thread Chris Williams
== Quote from Jonathan M Davis (jmdavisp...@gmail.com)'s article
> Well, unless it's declared shared, it's going to be thread-local,
and then each
> thread is going to have their own copy. Now, if it were declared
shared and you
> never changed it after initially setting all of its values, then you
shouldn't
> have any problems as far as I'm aware. Just accessing an associative
array
> shouldn't change it.
> - Jonathan M Davis

I'm using D 1.0. I don't believe it has a "shared" keyword. But,
globals are shared as well, I presume.


Re: Is there a queue class in phobos?

2010-08-10 Thread Jacob Carlborg

On 2010-08-10 18:22, Trass3r wrote:

Container has List, BinaryHeap etc. but no Queue. Is there anything like
that in Phobos?


Wouldn't a regular array with a couple of free functions work?

--
/Jacob Carlborg


Re: Sharing unlocked, unchanging data between threads?

2010-08-10 Thread awishformore

On 10/08/2010 20:01, Steven Schveighoffer wrote:

On Tue, 10 Aug 2010 13:45:03 -0400, Chris Williams  wrote:


I'm writing a fairly large, multithreaded application and some part
of it is causing periodic access errors.

Say that I have an associative array like:

uint[ char[] ] nameToId;

If I set all values before I start my threads going and never change
anything after that point -- all access is read only -- is there any
way that having multiple threads access it at the same time would
mess anything up? I'm doing this in several places as locking a
read-only data structure doesn't strike me as something which should
be necessary. I don't know what D's associative arrays look like
internally though, so perhaps it is dangerous to do. It would be a
major hassle to port it all over to locking everything, to test if
it fixes the problem. So, hopefully someone can say whether this is
worth checking.


I don't see any reason why you'd need to lock it. It should not be
modified unless you change/insert a value or remove one.

It's likely something else causing the issue.

-Steve



That and: you should probably declare it as immutable.

/Max


Re: Sharing unlocked, unchanging data between threads?

2010-08-10 Thread Jonathan M Davis
On Tuesday, August 10, 2010 10:45:03 Chris Williams wrote:
> I'm writing a fairly large, multithreaded application and some part
> of it is causing periodic access errors.
> 
> Say that I have an associative array like:
> 
> uint[ char[] ] nameToId;
> 
> If I set all values before I start my threads going and never change
> anything after that point -- all access is read only -- is there any
> way that having multiple threads access it at the same time would
> mess anything up? I'm doing this in several places as locking a
> read-only data structure doesn't strike me as something which should
> be necessary. I don't know what D's associative arrays look like
> internally though, so perhaps it is dangerous to do. It would be a
> major hassle to port it all over to locking everything, to test if
> it fixes the problem. So, hopefully someone can say whether this is
> worth checking.

Well, unless it's declared shared, it's going to be thread-local, and then each 
thread is going to have their own copy. Now, if it were declared shared and you 
never changed it after initially setting all of its values, then you shouldn't 
have any problems as far as I'm aware. Just accessing an associative array 
shouldn't change it.

- Jonathan M Davis


Re: [OT] Is this more readable, or just way too verbose?

2010-08-10 Thread Lutger
simendsjo wrote:

> Lutger wrote:
...
>  I didn't increase the if nesting though.

I count 2 nested if-statements inside of the foreach loop in the original, you 
have 3 nested if-statements.
 
> Something like this then?

Looks good to me, yes. 


Re: Sharing unlocked, unchanging data between threads?

2010-08-10 Thread Steven Schveighoffer

On Tue, 10 Aug 2010 13:45:03 -0400, Chris Williams  wrote:


I'm writing a fairly large, multithreaded application and some part
of it is causing periodic access errors.

Say that I have an associative array like:

uint[ char[] ] nameToId;

If I set all values before I start my threads going and never change
anything after that point -- all access is read only -- is there any
way that having multiple threads access it at the same time would
mess anything up? I'm doing this in several places as locking a
read-only data structure doesn't strike me as something which should
be necessary. I don't know what D's associative arrays look like
internally though, so perhaps it is dangerous to do. It would be a
major hassle to port it all over to locking everything, to test if
it fixes the problem. So, hopefully someone can say whether this is
worth checking.


I don't see any reason why you'd need to lock it.  It should not be  
modified unless you change/insert a value or remove one.


It's likely something else causing the issue.

-Steve


Sharing unlocked, unchanging data between threads?

2010-08-10 Thread Chris Williams
I'm writing a fairly large, multithreaded application and some part
of it is causing periodic access errors.

Say that I have an associative array like:

uint[ char[] ] nameToId;

If I set all values before I start my threads going and never change
anything after that point -- all access is read only -- is there any
way that having multiple threads access it at the same time would
mess anything up? I'm doing this in several places as locking a
read-only data structure doesn't strike me as something which should
be necessary. I don't know what D's associative arrays look like
internally though, so perhaps it is dangerous to do. It would be a
major hassle to port it all over to locking everything, to test if
it fixes the problem. So, hopefully someone can say whether this is
worth checking.


Re: DirectX 11 bindings?

2010-08-10 Thread div0

On 09/08/2010 23:12, Trass3r wrote:

No one?


Eugh. Nope got OpenGL 3 bindings though.
--
My enormous talent is exceeded only by my outrageous laziness.
http://www.ssTk.co.uk


Re: What is the term for a function that can be CTFEed?

2010-08-10 Thread div0

On 10/08/2010 13:59, BCS wrote:

Hello Jonathan,


On Monday 09 August 2010 21:18:42 BCS wrote:


We have pure functions, member functions, static functions and global
functions; but what kind of function can always be used with CTFE?


Haven't we typical called them CTFE or CTFEable functions?


I've seen the first used, even used it my self (but it isn't even the
correct part of speech) and the second is kind of hard to say.



I call them F-able functions. Where F stands for Fantasic or F*ck 
depending on how complicated they are.


--
My enormous talent is exceeded only by my outrageous laziness.
http://www.ssTk.co.uk


Re: Is there a queue class in phobos?

2010-08-10 Thread Jonathan M Davis
On Tuesday, August 10, 2010 09:22:16 Trass3r wrote:
> Container has List, BinaryHeap etc. but no Queue. Is there anything like
> that in Phobos?

At the moment, I believe that what you see is what you get. std.container is 
quite young, and there are definitely going to be more containers in it, but 
for 
the moment, it's a bit sparse. It's a definite improvement over no containers, 
but it's new enough that it's still lacking in the number of containers that it 
has.

- Jonathan M Davis


std.getopt in 2.047

2010-08-10 Thread Stanislav Blinov

 Hello,

I've noticed that documentation does not reflect what std.getopt does 
concerning endOfOptions ("--").


Documentation:

Options Terminator

A lonesome double-dash terminates getopt gathering. It is used to 
separate program options from other parameters (e.g. options to be 
passed to another program). Invoking the example above with "--foo -- 
--bar" parses foo but leaves "--bar" in args. The double-dash itself is 
removed from the argument array.


---

But the double-dash is not removed. I've encountered this while testing 
a small program, but then looked at std.getopt.d, and indeed 
handleOption just breaks on endOfOptions without removing it. Is this a 
documentation error or Phobos bug?


--

**



Is there a queue class in phobos?

2010-08-10 Thread Trass3r
Container has List, BinaryHeap etc. but no Queue. Is there anything like  
that in Phobos?


Re: std.string.chomp error

2010-08-10 Thread Jonathan M Davis
On Tuesday 10 August 2010 02:34:33 Lars T. Kyllingstad wrote:
> I guess it depends on what behaviour you're after.  In the present case,
> if you want chomp(a, null) and chomp(a, "") to do the same thing, then
> you should use '=='.  If you want chomp(a, "") to simply do nothing, use
> 'is'.  I just figured that the former was the desired behaviour here.  If
> it isn't, I agree with you. :)

I was really talking about the general case rather than chomp() in specific, 
but's fine with me if "" and null are treated the same here, I suppose. Still,  
I 
really don't like it when null and empty is treated the same way (in D or 
anything else). There's a difference between something not existing and it 
existing but not having anything in it. But, as I said, we're stuck with the 
way 
it is in D.

- Jonathan M Davis


Re: Casting away const

2010-08-10 Thread Steven Schveighoffer
On Mon, 09 Aug 2010 19:35:38 -0400, Jonathan M Davis  
 wrote:



On Monday, August 09, 2010 15:01:28 Steven Schveighoffer wrote:

Then the author failed to make it const, and it's a bug in the function
definition.  "Casting away const if you don't write" is crap, and should
be treated as suspiciously as code that writes to const data.


I totally agree that the author of the code screwed up. However,  
sometimes you
have to deal with other people's screw ups. And unfortunately, in my  
experience,
a _lot_ of programmers don't bother to write const-correct code, and it  
causes

huge problems for those of us who do.


Yes, but by using such code and casting away const you are:

1) opening up your application to potential undefined behavior if the code  
you are using changes in a way that actually *does* write to the object
2) opening up your *own* code to potential undefined behavior in case you  
accidentally forget that you casted away const.


Casting away const is bad unless you control all the elements involved,  
and I think you need to limit it to small pieces of code where you  
scrutinize every aspect of it.


I think creating a Mutable wrapper for a type can potentially be an asset  
if it's done correctly.


What if calculating the hash is expensive, and you know you don't have  
to
recalculate it, you might cache it as a member of the class.  Believe  
me,
if a programmer can do it, he will.  Documentation saying "don't do  
this!"

isn't enough.


That's why mutable would be highly desirable, but we don't have it so  
tough luck
for us on that count, I suppose. As for documentation, if the function  
is const,
then no documentation is necessary. They just can't do it (not without  
casting

away constness and going into undefined territory anyway).


As long as its encapsulated, I think we are ok.  Note that there are other  
parts of the instance that are always mutable, such as the monitor object.



Personally, I'd say tough luck to the guy who wants to cache the hash by
calculating it in toHash(). He can call some other function to cache it,  
or he
could have a non-const version which caches it for cases where the  
object isn't
const, or he could calculate it when something in the class changes  
(which
naturally comes with its own set of pros and cons). From the perspective  
of

logical constness, there is no reason why toHash() can't be const.


I've proven that logical const is doable without breaking const in a post  
a couple years ago.  It's just lacking the language support.  I also made  
an extremely complex proposal to allow specification of various levels of  
const but that was rejected on account of being too complex :)


But looking at things like Rebindable, I think we should be able to make a  
logical const type that allows what we need in a controlled manner.


The one thing that stumps me is why associative arrays allow for const  
keys with
toHash() not being const. If I were to try and write a hashtable  
implementation
myself, I'd have to cast away the constness of the keys to be able to  
call

toHash() on them, which would be _really_ annoying. Maybe that's what
associative arrays are doing internally.


hehe, AA's are part of the runtime, so they manually must obey const  
rules.  Basically, they get a TypeInfo and a void * (which the compiler  
strips of any const or type) and have to do the right thing.  The  
TypeInfo's getHash() function takes a void *, so no const is obeyed,  
that's why it works.


Personally, I tend to be of the opinion that if a function can be const,  
it
should be const. There are always exceptions of course, but generally I  
think
that functions should be const when possible. It allows for writing  
const-
correct code much more easily (if not just outright makes it possible),  
and that
can reduce the number of mutation bugs that programmers have to deal  
with.


I agree.

-Steve


Re: Shifting values within an array

2010-08-10 Thread Steven Schveighoffer

On Tue, 10 Aug 2010 09:01:28 -0400, Chris Williams  wrote:


I would like to be able to do something like this:

class A {
int i;
}

int main() {
A[] list;

for (uint L = 0; L < 3; L++) {
for (uint L2 = 0; L2 < 3; L2++) {
uint index = L + L2;

uint copyAmount = list.length - index;
list.length = list.length + 1;
			if (copyAmount > 0) {  // Move data after index one slot later to  
make room

A[] sliceFrom = list[index .. (index + 
copyAmount)];
A[] sliceTo = list[(index + 1) .. (index + 1 + 
copyAmount)];
sliceTo[] = sliceFrom[];
}
list[index] = new A();
list[index].i = index;
}
}

return 0;
}

I have a running implementation which uses C's memmove(), but I gather  
that this isn't a safe means to do it as the garbage collector
might run while the references to the object are being manipulated. Is  
there a way to do this outside of a loop?


I think memmove should be fine.  All thread stacks are scanned during GC  
cycles, so there is no danger of having one element get collected.  I  
think memmove will not copy half a reference anyways.


-Steve


Shifting values within an array

2010-08-10 Thread Chris Williams
I would like to be able to do something like this:

class A {
int i;
}

int main() {
A[] list;

for (uint L = 0; L < 3; L++) {
for (uint L2 = 0; L2 < 3; L2++) {
uint index = L + L2;

uint copyAmount = list.length - index;
list.length = list.length + 1;
if (copyAmount > 0) {  // Move data after index one 
slot later to make room
A[] sliceFrom = list[index .. (index + 
copyAmount)];
A[] sliceTo = list[(index + 1) .. (index + 1 + 
copyAmount)];
sliceTo[] = sliceFrom[];
}
list[index] = new A();
list[index].i = index;
}
}

return 0;
}

I have a running implementation which uses C's memmove(), but I gather that 
this isn't a safe means to do it as the garbage collector
might run while the references to the object are being manipulated. Is there a 
way to do this outside of a loop?


Re: What is the term for a function that can be CTFEed?

2010-08-10 Thread BCS

Hello Jonathan,


On Monday 09 August 2010 21:18:42 BCS wrote:


We have pure functions, member functions, static functions and global
functions; but what kind of function can always be used with CTFE?


Haven't we typical called them CTFE or CTFEable functions?


I've seen the first used, even used it my self (but it isn't even the correct 
part of speech) and the second is kind of hard to say.


--
... <





Re: std.string.chomp error

2010-08-10 Thread bearophile
Lars T. Kyllingstad:
> I like how it is designed now, that was my point.

Sorry, I misread you.


Re: std.string.chomp error

2010-08-10 Thread Lars T. Kyllingstad
On Tue, 10 Aug 2010 07:50:34 -0400, bearophile wrote:

> Lars T. Kyllingstad:
>> There, I don't agree with you.  Arrays are a sort of pseudo-reference
>> type, so I don't mind 'null' being a sort of pseudo-null in that
>> context.  Actually, I find it to be quite elegant.  It's a matter of
>> taste, I guess.
> 
> I suggest you to write down the things you don't like and the design you
> desire here.

??

I like how it is designed now, that was my point.

-Lars


Re: std.string.chomp error

2010-08-10 Thread bearophile
Lars T. Kyllingstad:
> There, I don't agree with you.  Arrays are a sort of pseudo-reference 
> type, so I don't mind 'null' being a sort of pseudo-null in that 
> context.  Actually, I find it to be quite elegant.  It's a matter of 
> taste, I guess.

I suggest you to write down the things you don't like and the design you desire 
here.

Bye,
bearophile


Re: [OT] Is this more readable, or just way too verbose?

2010-08-10 Thread simendsjo

Lutger wrote:

simendsjo wrote:


(...)


The CR and LF constants are a bit too much, probably because they don't really 
abstract over the literals which I can actually parse faster. The isCR and isLF 
are nice however. Taking it a step further:


bool canSplit = inPattern(c,"\r\n");
if (canSplit)
{
  ...

You have increased the nesting of ifs to 3 inside a for-loop.Personally I don't 
read deep nesting very well. To go for readability I would use a small function 
for the entire expression: 


if( s[i..$].startsWithCRLF() ) // same as startsWithCRLF(s[i..$])
{
  i++;
  istart++;
}

or use std.algorithm: if ( s[i..$].startsWith("\r\n") )
 

(...)
Nice. I didn't increase the if nesting though.

Something like this then?

S[] mysplitlines(S)(S s)
{
size_t istart;

auto result = Appender!(S[])();

foreach (i; 0 .. s.length)
{
immutable c = s[i];
immutable isEOL = inPattern(c, "\r\n");
if (isEOL)
{
auto beforeEOL = s[istart .. i];
result.put(beforeEOL);

auto rest = s[i .. $];
immutable isCRLF = rest.startsWith("\r\n");

istart = i + 1; // consume first EOL character
if (isCRLF) // skip \n too
{
i++;
istart++;
}
}
}

// The last line might not end with EOL
immutable lineNotEmpty = (istart != s.length);
if (lineNotEmpty)
{
auto lastLine = s[istart .. $];
result.put(lastLine);
}

return result.data;
}


Re: [OT] What is more readable?

2010-08-10 Thread bearophile
simendsjo:
> And on the other hand; I doubt anything of what I write will ever get 
> into phobos!

If you exercise writing D code for few months you will be able contribute to 
Phobos2.

Bye,
bearophile


Re: More constants in std.string?

2010-08-10 Thread bearophile
simendsjo:

> Why a runtime error when you can have a compile time error?

Because using the static type system has various kinds of costs that some 
people in some situations are not willing to pay.

Bye,
bearophile


Re: std.string.chomp error

2010-08-10 Thread Lars T. Kyllingstad
On Tue, 10 Aug 2010 01:48:17 -0700, Jonathan M Davis wrote:

> On Tuesday 10 August 2010 00:30:37 Lars T. Kyllingstad wrote:
>> No, using 'is' won't work.  Check this out:
>> 
>>   int[] a;
>>   assert (a == null);
>>   assert (a is null);
>> 
>>   a = new int[10];
>>   a.length = 0;
>>   assert (a == null);
>>   assert (a !is null);
>> 
>> The thing is, '==' tests whether two arrays are equal, that is, that
>> they are equally long and that their elements are equal.  Any empty
>> array is equal to null -- in fact, in this context 'null' is just a way
>> of denoting an empty array that doesn't point to any particular memory
>> block (i.e. hasn't been initialised yet).
>> 
>>   // This is what '==' does
>>   bool mimicEquals(int[] a, int[] b)
>>   {
>>   if (a.length != b.length) return false; foreach (i; 0 ..
>>   a.length) if (a[i] != b[i]) return false; return true;
>>   }
>> 
>> 'is', on the other hand, tests whether two arrays are identical, i.e.
>> that they have the same length and *refer to the same piece of memory*.
>> 
>>   // This is (sort of) what 'is' does
>>   bool mimicIs(int[] a, int[] b)
>>   {
>>  return (a.ptr == b.ptr  &&  a.length == b.length);
>>   }
>> 
>> -Lars
> 
> Actually, it looks to me that that's an argument for using is for
> checking for null rather than ==, since == isn't really going to tell
> you. The fact that == doesn't care about whether an array is null makes
> it not work for checking for whether an array is null.

I guess it depends on what behaviour you're after.  In the present case, 
if you want chomp(a, null) and chomp(a, "") to do the same thing, then 
you should use '=='.  If you want chomp(a, "") to simply do nothing, use 
'is'.  I just figured that the former was the desired behaviour here.  If 
it isn't, I agree with you. :)


> 1. As I understand it, using is instead of == is for all references, not
> just arrays and their bizarre pseudo-null state. Using is with a class
> will avoid calling opEquals() and does exactly what you want when
> checking whether a class reference is null.

Fun fact: Actually, 'is' works for any type.

  assert (1 is 1);

As I've understood it, 'a is b' is true if the variables a and b contain 
the exact same bits.  If a and b are value types, this must mean they 
have the same value, and if they are references (including arrays), it 
means they refer to the same data.


> 2. For arrays, if you want to check whether it really is null, then you
> _must_ use is, because == obviously isn't going to tell you. It'll just
> lump empty arrays in with null ones. For instance, if you want to check
> that an array has never been initialized or that it has been set to null
> and never set to something else, then you need to use is.
> 
> 3. On the other hand, if what you really care about is checking whether
> an array has any elements and you don't care about whether it's null or
> not, then the empty function/property would be the better way to go.
> It's quite explicit, and it's more generic, doing things the way that
> ranges are done.

I totally agree with you.  Lately, I have started using "empty" (as well 
as the other range primitives) for arrays myself.  I just disagreed that 
'is' would produce what I perceived to be the right behaviour for the 
function in question.  But that perception may well be wrong. ;)


> Personally, I think that the way that null is handled with arrays and
> associative arrays is a poor design choice (if they're null, they should
> be null until you assign to them with new rather than this whole null
> but not null nonsense), but we're stuck with it I guess.

There, I don't agree with you.  Arrays are a sort of pseudo-reference 
type, so I don't mind 'null' being a sort of pseudo-null in that 
context.  Actually, I find it to be quite elegant.  It's a matter of 
taste, I guess.

-Lars


Re: std.string.chomp error

2010-08-10 Thread Jonathan M Davis
On Tuesday 10 August 2010 00:30:37 Lars T. Kyllingstad wrote:
> No, using 'is' won't work.  Check this out:
> 
>   int[] a;
>   assert (a == null);
>   assert (a is null);
> 
>   a = new int[10];
>   a.length = 0;
>   assert (a == null);
>   assert (a !is null);
> 
> The thing is, '==' tests whether two arrays are equal, that is, that they
> are equally long and that their elements are equal.  Any empty array is
> equal to null -- in fact, in this context 'null' is just a way of
> denoting an empty array that doesn't point to any particular memory block
> (i.e. hasn't been initialised yet).
> 
>   // This is what '==' does
>   bool mimicEquals(int[] a, int[] b)
>   {
>   if (a.length != b.length) return false;
>   foreach (i; 0 .. a.length) if (a[i] != b[i]) return false;
>   return true;
>   }
> 
> 'is', on the other hand, tests whether two arrays are identical, i.e.
> that they have the same length and *refer to the same piece of memory*.
> 
>   // This is (sort of) what 'is' does
>   bool mimicIs(int[] a, int[] b)
>   {
>  return (a.ptr == b.ptr  &&  a.length == b.length);
>   }
> 
> -Lars

Actually, it looks to me that that's an argument for using is for checking for 
null rather than ==, since == isn't really going to tell you. The fact that == 
doesn't care about whether an array is null makes it not work for checking for 
whether an array is null.

1. As I understand it, using is instead of == is for all references, not just 
arrays and their bizarre pseudo-null state. Using is with a class will avoid 
calling opEquals() and does exactly what you want when checking whether a class 
reference is null.

2. For arrays, if you want to check whether it really is null, then you _must_ 
use is, because == obviously isn't going to tell you. It'll just lump empty 
arrays in with null ones. For instance, if you want to check that an array has 
never been initialized or that it has been set to null and never set to 
something else, then you need to use is.

3. On the other hand, if what you really care about is checking whether an 
array 
has any elements and you don't care about whether it's null or not, then the 
empty function/property would be the better way to go. It's quite explicit, and 
it's more generic, doing things the way that ranges are done.

Personally, I think that the way that null is handled with arrays and 
associative arrays is a poor design choice (if they're null, they should be 
null 
until you assign to them with new rather than this whole null but not null 
nonsense), but we're stuck with it I guess.

- Jonathan M Davis


Re: std.string.chomp error

2010-08-10 Thread Lars T. Kyllingstad
On Mon, 09 Aug 2010 17:35:56 -0700, Jonathan M Davis wrote:

> On Monday, August 09, 2010 17:09:03 simendsjo wrote:
>> On 10.08.2010 02:09, Jonathan M Davis wrote:
>> > On Monday, August 09, 2010 16:59:07 bearophile wrote:
>> >> simendsjo:
>> >>> Ahem.. :) Yes, I did miss your answer! How I got fooled by the
>> >>> preview pane and never noticed the scrollbar.
>> >> 
>> >> No problem, it happens, don't worry.
>> >> 
>> >>> I cannot see how your other bug report relates to this though.
>> >> 
>> >> My other bug report is about this line in your code:
>> >>   if (delimiter == null)
>> >> 
>> >> I don't like it :-)
>> >> 
>> >> Bye,
>> >> bearophile
>> > 
>> > Why, because it should be
>> > 
>> > if(delimiter is null)
>> > 
>> > 
>> > or just
>> > 
>> > if(!delimiter)
>> > 
>> > 
>> > - Jonathan M Davis
>> 
>> Hehe.. You're a bit beyond my D level right now. At least I now know
>> null == false and you can do reference is null :)
> 
> IIRC, you're not really supposed to do "delim == null" but rather us
> "delim is null" or shorten to to just "!delim". Why, I don't recall off
> the top of my head, but it might be because "delim == null" would be
> calling Object.opEquals(), and there's no need for that function call
> (though fortunately "delim == null" translates to Object.opEquals(delim,
> null) rather than delim.opEquals(null) which avoids issues where the lhs
> is null and causes it to go boom).
> 
> In either case, for null checks, I'd suggest either just using the
> reference by itself or to explictly use "is null" if you want the extra
> clarity.

No, using 'is' won't work.  Check this out:

  int[] a;
  assert (a == null);
  assert (a is null);

  a = new int[10];
  a.length = 0;
  assert (a == null);
  assert (a !is null);

The thing is, '==' tests whether two arrays are equal, that is, that they 
are equally long and that their elements are equal.  Any empty array is 
equal to null -- in fact, in this context 'null' is just a way of 
denoting an empty array that doesn't point to any particular memory block 
(i.e. hasn't been initialised yet).

  // This is what '==' does
  bool mimicEquals(int[] a, int[] b)
  {
  if (a.length != b.length) return false;
  foreach (i; 0 .. a.length) if (a[i] != b[i]) return false;
  return true;
  }

'is', on the other hand, tests whether two arrays are identical, i.e. 
that they have the same length and *refer to the same piece of memory*.

  // This is (sort of) what 'is' does
  bool mimicIs(int[] a, int[] b)
  {
 return (a.ptr == b.ptr  &&  a.length == b.length);
  }

-Lars