Re: AA invalidating pointers and references..?

2010-08-09 Thread simendsjo

bearophile wrote:

simendsjo:

I haven't worked much with AA's, but I find the key in aa returns a 
reference to the value to be handy. I think it's better than the following:


int value;
if( 1 in a )
   value = a[1];

or a[1] in a try/catch or other implementations.


Your examples have shown me that probably the current design can't be made 
safe, and you can't use in SafeD code.
But performing x in AA is a very useful operation that I want to perform in 
SafeD code.

And in my opinion this code:

int value;
auto ptr = 1 in a;
if (ptr)
value = *ptr;


Doesn't look better than:

int value;
if (1 in a)
value = a[1];


2) I don't know what you mean. Does a single lookup often involve 
several under the hood?


If your compiler is naive then code like this:
if (1 in a)
value = a[1];
requires to perform two searches inside the hash, the first to tell if the key 
is present, and the second to find it again and fetch its value.

A bit better compiler (LDC is already able to do this) can recognize that you 
are performing two nearby key searches with the same key, and it can remove the 
second one, essentially replacing that code with this one:

int value;
auto ptr = 1 in a;
if (ptr)
value = *ptr;

Bye,
bearophile


You can always use:
auto value = 1 in a;
if (value) // needs != null? Haven't looked at this in the spec yet.
  //work with *value

But if the compiler can optimize the calls either way, and this is 
unsafe, a safer way sounds nice.


Re: Problem with std.array(std.regex.splitter())

2010-08-09 Thread Pelle

On 08/09/2010 12:50 AM, bearophile wrote:

This D2 code:

import std.regex: splitter, regex;
import std.array: array;
void main() {
 array(splitter(, abc, de, regex(, *)));
}


Gives the errors:

test.d(4): Error: template std.array.array(Range) if (isForwardRange!(Range)) 
does not match any function template declaration
test.d(4): Error: template std.array.array(Range) if (isForwardRange!(Range)) 
cannot deduce template function from argument types !()(Splitter!(string))

Do you know what's wrong in it?

Bye and thank you,
bearophile


std.array.array() erroneously requires a forward range, where it should 
require an input range.


Splitter also does not define save(), so it's not a forward range.


Re: d equivilent of java's public static class fields

2010-08-09 Thread Jacob Carlborg

On 2010-08-08 21:12, %u wrote:

I'm porting some code from Java to D and am getting stuck on what Java calls
static class fields.  I can't find out how to write the functional (or best
practices) equivalent in D.

(There are other syntax errors in D code, I'm fixing them one by one)

# Begin D code (ported from Java code below, and I probably should use
an Enum, but  haven't)
public class Answer
{
/* I've tried various combinations of syntax here */
   static int CORRECT = 0;
   public const int WRONG = 1;

   private int _answerCode;
   private string _answerText;

   /*
   */
   public this(int answerCode, string answerText)
   {
 _answerCode = answerCode;
 _answerText = answerText;
   }

   /*
   */
   public int getAnswerCode()
   {
 return _answerCode;
   }

   /*
   */
   public string getAnswerText()
   {
 return _answerText;
   }
}
### End D code code

### Begin Java code (included to show how it was done in java)
public class Answer
{
   public static final int CORRECT = 0;
   public static final int WRONG = 1;

   private int _answerCode;
   private String _answerText;

   /*
   */
   public Answer(int answerCode, String answerText)
   {
 _answerCode = answerCode;
 _answerText = answerText;
   }

   /*
   */
   public int getAnswerCode()
   {
 return _answerCode;
   }

   /*
   */
   public String getAnswerText()
   {
 return _answerText;
   }
}
## End Java code

# Begin D code snippet trying to use the Answer class
int asd = Answer.CORRECT;-- compile error here

try
{
   answer = problem.getAnswer(reply); // grade answer

   if (answer.getAnswerCode() == Answer.CORRECT)-- compile error here
 inOut.displayAnswer(Correct);
   else
 inOut.displayAnswer(Nope,  ~ answer.getAnswerText());
}
catch (Exception iae)
{
   inOut.displayAnswer(iae.getMessage());
   repeatQuestion = true; // show same question again
}
# End D code snippet


I don't know how you are trying to use your class but I don't see any 
errors in your code.


--
/Jacob Carlborg


Re: d equivilent of java's public static class fields

2010-08-09 Thread Jacob Carlborg

On 2010-08-08 21:28, Simen kjaeraas wrote:

%u throwa...@limewall.org wrote:


I'm porting some code from Java to D and am getting stuck on what Java
calls
static class fields. I can't find out how to write the functional (or
best
practices) equivalent in D.

[snip]

static int CORRECT = 0;

[snip]

int asd = Answer.CORRECT; -- compile error here

[snip]

if (answer.getAnswerCode() == Answer.CORRECT) -- compile error here


The default access level in D is private, so CORRECT will not be
available outside the module in which Answer is defined.


Since when is the default access level in D private?


As you mention, you should probably use an enum for wrong/correct.
However, due to lookup rules, an embedded enum would require users to
specify Answer.Correctness.CORRECT/WRONG, so separate enums for each
might be a better idea.

The most common way to expose the stored values in D code would probably
be as properties:

class Answer {
alias int Correctness;
enum Correctness CORRECT = 0;
enum Correctness WRONG = 1;

Correctness _answerCode;
string _answerText;

@property Correctness answerCode( ) const {
return _answerCode;
}

@property string answerText( ) const {
return _answerText;
}
}




--
/Jacob Carlborg


Re: Problem with std.array(std.regex.splitter())

2010-08-09 Thread Jonathan M Davis
On Monday 09 August 2010 01:13:30 Pelle wrote:
 std.array.array() erroneously requires a forward range, where it should
 require an input range.
 
 Splitter also does not define save(), so it's not a forward range.

Well, the requirement for save() being part of a forward range is fairly 
recent, 
and a bunch of ranges which are supposed to be forward ranges don't have them 
even though they're supposed to. The change was made fairly close to the 
release 
of 2.047, I believe, and it was missed for many ranges. It's mostly if not 
entirely fixed in svn. Actually, if I try and compile Bearophile's code on my 
machine (which has a fairly recent version of phobos), it compiles just fine. 
So, 
I don't know if array() should require an input range or a forward range, but 
the issue here has to do with recent changes to forward ranges which didn't 
make 
it into all forward ranges. It should be fixed with 2.048.

- Jonathan M Davis


Re: inheriting ctors?

2010-08-09 Thread Rory Mcguire
Philippe Sigaud wrote:

 On Fri, Aug 6, 2010 at 21:59, Rory Mcguire rjmcgu...@gm_no_ail.com
 wrote:
 

 Here is a possible solution to your problem:

 -Rory
 
 
 I believe you can get the type of A. Isn't it typeof(super) or
 std.traits.BaseClassesTuple!B[0] ? B in the latter case being typeof(this)
 That way, there is no need for the user to provide A, it's automatically
 found by the template.
 Warning: I did not test this.
 
 And, we know the constructs are of type 'A function(someTypes)'  [*], so
 the 'A function' part is redundant.
 Hence, the user only needs to provide for the args types and that makes
 for a cleaner call.
 
 * either as a list :
 mixin(InheritConstructors!(int, double, string)); // I want to inherit
 the constructors taking one type, build me the __ctors for int, double and
 string
 
 * or, in the case of multi-parameters constructors, wrap them in a tuple:
 mixin(InheritConstructors!(int, double, Tuple!(int, double)); // I
 want
 super(int), super(double) and super(int, double)
 
 That means iterating on the type list, and determining if the current type
 is a tuple or not
 * if its a 'normal' type, create the corresponding contructor
 * if it's a Tuple, crack it open and get the types, using the .Types alias
 std.typecons.Tuples have. Creating a constructor from this typetuple is no
 different from creating it for one type.
 
 To determine if something is a std.typecons.Tuple, you cannot use an is()
 expression: they do not allow multiple types:
 
 enum bool isTuple = is(T == Tuple!U, U...); // no. U... is not allowed.
 Hmm, enhancement request?
 
 So, you can either rely on it having a .Types 'member':
 
 template isTuple(T)
 {
   enum bool isTuple = is(T.Types);
 }
 
 Pb: that will flag as tuples any type that exposes a .Types alias.
 
 Or use a function accepting a Tuple:
 
 template isTuple(T)
 {
 enum bool isTuple = is(typeof({
void foo(U...)(Tuple!U t) {}; // this
 function accepts only tuples
foo(T.init); // test it
   }()));
 }
 
 It's ugly as a rat's ass, but it's more solid than the former template.
 
 
 Philippe
 
 [*] btw, shouldn't that be A delegate(someTypes)???

I'll see what I can do to shorten it but I'm not sure how to iterate over 
the Selectors inside the foreach and still be able to skip unselected 
constructors. Hmmm I suppose I could use a temporary boolean or something.


I don't use A delegate(someTuypes) because the compiler says that the type
of the constructors is for instance: A function(int x)




Re: inheriting ctors?

2010-08-09 Thread Rory Mcguire
I had been trying to use AutoImplement to make something before but it gave 
me weird errors.
I'm going to try using it for implementing this when I get some time.

Andrej Mitrovic wrote:

 Here's an example:
[snip]


Re: Problem with std.array(std.regex.splitter())

2010-08-09 Thread bearophile
Jonathan M Davis:
 Well, the requirement for save() being part of a forward range is fairly 
 recent, 
 and a bunch of ranges which are supposed to be forward ranges don't have them 
 even though they're supposed to. The change was made fairly close to the 
 release 
 of 2.047, I believe, and it was missed for many ranges. It's mostly if not 
 entirely fixed in svn. Actually, if I try and compile Bearophile's code on my 
 machine (which has a fairly recent version of phobos), it compiles just fine.

I have tried the latest beta and indeed it works, thank you.
Where can I find information about the purposes and meaning of save()? TDPL?

Bye,
bearophile


Re: Casting away const

2010-08-09 Thread Steven Schveighoffer
On Sun, 08 Aug 2010 17:56:25 -0400, simendsjo simen.end...@pandavre.com  
wrote:


I'm totally new to the const/immutable thing, so this might be a naive  
question..


The spec says:
modification after casting away const = undefined behavior


I thought it was you're on your own, not undefined behavior.  The former  
implies there is some right way to do this if you know more about the  
data than the compiler, the latter implies that there is no right way to  
cast away const.  Am I wrong?


-Steve


Re: Problem with std.array(std.regex.splitter())

2010-08-09 Thread Lars T. Kyllingstad
On Mon, 09 Aug 2010 07:31:21 -0400, bearophile wrote:

 Jonathan M Davis:
 Well, the requirement for save() being part of a forward range is
 fairly recent, and a bunch of ranges which are supposed to be forward
 ranges don't have them even though they're supposed to. The change was
 made fairly close to the release of 2.047, I believe, and it was missed
 for many ranges. It's mostly if not entirely fixed in svn. Actually, if
 I try and compile Bearophile's code on my machine (which has a fairly
 recent version of phobos), it compiles just fine.
 
 I have tried the latest beta and indeed it works, thank you. Where can I
 find information about the purposes and meaning of save()? TDPL?


It should be in the documentation of std.range.isForwardRange(), but 
Andrei seems to have forgotten it.  He did describe it in his 'On 
Iteration' article, though:

http://www.informit.com/articles/article.aspx?p=1407357

Check out page 7, section 'Forward Ranges'.  (I think the whole article 
is worth reading, if you haven't already -- it really helped me 
understand ranges.)

-Lars


Re: Casting away const

2010-08-09 Thread bearophile
Steven Schveighoffer:
 I thought it was you're on your own, not undefined behavior.  The former  
 implies there is some right way to do this if you know more about the  
 data than the compiler, the latter implies that there is no right way to  
 cast away const.  Am I wrong?

In my opinion if this thing is well designed then you go in undefined behaviour 
only when you change the contents of something after you have removed its const 
nature with a cast. Just casting const away and then reading the data can't be 
undefined behaviour, otherwise casting const away is useless and can be totally 
disallowed.

Bye,
bearophile


Re: Casting away const

2010-08-09 Thread Don

Steven Schveighoffer wrote:
On Sun, 08 Aug 2010 17:56:25 -0400, simendsjo 
simen.end...@pandavre.com wrote:


I'm totally new to the const/immutable thing, so this might be a naive 
question..


The spec says:
modification after casting away const = undefined behavior


I thought it was you're on your own, not undefined behavior.  The 
former implies there is some right way to do this if you know more 
about the data than the compiler, the latter implies that there is no 
right way to cast away const.  Am I wrong?


-Steve


I think you're wrong. It's OK to cast away const, as long as you don't 
modify the thing which is supposed to be const.
But if you modify it, there's no way the compiler can guarantee that 
your code will work. Anything could happen.


Re: Casting away const

2010-08-09 Thread Steven Schveighoffer
On Mon, 09 Aug 2010 09:57:47 -0400, bearophile bearophileh...@lycos.com  
wrote:



Steven Schveighoffer:
I thought it was you're on your own, not undefined behavior.  The  
former

implies there is some right way to do this if you know more about the
data than the compiler, the latter implies that there is no right way to
cast away const.  Am I wrong?


In my opinion if this thing is well designed then you go in undefined  
behaviour only when you change the contents of something after you have  
removed its const nature with a cast. Just casting const away and then  
reading the data can't be undefined behaviour, otherwise casting const  
away is useless and can be totally disallowed.


Casting away const just to read the data is useless.  You can read const  
data without a cast.


But my understanding is that casting away const to write should be doable  
if you know what you're doing.  If this is undefined behavior, then that's  
fine, I'm just unclear on what undefined behavior actually means.  I  
thought undefined behavior means that you cannot count on the behavior  
to work in the future.


An example of where casting away const to write should be allowed is for a  
hypothetical mutable member:


class C
{
   private Mutable!(int) cache = -1;
   int expensiveFunction() const { return cache == -1 ? cache =  
_expensiveFunctionImpl() : cache; }

   private int _expensiveFunctionImpl() const {...}
}

If this is undefined, then something like this cannot be relied on, even  
when performance is critical.


-Steve


Re: Casting away const

2010-08-09 Thread Steven Schveighoffer

On Mon, 09 Aug 2010 10:11:39 -0400, Don nos...@nospam.com wrote:


Steven Schveighoffer wrote:
On Sun, 08 Aug 2010 17:56:25 -0400, simendsjo  
simen.end...@pandavre.com wrote:


I'm totally new to the const/immutable thing, so this might be a naive  
question..


The spec says:
modification after casting away const = undefined behavior
 I thought it was you're on your own, not undefined behavior.  The  
former implies there is some right way to do this if you know more  
about the data than the compiler, the latter implies that there is no  
right way to cast away const.  Am I wrong?

 -Steve


I think you're wrong. It's OK to cast away const, as long as you don't  
modify the thing which is supposed to be const.
But if you modify it, there's no way the compiler can guarantee that  
your code will work. Anything could happen.


But then what is the point of casting away const?  If you are not going to  
modify it, then there is no reason to cast it away.


What about how Rebindable works?  It doesn't exactly cast away const, it  
uses a union, but the effect is the same.  Is this OK simply because a  
union is used?


Also, see my reply to bearophile, with hypothetical example.

-Steve


Re: Casting away const

2010-08-09 Thread Don

Steven Schveighoffer wrote:
On Mon, 09 Aug 2010 09:57:47 -0400, bearophile 
bearophileh...@lycos.com wrote:



Steven Schveighoffer:
I thought it was you're on your own, not undefined behavior.  The 
former

implies there is some right way to do this if you know more about the
data than the compiler, the latter implies that there is no right way to
cast away const.  Am I wrong?


In my opinion if this thing is well designed then you go in undefined 
behaviour only when you change the contents of something after you 
have removed its const nature with a cast. Just casting const away and 
then reading the data can't be undefined behaviour, otherwise casting 
const away is useless and can be totally disallowed.


Casting away const just to read the data is useless.  You can read const 
data without a cast.


No you can't. You can't pass it to a C function.



But my understanding is that casting away const to write should be 
doable if you know what you're doing.  If this is undefined behavior, 
then that's fine, I'm just unclear on what undefined behavior actually 
means.  I thought undefined behavior means that you cannot count on 
the behavior to work in the future.


An example of where casting away const to write should be allowed is for 
a hypothetical mutable member:


class C
{
   private Mutable!(int) cache = -1;
   int expensiveFunction() const { return cache == -1 ? cache = 
_expensiveFunctionImpl() : cache; }

   private int _expensiveFunctionImpl() const {...}
}

If this is undefined, then something like this cannot be relied on, even 
when performance is critical.


-Steve


I really can't see how the compiler could make that work, without 
destroying most of the benefits of const. For example, if that code is 
legal, it disallows most const-related optimisation.


Re: Casting away const

2010-08-09 Thread BCS

Hello Steven,


On Sun, 08 Aug 2010 17:56:25 -0400, simendsjo
simen.end...@pandavre.com  wrote:


I'm totally new to the const/immutable thing, so this might be a
naive  question..

The spec says:
modification after casting away const = undefined behavior

I thought it was you're on your own, not undefined behavior.  The
former  implies there is some right way to do this if you know more
about the  data than the compiler, the latter implies that there is no
right way to  cast away const.  Am I wrong?


I think you are right re the meaning of those terms but I think what you 
thought it to be is more along the lines of what is correct. I /think/ the 
situation is that there are things that will work reliably and things that 
result in undefined behavior and you're on your own figuring out what is 
what.



-Steve


--
... IXOYE





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

2010-08-09 Thread simendsjo

I took splitlines from std.string, which is a simple, short method.

S[] splitlines(S)(S s)
{
size_t istart;
auto result = Appender!(S[])();

foreach (i; 0 .. s.length)
{
immutable c = s[i];
if (c == '\r' || c == '\n')
{
result.put(s[istart .. i]);
istart = i + 1;
if (c == '\r'  i + 1  s.length  s[i + 1] == '\n')
{
i++;
istart++;
}
}
}
if (istart != s.length)
{
result.put(s[istart .. $]);
}

return result.data;
}


I guess it takes less than 30 seconds to fully understand this method. 
Then I rap.. I mean refactored it to this:


S[] mysplitlines(S)(S s)
{
const CR = '\r';
const LF = '\n';

size_t istart;

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

foreach (i; 0 .. s.length)
{
immutable c = s[i];

immutable isCR = (c == CR);
immutable isLF = (c == LF);

if (isCR || isLF)
{
auto line = s[istart .. i];
result.put(line);

istart = i + 1;

// Might be CRLF. In that case we need to consume LF too
if (isCR)
{
immutable hasMoreCharacters = (i + 1  s.length);
immutable nextIsLF = hasMoreCharacters  (s[i + 1] == LF);
immutable isCRLF = isCR  nextIsLF;

if (isCRLF)
{
i++;
istart++;
}
}
}
}

immutable lineNotEmpty = (istart != s.length);
if (lineNotEmpty)
{
auto lastLine = s[istart .. $];
result.put(lastLine);
}

return result.data;
}


Yes, I'm reading some books now and don't have much experience :)

It went from a small 26 line, very readable function to 48 lines (85% 
increase!) with many more temporary variables..


So... Do you think this kind of code is (more) readable, or just way too 
verbose and doing more harm than good?


And will the compiler generate slower code, or should the optimizer be 
able to inline the temporaries?


Re: Casting away const

2010-08-09 Thread BCS

Hello Steven,


On Mon, 09 Aug 2010 10:11:39 -0400, Don nos...@nospam.com wrote:


Steven Schveighoffer wrote:


On Sun, 08 Aug 2010 17:56:25 -0400, simendsjo
simen.end...@pandavre.com wrote:


I'm totally new to the const/immutable thing, so this might be a
naive  question..

The spec says:
modification after casting away const = undefined behavior

I thought it was you're on your own, not undefined behavior.  The
former implies there is some right way to do this if you know more
about the data than the compiler, the latter implies that there is
no
right way to cast away const.  Am I wrong?
-Steve

I think you're wrong. It's OK to cast away const, as long as you
don't
modify the thing which is supposed to be const.
But if you modify it, there's no way the compiler can guarantee that
your code will work. Anything could happen.


But then what is the point of casting away const?  If you are not
going to  modify it, then there is no reason to cast it away.


There are some cases where non-const pointers are used but never modified 
(C api's for instance) cast as always is just a way subvert the type system 
where it gets in your way.


--
... IXOYE





Re: Casting away const

2010-08-09 Thread Steven Schveighoffer

On Mon, 09 Aug 2010 10:27:09 -0400, Don nos...@nospam.com wrote:


Steven Schveighoffer wrote:
On Mon, 09 Aug 2010 09:57:47 -0400, bearophile  
bearophileh...@lycos.com wrote:



Steven Schveighoffer:
I thought it was you're on your own, not undefined behavior.  The  
former
implies there is some right way to do this if you know more about  
the
data than the compiler, the latter implies that there is no right way  
to

cast away const.  Am I wrong?


In my opinion if this thing is well designed then you go in undefined  
behaviour only when you change the contents of something after you  
have removed its const nature with a cast. Just casting const away and  
then reading the data can't be undefined behaviour, otherwise casting  
const away is useless and can be totally disallowed.
 Casting away const just to read the data is useless.  You can read  
const data without a cast.


No you can't. You can't pass it to a C function.


Sure you can.

extern(C) int strlen(const(char) *arg);



 But my understanding is that casting away const to write should be  
doable if you know what you're doing.  If this is undefined behavior,  
then that's fine, I'm just unclear on what undefined behavior  
actually means.  I thought undefined behavior means that you cannot  
count on the behavior to work in the future.
 An example of where casting away const to write should be allowed is  
for a hypothetical mutable member:

 class C
{
   private Mutable!(int) cache = -1;
   int expensiveFunction() const { return cache == -1 ? cache =  
_expensiveFunctionImpl() : cache; }

   private int _expensiveFunctionImpl() const {...}
}
 If this is undefined, then something like this cannot be relied on,  
even when performance is critical.

 -Steve


I really can't see how the compiler could make that work, without  
destroying most of the benefits of const. For example, if that code is  
legal, it disallows most const-related optimisation.


Why not?  What possible optimization can the compiler do here?  Mutable  
has an assign operation that is labeled as const, it should be callable by  
the compiler.


I haven't really seen what const optimizations can be, so maybe an example  
(even if unimplemented) is helpful.


-Steve


Re: Casting away const

2010-08-09 Thread Steven Schveighoffer

On Mon, 09 Aug 2010 10:37:14 -0400, BCS n...@anon.com wrote:


Hello Steven,


On Mon, 09 Aug 2010 10:11:39 -0400, Don nos...@nospam.com wrote:


Steven Schveighoffer wrote:


On Sun, 08 Aug 2010 17:56:25 -0400, simendsjo
simen.end...@pandavre.com wrote:


I'm totally new to the const/immutable thing, so this might be a
naive  question..
 The spec says:
modification after casting away const = undefined behavior

I thought it was you're on your own, not undefined behavior.  The
former implies there is some right way to do this if you know more
about the data than the compiler, the latter implies that there is
no
right way to cast away const.  Am I wrong?
-Steve

I think you're wrong. It's OK to cast away const, as long as you
don't
modify the thing which is supposed to be const.
But if you modify it, there's no way the compiler can guarantee that
your code will work. Anything could happen.


But then what is the point of casting away const?  If you are not
going to  modify it, then there is no reason to cast it away.


There are some cases where non-const pointers are used but never  
modified (C api's for instance) cast as always is just a way subvert the  
type system where it gets in your way.


C's api can be modified at declaration.  It has no mangling, so you can  
type it how it should be (if C had const).  For example:


extern(C) int strlen(const(char)* str);

I find that much more pleasant than having to cast away const.

-Steve


Re: Casting away const

2010-08-09 Thread Steven Schveighoffer

On Mon, 09 Aug 2010 10:24:56 -0400, BCS n...@anon.com wrote:


Hello Steven,


On Sun, 08 Aug 2010 17:56:25 -0400, simendsjo
simen.end...@pandavre.com  wrote:


I'm totally new to the const/immutable thing, so this might be a
naive  question..
 The spec says:
modification after casting away const = undefined behavior

I thought it was you're on your own, not undefined behavior.  The
former  implies there is some right way to do this if you know more
about the  data than the compiler, the latter implies that there is no
right way to  cast away const.  Am I wrong?


I think you are right re the meaning of those terms but I think what you  
thought it to be is more along the lines of what is correct. I /think/  
the situation is that there are things that will work reliably and  
things that result in undefined behavior and you're on your own figuring  
out what is what.


I'm sort of interpreting what you're saying is:

In some cases, you can cast away const and modify the variable with no  
adverse effects, but we can't tell you which cases those are.


Which is kind of like saying yes, casting away const is allowed, but only  
people who wrote the compiler can do it.


-Steve


Re: Casting away const

2010-08-09 Thread BCS

Hello Steven,


On Mon, 09 Aug 2010 09:57:47 -0400, bearophile
bearophileh...@lycos.com  wrote:


Steven Schveighoffer:


I thought it was you're on your own, not undefined behavior.  The
former
implies there is some right way to do this if you know more about
the
data than the compiler, the latter implies that there is no right
way to
cast away const.  Am I wrong?

In my opinion if this thing is well designed then you go in undefined
behaviour only when you change the contents of something after you
have  removed its const nature with a cast. Just casting const away
and then  reading the data can't be undefined behaviour, otherwise
casting const  away is useless and can be totally disallowed.


Casting away const just to read the data is useless.  You can read
const  data without a cast.

But my understanding is that casting away const to write should be
doable  if you know what you're doing.  If this is undefined behavior,
then that's  fine, I'm just unclear on what undefined behavior
actually means.  I  thought undefined behavior means that you cannot
count on the behavior  to work in the future.


Undefined behavior implies exactly that, once you enter the realm of undefined 
behavior, /anything/ that happens is your fault, the program can do anything 
at all and sill be considered a conforming program. It need not even behave 
the same between one run and the next.


The practical implications of this are that compilers are allowed to always 
assume the code never does anything that results in undefined behavior and 
generate code that is wrong in any number of ways if that assumption fails.


--
... IXOYE





Re: Casting away const

2010-08-09 Thread BCS

Hello Steven,


On Mon, 09 Aug 2010 10:37:14 -0400, BCS n...@anon.com wrote:


Hello Steven,


On Mon, 09 Aug 2010 10:11:39 -0400, Don nos...@nospam.com wrote:


Steven Schveighoffer wrote:


On Sun, 08 Aug 2010 17:56:25 -0400, simendsjo
simen.end...@pandavre.com wrote:

I'm totally new to the const/immutable thing, so this might be a
naive  question..
The spec says:
modification after casting away const = undefined behavior

I thought it was you're on your own, not undefined behavior.
The
former implies there is some right way to do this if you know
more
about the data than the compiler, the latter implies that there is
no
right way to cast away const.  Am I wrong?
-Steve

I think you're wrong. It's OK to cast away const, as long as you
don't
modify the thing which is supposed to be const.
But if you modify it, there's no way the compiler can guarantee
that
your code will work. Anything could happen.

But then what is the point of casting away const?  If you are not
going to  modify it, then there is no reason to cast it away.


There are some cases where non-const pointers are used but never
modified (C api's for instance) cast as always is just a way subvert
the  type system where it gets in your way.


C's api can be modified at declaration.  It has no mangling, so you
can  type it how it should be (if C had const).  For example:

extern(C) int strlen(const(char)* str);

I find that much more pleasant than having to cast away const.


OTOH that is effectively a hidden cast and has 100% of the same issues (re 
undefined behavior) as casting away const while being slightly harder to 
find.


--
... IXOYE





Re: Casting away const

2010-08-09 Thread BCS

Hello Steven,


On Mon, 09 Aug 2010 10:24:56 -0400, BCS n...@anon.com wrote:


Hello Steven,


On Sun, 08 Aug 2010 17:56:25 -0400, simendsjo
simen.end...@pandavre.com  wrote:

I'm totally new to the const/immutable thing, so this might be a
naive  question..
The spec says:
modification after casting away const = undefined behavior

I thought it was you're on your own, not undefined behavior.  The
former  implies there is some right way to do this if you know
more about the  data than the compiler, the latter implies that
there is no right way to  cast away const.  Am I wrong?


I think you are right re the meaning of those terms but I think what
you  thought it to be is more along the lines of what is correct. I
/think/  the situation is that there are things that will work
reliably and  things that result in undefined behavior and you're on
your own figuring  out what is what.


I'm sort of interpreting what you're saying is:

In some cases, you can cast away const and modify the variable with no
adverse effects, but we can't tell you which cases those are.


Yes and no. Yes, sometimes casting away const and then writing to the pointer 
doesn't crash your program (or do anything else) but no that's not what I 
was saying. It's still undefined behavior even if it works. What your 
on your own with is making sure you don't write to the pointer. Once you 
cast, the compiler won't check your work.




Which is kind of like saying yes, casting away const is allowed, but
only  people who wrote the compiler can do it.

-Steve


--
... IXOYE





Re: Casting away const

2010-08-09 Thread Steven Schveighoffer

On Mon, 09 Aug 2010 10:53:48 -0400, BCS n...@anon.com wrote:


Hello Steven,


On Mon, 09 Aug 2010 10:37:14 -0400, BCS n...@anon.com wrote:


Hello Steven,


On Mon, 09 Aug 2010 10:11:39 -0400, Don nos...@nospam.com wrote:


Steven Schveighoffer wrote:


On Sun, 08 Aug 2010 17:56:25 -0400, simendsjo
simen.end...@pandavre.com wrote:

I'm totally new to the const/immutable thing, so this might be a
naive  question..
The spec says:
modification after casting away const = undefined behavior

I thought it was you're on your own, not undefined behavior.
The
former implies there is some right way to do this if you know
more
about the data than the compiler, the latter implies that there is
no
right way to cast away const.  Am I wrong?
-Steve

I think you're wrong. It's OK to cast away const, as long as you
don't
modify the thing which is supposed to be const.
But if you modify it, there's no way the compiler can guarantee
that
your code will work. Anything could happen.

But then what is the point of casting away const?  If you are not
going to  modify it, then there is no reason to cast it away.


There are some cases where non-const pointers are used but never
modified (C api's for instance) cast as always is just a way subvert
the  type system where it gets in your way.


C's api can be modified at declaration.  It has no mangling, so you
can  type it how it should be (if C had const).  For example:
 extern(C) int strlen(const(char)* str);
 I find that much more pleasant than having to cast away const.


OTOH that is effectively a hidden cast and has 100% of the same issues  
(re undefined behavior) as casting away const while being slightly  
harder to find.


But you just said that casting and reading is not undefined?  Isn't this  
the same thing?


Const is such a strange beast because it plays no role in code generation,  
it's effectively only a tool to help the compiler decide what is  
possible.  It doesn't occupy any space or translate whatsoever to the  
underlying code.


I think there are definite good uses for writing to const or immutable  
data besides ones that can be stored in ROM.  That is, if you are sure a  
const or immutable piece of data is on the heap/stack, it should be  
reasonable to be able to modify it for performance gains.


-Steve


std.regex.match

2010-08-09 Thread bearophile
A question about std.regex.match() design. I am not sure, so I ask here first 
(if the ideas are sane I will write an enhancement request later).

This is the current syntax you have to use to iterated on the matches:
foreach (m; match(text, regex(r\d)).captures) {}


The regex() there is useful because you can add attributes like g as second 
argument, but often I don't need attributes. So is it possible to make match() 
accept a syntax like this too, that is more handy (the second argument of 
match() can be just a string, and there is no .captures):

foreach (m; match(text, r\d)) {}

Bye,
bearophile


Re: Casting away const

2010-08-09 Thread Steven Schveighoffer
On Mon, 09 Aug 2010 11:04:40 -0400, Steven Schveighoffer  
schvei...@yahoo.com wrote:



On Mon, 09 Aug 2010 10:53:48 -0400, BCS n...@anon.com wrote:

OTOH that is effectively a hidden cast and has 100% of the same issues  
(re undefined behavior) as casting away const while being slightly  
harder to find.


But you just said that casting and reading is not undefined?  Isn't this  
the same thing?


Const is such a strange beast because it plays no role in code  
generation, it's effectively only a tool to help the compiler decide  
what is possible.  It doesn't occupy any space or translate whatsoever  
to the underlying code.


I think there are definite good uses for writing to const or immutable  
data besides ones that can be stored in ROM.  That is, if you are sure a  
const or immutable piece of data is on the heap/stack, it should be  
reasonable to be able to modify it for performance gains.


I should say, when performance gains are not possible because of the  
limitations of the const/immutable notation.  The classic example is the  
mutable cache for avoiding recalculations on an immutable object.


-Steve


Re: Casting away const

2010-08-09 Thread bearophile
Steven Schveighoffer:
 extern(C) int strlen(const(char)* str);

C has no const(char)* so I am now thinking about a possible D2 diagnostic 
enhancement request that turns that line of code into a compile time error :-)

Bye,
bearophile


Re: Casting away const

2010-08-09 Thread Steven Schveighoffer
On Mon, 09 Aug 2010 11:15:38 -0400, bearophile bearophileh...@lycos.com  
wrote:



Steven Schveighoffer:

extern(C) int strlen(const(char)* str);


C has no const(char)* so I am now thinking about a possible D2  
diagnostic enhancement request that turns that line of code into a  
compile time error :-)


But an extern(C) function does not have to be written in C :)

-Steve


Re: What on earth is a ref function?

2010-08-09 Thread Simen kjaeraas

simendsjo simen.end...@pandavre.com wrote:


The spec is very short here, and the example doesn't give me much..

// I thought allows functinos to return by reference meant it could  
return local variables..

ref int* ptr() {
auto p = new int;
*p = 12;
return p; // Error: escaping local variable
}


This fails because p itself is stack allocated. By reference means it
returns a hidden pointer to something. Because this is a pointer, you
can get the address of the returned value, and do things to it.



// So whats the difference between these functions?

ref int val() {
auto p = new int;
assert(*p == 0);
*p = 10;
assert(*p == 10);
return *p;
}


This returns what is in effect p - a pointer (reference) to an int.



int val2() {
auto p = new int;
*p = 10;
return *p;
}


This returns simply the value of *p.


unittest
{
assert(val() == 10);
assert(val2() == 10);
auto retvalue = val() = 99; // References can be lvalues.. What?
assert(retvalue == 99);
}


Giving an example of what one can do with a reference:

ref int foo( ref int val ) {
return ++value;
}

int n = 3;
foo( n ) = 4;
assert( n == 4 );
assert( foo( n ) == 5 );

--
Simen


Re: Casting away const

2010-08-09 Thread bearophile
Steven Schveighoffer:
 But an extern(C) function does not have to be written in C :)

You are right. But that function written in an arbitrary language has to follow 
the C interface rules and limitations, and among those there is no way to 
define a variable to be const(char)*.

So in that line of code you are writing something that can't be enforced. 
Generally D design refuses features that the compiler is unable to verify. So I 
think an enhancement request to disallow that is good here. An extern(C) call 
has to specify only things that are understood by the C interface.

On the other hand in C you have const, but its semantics is different. Uhm...

Bye,
bearophile


Re: Casting away const

2010-08-09 Thread BCS

Hello Steven,


On Mon, 09 Aug 2010 10:53:48 -0400, BCS n...@anon.com wrote:


C's api can be modified at declaration.  It has no mangling, so you
can  type it how it should be (if C had const).  For example:
extern(C) int strlen(const(char)* str);
I find that much more pleasant than having to cast away const.

OTOH that is effectively a hidden cast and has 100% of the same
issues  (re undefined behavior) as casting away const while being
slightly  harder to find.


But you just said that casting and reading is not undefined?  Isn't
this  the same thing?


Casting away const or tacking const into a extern(C) prototype is safe under 
exactly the same conditions. The gains a savings of a few keystrokes and 
looses some degree of findability, aside from that, there is effectively 
no difference between them.



if you are sure
a  const or immutable piece of data is on the heap/stack, it should be
reasonable to be able to modify it for performance gains.


A conforming compiler can be implemented in such a way that you can never 
be sure of that without looking at the generated asm or even in such a way 
that it can't be know till runtime.


--
... IXOYE





Re: Casting away const

2010-08-09 Thread Simen kjaeraas

Steven Schveighoffer schvei...@yahoo.com wrote:


 class C
{
   private Mutable!(int) cache = -1;
   int expensiveFunction() const { return cache == -1 ? cache =  
_expensiveFunctionImpl() : cache; }

   private int _expensiveFunctionImpl() const {...}
}
 If this is undefined, then something like this cannot be relied on,  
even when performance is critical.

 -Steve


I really can't see how the compiler could make that work, without  
destroying most of the benefits of const. For example, if that code is  
legal, it disallows most const-related optimisation.


Why not?  What possible optimization can the compiler do here?  Mutable  
has an assign operation that is labeled as const, it should be callable  
by the compiler.


I haven't really seen what const optimizations can be, so maybe an  
example (even if unimplemented) is helpful.


The compiler may decide to store the value of cache in a register, and
use that value instead of fetching it after _expensiveFunctionImpl is
called. That's the simplest example I could come up with.

--
Simen


Re: d equivilent of java's public static class fields

2010-08-09 Thread Simen kjaeraas

Jacob Carlborg d...@me.com wrote:


Since when is the default access level in D private?


Uhm, since I made it up? Sorry about that, I believe I
mixed it up with C++.

--
Simen


Re: Casting away const

2010-08-09 Thread Steven Schveighoffer
On Mon, 09 Aug 2010 11:31:18 -0400, Simen kjaeraas  
simen.kja...@gmail.com wrote:



Steven Schveighoffer schvei...@yahoo.com wrote:


 class C
{
   private Mutable!(int) cache = -1;
   int expensiveFunction() const { return cache == -1 ? cache =  
_expensiveFunctionImpl() : cache; }

   private int _expensiveFunctionImpl() const {...}
}
 If this is undefined, then something like this cannot be relied on,  
even when performance is critical.

 -Steve


I really can't see how the compiler could make that work, without  
destroying most of the benefits of const. For example, if that code is  
legal, it disallows most const-related optimisation.


Why not?  What possible optimization can the compiler do here?  Mutable  
has an assign operation that is labeled as const, it should be callable  
by the compiler.


I haven't really seen what const optimizations can be, so maybe an  
example (even if unimplemented) is helpful.


The compiler may decide to store the value of cache in a register, and
use that value instead of fetching it after _expensiveFunctionImpl is
called. That's the simplest example I could come up with.



The compiler will rewrite the code as follows:

return cache.opEquals(-1) ? cache.opAssign(_expensiveFunctionImpl()) :  
cache.xxx;


I'm assuming for cache.xxx that it's some sort of alias this to a getter  
function.  All of these function would be const.


We can define the opAssign in such a way that it cannot be inlined,  
forcing the compiler to assume nothing about the result of opAssign.


Note also that the optimization you stated is not possible, even without  
casting away const, but would be possible on an immutable class.  But the  
fact that the compiler cannot peek into the implementation of the opAssign  
means it's forced to make no assumptions about the result of opAssign.


How does one write a conforming compiler that alters the result of this?

-Steve


Re: Casting away const

2010-08-09 Thread Mafi

Am 09.08.2010 17:31, schrieb bearophile:

Steven Schveighoffer:

But an extern(C) function does not have to be written in C :)


You are right. But that function written in an arbitrary language has to follow 
the C interface rules and limitations, and among those there is no way to 
define a variable to be const(char)*.

So in that line of code you are writing something that can't be enforced. 
Generally D design refuses features that the compiler is unable to verify. So I 
think an enhancement request to disallow that is good here. An extern(C) call 
has to specify only things that are understood by the C interface.

On the other hand in C you have const, but its semantics is different. Uhm...

Bye,
bearophile


I think, that isn't a good idea. I mean const-ness a compile time thing 
so the c abi has no problem with it. What's wrong when I define a

extern(c) bool thinkeAboutMyInt(const int* x) {
  
}
I want to inform the D typesystem that I'm not going to change the int 
but I need a pointer because the adress is important. I want this 
function to be also callable outside D (eg C).


Mafi


Re: Casting away const

2010-08-09 Thread Lars T. Kyllingstad
On Mon, 09 Aug 2010 10:35:02 -0400, Steven Schveighoffer wrote:

 On Mon, 09 Aug 2010 10:27:09 -0400, Don nos...@nospam.com wrote:
 
 Steven Schveighoffer wrote:
 On Mon, 09 Aug 2010 09:57:47 -0400, bearophile
 bearophileh...@lycos.com wrote:

 Steven Schveighoffer:
 I thought it was you're on your own, not undefined behavior.  The
 former
 implies there is some right way to do this if you know more about
 the
 data than the compiler, the latter implies that there is no right
 way to
 cast away const.  Am I wrong?

 In my opinion if this thing is well designed then you go in undefined
 behaviour only when you change the contents of something after you
 have removed its const nature with a cast. Just casting const away
 and then reading the data can't be undefined behaviour, otherwise
 casting const away is useless and can be totally disallowed.
  Casting away const just to read the data is useless.  You can read
 const data without a cast.

 No you can't. You can't pass it to a C function.
 
 Sure you can.
 
 extern(C) int strlen(const(char) *arg);
 
 
  But my understanding is that casting away const to write should be
 doable if you know what you're doing.  If this is undefined behavior,
 then that's fine, I'm just unclear on what undefined behavior
 actually means.  I thought undefined behavior means that you cannot
 count on the behavior to work in the future.
  An example of where casting away const to write should be allowed is
 for a hypothetical mutable member:
  class C
 {
private Mutable!(int) cache = -1;
int expensiveFunction() const { return cache == -1 ? cache =
 _expensiveFunctionImpl() : cache; }
private int _expensiveFunctionImpl() const {...}
 }
  If this is undefined, then something like this cannot be relied on,
 even when performance is critical.
  -Steve

 I really can't see how the compiler could make that work, without
 destroying most of the benefits of const. For example, if that code is
 legal, it disallows most const-related optimisation.
 
 Why not?  What possible optimization can the compiler do here?  Mutable
 has an assign operation that is labeled as const, it should be callable
 by the compiler.
 
 I haven't really seen what const optimizations can be, so maybe an
 example (even if unimplemented) is helpful.

The compiler does an optimization on const/immutable struct members 
which I reported as a bug:

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

-Lars


std.string.chomp error

2010-08-09 Thread simendsjo

The documentation says
/***
 * Returns s[] sans trailing delimiter[], if any.
 * If delimiter[] is null, removes trailing CR, LF, or CRLF, if any.
 */

To adhere to the documentation, chomp must be changed from:

C[] chomp(C, C1)(C[] s, in C1[] delimiter)
{
if (endsWith(s, delimiter))
{
return s[0 .. $ - delimiter.length];
}
return s;
}

to:

C[] chomp(C, C1)(C[] s, in C1[] delimiter)
{
if (delimiter == null)
  return chomp(s);
else if (endsWith(s, delimiter))
  return s[0 .. $ - delimiter.length];
else
  return s;
}




Re: std.string.chomp error

2010-08-09 Thread Lars T. Kyllingstad
On Mon, 09 Aug 2010 18:58:36 +0200, simendsjo wrote:

 The documentation says
 /***
   * Returns s[] sans trailing delimiter[], if any. * If delimiter[] is
   null, removes trailing CR, LF, or CRLF, if any. */
 
 To adhere to the documentation, chomp must be changed from:
 
 C[] chomp(C, C1)(C[] s, in C1[] delimiter) {
  if (endsWith(s, delimiter))
  {
  return s[0 .. $ - delimiter.length];
  }
  return s;
 }
 
 to:
 
 C[] chomp(C, C1)(C[] s, in C1[] delimiter) {
  if (delimiter == null)
return chomp(s);
  else if (endsWith(s, delimiter))
return s[0 .. $ - delimiter.length];
  else
return s;
 }


Either that, or the documentation for it needs to be changed.  Anyway, it 
would be great if you'd report this.

http://d.puremagic.com/issues/

Thanks!

-Lars


Re: std.string.chomp error

2010-08-09 Thread bearophile
Lars T. Kyllingstad:
 Either that, or the documentation for it needs to be changed.  Anyway, it 
 would be great if you'd report this.

A really basic unit testing is able to catch an error like this. This means 
Phobos needs more unit tests.

Stuff that may be added to that unittest:

import std.stdio, std.string;
void main() {
assert(chomp(hello) == hello);
assert(chomp(hello\n) == hello);
assert(chomp(hello\r\n) == hello);
assert(chomp(hello, ) == hello);
assert(chomp(hello\n, ) == hello);
assert(chomp(hello\r\n, ) == hello);
assert(chomp(hello\r\n, ) == hello);
assert(chomp(helloxxx, x) == helloxx);
}


But instead of:
if (delimiter == null)
Is better to write:
if (delimiter.length == 0)
Or:
if (delimiter == )

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

Bye,
bearophile


Re: Casting away const

2010-08-09 Thread bearophile
Mafi:
 I think, that isn't a good idea.

I agree, that idea doesn't work well.

Bye,
bearophile


Re: Casting away const

2010-08-09 Thread Lutger
bearophile wrote:

 Mafi:
 I think, that isn't a good idea.
 
 I agree, that idea doesn't work well.
 
 Bye,
 bearophile

I think it still is a good idea to forbid this in safe mode. Perhaps in trusted 
too.


Re: Casting away const

2010-08-09 Thread Steven Schveighoffer
On Mon, 09 Aug 2010 14:39:58 -0400, Lutger lutger.blijdest...@gmail.com  
wrote:



bearophile wrote:


Mafi:

I think, that isn't a good idea.


I agree, that idea doesn't work well.

Bye,
bearophile


I think it still is a good idea to forbid this in safe mode. Perhaps in  
trusted

too.


Note, this isn't any less safe than defining whatever you want for a C  
function:


extern(C) int strlen(int x);

C has no mangling, so there is no storage of parameter types in the  
symbol.  You can call any C function with whatever parameters you want to  
define for them.  Making some set of parameters illegal because in some  
cases it might not be true where you don't prevent it in others because  
you can't prove it, is just simply useless.


-Steve


Re: Casting away const

2010-08-09 Thread Lutger
Steven Schveighoffer wrote:

 On Mon, 09 Aug 2010 14:39:58 -0400, Lutger lutger.blijdest...@gmail.com
 wrote:
 
 bearophile wrote:

 Mafi:
 I think, that isn't a good idea.

 I agree, that idea doesn't work well.

 Bye,
 bearophile

 I think it still is a good idea to forbid this in safe mode. Perhaps in
 trusted
 too.
 
 Note, this isn't any less safe than defining whatever you want for a C
 function:
 
 extern(C) int strlen(int x);
 
 C has no mangling, so there is no storage of parameter types in the
 symbol.  You can call any C function with whatever parameters you want to
 define for them.  Making some set of parameters illegal because in some
 cases it might not be true where you don't prevent it in others because
 you can't prove it, is just simply useless.
 
 -Steve

Well you manually add typing, I think that is useful. But come to think of it, 
extern(C) functions should not be allowed in @safe code at all, only via 
@trusted and then the typing is useful. Perhaps this has been talked about, but 
I'm not sure how far @trusted can be allowed to go.



Re: Casting away const

2010-08-09 Thread Simen kjaeraas

Steven Schveighoffer schvei...@yahoo.com wrote:

Note also that the optimization you stated is not possible, even without  
casting away const, but would be possible on an immutable class.  But  
the fact that the compiler cannot peek into the implementation of the  
opAssign means it's forced to make no assumptions about the result of  
opAssign


You're right, I was thinking of immutable.

--
Simen


Re: Casting away const

2010-08-09 Thread Simen kjaeraas

Simen kjaeraas simen.kja...@gmail.com wrote:


Steven Schveighoffer schvei...@yahoo.com wrote:

Note also that the optimization you stated is not possible, even  
without casting away const, but would be possible on an immutable  
class.  But the fact that the compiler cannot peek into the  
implementation of the opAssign means it's forced to make no assumptions  
about the result of opAssign


You're right, I was thinking of immutable.


This said, one of the reasons casting away const is undefined, is because
the underlying type may be immutable.

--
Simen


Re: Casting away const

2010-08-09 Thread Steven Schveighoffer
On Mon, 09 Aug 2010 15:49:12 -0400, Simen kjaeraas  
simen.kja...@gmail.com wrote:



Simen kjaeraas simen.kja...@gmail.com wrote:


Steven Schveighoffer schvei...@yahoo.com wrote:

Note also that the optimization you stated is not possible, even  
without casting away const, but would be possible on an immutable  
class.  But the fact that the compiler cannot peek into the  
implementation of the opAssign means it's forced to make no  
assumptions about the result of opAssign


You're right, I was thinking of immutable.


This said, one of the reasons casting away const is undefined, is because
the underlying type may be immutable.


Right.  After reading all these replies, I think the way it looks to me is  
technically it's undefined to cast away const/immutable and write the  
data.  But, in certain circumstances, I think it will be possible to write  
portable code that works on all compilers that does this.


It's like a threading race condition.  If you simply allow unchecked  
access to a variable, it's undefined, you get races and can be using a  
partially written value, but slap a mutex around it, and the variable  
suddenly becomes well defined and behaves perfectly.  The compiler cannot  
guarantee this, nor detect it, but the programmer can determine based on  
analysis of all the code that it's safe.


-Steve


Re: Casting away const

2010-08-09 Thread Jonathan M Davis
On Monday, August 09, 2010 07:13:31 Steven Schveighoffer wrote:
 Casting away const just to read the data is useless.  You can read const
 data without a cast.

That's not actually quite true. If all code were const-correct, then it would 
be, but much of D is not. For instance, toHash() is not const even though it 
should be. The result is that if you need to call it with a const object, you 
have to cast away the constness. No writing is going on there (unless the 
writer 
of the toHash() function in the derived class(es) screwed it up), but you can't 
call it with a const object. I've run into plenty of similar situations in C++ 
where whoever wrote the code didn't choose to use const at all, and it made 
making that code deal with const a royal pain if not totally unreasonable. 
Casting away constness in cases where you knew that no write was going to take 
place or just dropping the constness in in your code were the only two options.

If anything, my reaction would have been that the programmer has no business 
writing to anything that they cast away the constness of. Dealing with code 
which _could_ and _should_ be const but isn't is the only place that I've ever 
even considered casting away const.

- Jonathan M Davis


Re: Problem with std.array(std.regex.splitter())

2010-08-09 Thread Jonathan M Davis
On Monday, August 09, 2010 04:31:21 bearophile wrote:
 Jonathan M Davis:
  Well, the requirement for save() being part of a forward range is fairly
  recent, and a bunch of ranges which are supposed to be forward ranges
  don't have them even though they're supposed to. The change was made
  fairly close to the release of 2.047, I believe, and it was missed for
  many ranges. It's mostly if not entirely fixed in svn. Actually, if I
  try and compile Bearophile's code on my machine (which has a fairly
  recent version of phobos), it compiles just fine.
 
 I have tried the latest beta and indeed it works, thank you.
 Where can I find information about the purposes and meaning of save()?
 TDPL?
 
 Bye,
 bearophile

save() gives you a generic way to get a copy of the range so that you can mess 
with the copy without altering the original. That way you don't have to worry 
about the different copy semantics for classes, structs, and arrays.

- Jonathan M Davis


Re: std.string.chomp error

2010-08-09 Thread simendsjo

On 09.08.2010 19:16, Lars T. Kyllingstad wrote:

On Mon, 09 Aug 2010 18:58:36 +0200, simendsjo wrote:


The documentation says
/***
   * Returns s[] sans trailing delimiter[], if any. * If delimiter[] is
   null, removes trailing CR, LF, or CRLF, if any. */

To adhere to the documentation, chomp must be changed from:

C[] chomp(C, C1)(C[] s, in C1[] delimiter) {
  if (endsWith(s, delimiter))
  {
  return s[0 .. $ - delimiter.length];
  }
  return s;
}

to:

C[] chomp(C, C1)(C[] s, in C1[] delimiter) {
  if (delimiter == null)
return chomp(s);
  else if (endsWith(s, delimiter))
return s[0 .. $ - delimiter.length];
  else
return s;
}



Either that, or the documentation for it needs to be changed.  Anyway, it
would be great if you'd report this.

http://d.puremagic.com/issues/

Thanks!

-Lars


Ok; http://d.puremagic.com/issues/show_bug.cgi?id=4608


Justify text

2010-08-09 Thread simendsjo
Phobos assumes that you only want to fill with spaces when justifying 
text. I merged the functions with a user supplied character. Don't think 
it should be much slower.. Just the switch extra switch if the function 
is inlined.. (but don't take my word for it :) )?


enum Alignment { Right, Left, Center }

string justify(string text, Alignment alignment, int width, char symbol)
{
if (text.length = width)
return text;

char[] result = new char[width];
switch(alignment)
{
case Alignment.Right:
result[0 .. width - text.length] = symbol;
result[width - text.length .. width] = text;
break;
case Alignment.Center:
int left = (width - text.length) / 2;
result[0 .. left] = symbol;
result[left .. left + text.length] = text;
result[left + text.length .. width] = symbol;
break;
case Alignment.Left:
result[0 .. text.length] = text;
result[text.length .. width] = symbol;
break;
default:
assert(false);
}

return assumeUnique(result);
}

string ljustify(string s, int width)
{
return justify(s, Alignment.Left, width, ' ');
}

string rjustify(string s, int width)
{
return justify(s, Alignment.Right, width, ' ');
}

string center(string s, int width)
{
return justify(s, Alignment.Center, width, ' ');
}


Re: Casting away const

2010-08-09 Thread Steven Schveighoffer
On Mon, 09 Aug 2010 17:15:41 -0400, Jonathan M Davis  
jmdavisp...@gmail.com wrote:



On Monday, August 09, 2010 07:13:31 Steven Schveighoffer wrote:

Casting away const just to read the data is useless.  You can read const
data without a cast.


That's not actually quite true. If all code were const-correct, then it  
would
be, but much of D is not. For instance, toHash() is not const even  
though it
should be. The result is that if you need to call it with a const  
object, you
have to cast away the constness. No writing is going on there (unless  
the writer
of the toHash() function in the derived class(es) screwed it up), but  
you can't

call it with a const object.


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.


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.



I've run into plenty of similar situations in C++
where whoever wrote the code didn't choose to use const at all, and it  
made
making that code deal with const a royal pain if not totally  
unreasonable.


Casting away const in C++ and writing to the data I think is not  
undefined.  I believe that's one of Walter's gripes with C++ const.


-Steve


Re: std.string.chomp error

2010-08-09 Thread simendsjo

On 09.08.2010 23:58, bearophile wrote:

simendsjo:

Ok; http://d.puremagic.com/issues/show_bug.cgi?id=4608


You seem to have missed my answer :-)

Bye,
bearophile


No, but I don't know if it's the documentation or implementation that's 
correct.


Re: Justify text

2010-08-09 Thread simendsjo

On 09.08.2010 23:59, simendsjo wrote:


 return justify(s, Alignment.Right, width, ' ');


Forgot zfill:

string zfill(string s, int width)
{
return justify(s, Alignment.Right, width, '0');
}


Re: DirectX 11 bindings?

2010-08-09 Thread Trass3r

No one?


Missing test in std.string.replace

2010-08-09 Thread simendsjo

Replacing with  / null is missing.
I first looked at the function and modified it. Quickly noticed that a 
few unit tests were missing:


assert(replace(foo, foo, ) == );
assert(replace(foo, foo, null) == );


Re: Missing test in std.string.replace

2010-08-09 Thread simendsjo

On 10.08.2010 00:29, simendsjo wrote:

Replacing with  / null is missing.
I first looked at the function and modified it. Quickly noticed that a
few unit tests were missing:

assert(replace(foo, foo, ) == );
assert(replace(foo, foo, null) == );


I refactored replace to understand what was going on (related to my post 
is this more readable).
I've seen a couple of functions using Appender, and it's documentation 
says it's faster than ~=. I tried to change char[] result to Appender, 
but dmd crashed...



string replace(string s, string from, string to)
{
if (from.length == 0) // Nothing to replace
return s;

char[] result;
for (size_t searchIndex; searchIndex  s.length; )
{
auto rest = s[searchIndex .. s.length];
auto fromIndex = indexOf(rest, from);

bool nothingToReplace = (fromIndex == -1);
if (nothingToReplace)
{
bool firstSearch = (searchIndex == 0);
if (firstSearch)
{
// Never found, so just return s
return s;
}

result ~= rest;
break;
}

auto beforeFrom = s[searchIndex .. searchIndex + fromIndex];
result ~= beforeFrom;
result ~= to;

searchIndex += fromIndex + from.length;
}

return assumeUnique(result);
}


Re: std.string.chomp error

2010-08-09 Thread simendsjo

On 09.08.2010 19:34, bearophile wrote:

Lars T. Kyllingstad:

Either that, or the documentation for it needs to be changed.  Anyway, it
would be great if you'd report this.


A really basic unit testing is able to catch an error like this. This means 
Phobos needs more unit tests.

Stuff that may be added to that unittest:

import std.stdio, std.string;
void main() {
 assert(chomp(hello) == hello);
 assert(chomp(hello\n) == hello);
 assert(chomp(hello\r\n) == hello);
 assert(chomp(hello, ) == hello);
 assert(chomp(hello\n, ) == hello);
 assert(chomp(hello\r\n, ) == hello);
 assert(chomp(hello\r\n, ) == hello);
 assert(chomp(helloxxx, x) == helloxx);
}


But instead of:
if (delimiter == null)
Is better to write:
if (delimiter.length == 0)
Or:
if (delimiter == )

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

Bye,
bearophile


Ahem.. :) Yes, I did miss your answer! How I got fooled by the preview 
pane and never noticed the scrollbar.
I cannot see how your other bug report relates to this though. For 
chomps part it's just an implementation vs. documentation issue.


Re: Casting away const

2010-08-09 Thread Jonathan M Davis
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.

 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).

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.

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.

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.

- Jonathan M Davis


Cannot use local xxx as parameter to non-global template.

2010-08-09 Thread simendsjo
I'm new, so this is most certainly my fault I guess, but I cannot 
understand the error message...

I wish to slice an array and store the slices in a tuple.

auto partitionArray(T)(T[] array, int offset, int len)
{
auto pre = array[0 .. offset];
auto slice = array[offset .. offset+len];
auto post = array[offset+len .. $];

return Tuple!(pre, slice, post);
}
unittest
{
auto val = partitionArray([1,2,3,4], 1, 2);
}

typecons.d(255): Error: template instance cannot use local 'post' as 
parameter to non-global template A(U...)


Re: std.string.chomp error

2010-08-09 Thread bearophile
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


Re: std.string.chomp error

2010-08-09 Thread Jonathan M Davis
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


Re: std.string.chomp error

2010-08-09 Thread simendsjo

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 :)


[OT] What is more readable?

2010-08-09 Thread simendsjo
Continuing my what is more readable thread (just shut me up, but I 
don't always agree with i, j, k etc...):


std.string.count:

size_t count(string s, string sub)
{
size_t i;
int j;
int count = 0;

for (i = 0; i  s.length; i += j + sub.length)
{
j = indexOf(s[i .. s.length], sub);
if (j == -1)
break;
count++;
}
return count;
}




size_t count(string s, string sub)
{
int result = 0;

int subStart = 0;
for (size_t restStart = 0; restStart  s.length; restStart += 
subStart + sub.length)

{
auto rest = s[restStart .. $];
subStart = indexOf(rest, sub);

bool notFound = (subStart == -1);
if (notFound)
break;

result++;
}

return result;
}


More constants in std.string?

2010-08-09 Thread simendsjo
\r and \n is used many times throughout std.string (and probably other 
modules like file).

I assume defining constants were considered:
const CR = '\r';
const LF = '\n';

So why isn't constants used instead?


Re: [OT] What is more readable?

2010-08-09 Thread Jonathan M Davis
On Monday, August 09, 2010 17:20:07 simendsjo wrote:
 Continuing my what is more readable thread (just shut me up, but I
 don't always agree with i, j, k etc...):

Personally, I think that i is just fine in many cases where it's quite clear 
what 
you're doing. e.g. the standard for loop:

for(size_t i = 0; i  a.length; ++i)
  //whatever we do with a[i]...

foreach does reduce how often that sort of thing is necessary though. However, 
once you get beyond i, and maybe j, it just gets confusing (not to mention the 
fact that i and j look a fair bit alike). So, personally, I avoid going beyond 
i, and I don't use i unless it's quite clear what I'm doing. Other than that, I 
find clearly named variables make the code much easier to read and understand - 
especially if someone else wrote the code, or you haven't read it in a while.

- Jonathan M Davis


Re: More constants in std.string?

2010-08-09 Thread Jonathan M Davis
On Monday, August 09, 2010 17:24:47 simendsjo wrote:
 \r and \n is used many times throughout std.string (and probably other
 modules like file).
 I assume defining constants were considered:
 const CR = '\r';
 const LF = '\n';
 
 So why isn't constants used instead?

Well, what would that really save or help? They're totally unambiguous and 
easily typed with the keyboard. Not to mention, if you were going to do that, 
you'd probably define them like so

enum CR = \r;
enum LF = \n;

Using enum for manifest constants is the more typical way to do it in D (it 
also 
forces compile-time evaluation of their value), and we want to avoid using 
individual chars or wchars, so pretty much all string-related functions take 
strings even if you'd think that they'd take a character of some kind (though 
if 
they were to take a character type, it would have to be dchar).

In any case, the values for these constants never change regardless of the 
machine - unlike something like path.sep which indicates the path separator for 
the machine and changes depending on which machine you compile on. For it to be 
worth making \r and \n constants, you have to gain something from it, and I 
don't think that there's much to be gained. Not to mention, you can always make 
more constants, and you have to stop somewhere, so you're always going to find 
something that _could_ be a constant and isn't.

- Jonathan M Davis


std.string.translate using initializing twice?

2010-08-09 Thread simendsjo

translate does this:
bool[256] deltab; // this would make all values of deltab false as 
bool.init == false, right?


deltab[] = false;

Isn't this just initializing all values of deltab to false twice..?

And my Is this more readable?

Original:

string translate(string s, in string transtab, in string delchars)
in
{
assert(transtab.length == 256);
}
body
{
char[] r;
int count;
bool[256] deltab;

deltab[] = false;
foreach (char c; delchars)
{
deltab[c] = true;
}

count = 0;
foreach (char c; s)
{
if (!deltab[c])
count++;
//printf(s[%d] = '%c', count = %d\n, i, s[i], count);
}

r = new char[count];
count = 0;
foreach (char c; s)
{
if (!deltab[c])
{
r[count] = transtab[c];
count++;
}
}

return assumeUnique(r);
}



More readable?:


string translate(string s, in string transtab, in string delchars)
in
{
assert(transtab.length == 256);
}
body
{
// Mark characters to delete
bool[256] deltab;
foreach (char c; delchars)
deltab[c] = true;

// Count characters to translate
int numToTranslate;
foreach (char c; s)
{
if (!deltab[c])
numToTranslate++;
}

char[] result = new char[numToTranslate];

// Translate
int translateIndex = 0;
foreach (char c; s)
{
bool mustTranslate = !deltab[c];
if (mustTranslate)
{
result[translateIndex] = transtab[c];
translateIndex++;
}
}

return assumeUnique(result);
}



Re: [OT] What is more readable?

2010-08-09 Thread simendsjo

On 10.08.2010 02:40, Jonathan M Davis wrote:

On Monday, August 09, 2010 17:20:07 simendsjo wrote:

Continuing my what is more readable thread (just shut me up, but I
don't always agree with i, j, k etc...):


Personally, I think that i is just fine in many cases where it's quite clear 
what
you're doing. e.g. the standard for loop:

for(size_t i = 0; i  a.length; ++i)
   //whatever we do with a[i]...

foreach does reduce how often that sort of thing is necessary though. However,
once you get beyond i, and maybe j, it just gets confusing (not to mention the
fact that i and j look a fair bit alike). So, personally, I avoid going beyond
i, and I don't use i unless it's quite clear what I'm doing. Other than that, I
find clearly named variables make the code much easier to read and understand -
especially if someone else wrote the code, or you haven't read it in a while.

- Jonathan M Davis



I also use i in my for loops. Always!
But I still find it difficult to understand when there are more than one 
index in use.


The thing here is that I couldn't understand the function top to bottom..
j was used both by the incrementer in the for loop, in the indexOf and 
the if statement. I had to get to the indexOf before I could understand 
what j was.


Of course, I'm just pointing out very small areas of potential 
improvement as I've only covered 5% of the spec and 1% of the stdlib :)


Re: std.string.translate using initializing twice?

2010-08-09 Thread Jonathan M Davis
On Monday, August 09, 2010 17:45:07 simendsjo wrote:
 translate does this:
  bool[256] deltab; // this would make all values of deltab false as
 bool.init == false, right?
 
  deltab[] = false;
 
 Isn't this just initializing all values of deltab to false twice..?

I believe that you are correct and that the array is getting set twice.

  [snip]...

I confess that it's entirely irrational on my part given that D is smart enough 
that a post-increment where the temporary is not used should be just as 
efficient 
as a pre-increment (even in the face of operator overloading - unlike C++), but 
it always makes me cringe to see post-increments where a pre-increment would 
do...

- Jonathan M Davis


Re: More constants in std.string?

2010-08-09 Thread simendsjo

On 10.08.2010 02:46, Jonathan M Davis wrote:

On Monday, August 09, 2010 17:24:47 simendsjo wrote:

\r and \n is used many times throughout std.string (and probably other
modules like file).
I assume defining constants were considered:
const CR = '\r';
const LF = '\n';

So why isn't constants used instead?


Well, what would that really save or help? They're totally unambiguous and
easily typed with the keyboard. Not to mention, if you were going to do that,
you'd probably define them like so

enum CR = \r;
enum LF = \n;

Using enum for manifest constants is the more typical way to do it in D (it also
forces compile-time evaluation of their value), and we want to avoid using
individual chars or wchars, so pretty much all string-related functions take
strings even if you'd think that they'd take a character of some kind (though if
they were to take a character type, it would have to be dchar).

In any case, the values for these constants never change regardless of the
machine - unlike something like path.sep which indicates the path separator for
the machine and changes depending on which machine you compile on. For it to be
worth making \r and \n constants, you have to gain something from it, and I
don't think that there's much to be gained. Not to mention, you can always make
more constants, and you have to stop somewhere, so you're always going to find
something that _could_ be a constant and isn't.

- Jonathan M Davis


I agree. I really don't thing it makes a difference or not.. '\r' is 
always that symbol no matter if it's a iPhone, embedded device or 
supercomputer. It's more that it's more error prone to write it than CR 
(ooops! compiler error!). If I wrote '\e' in a large switch and haven't 
tested all code paths.. Yes, shame on me, but I really meant \r! A 
constant gives me an at once. D is all about removing common, stupid 
programmer errors like I do, right? :)


It's just nitpicking and not a big deal at all. I can only remember once 
I've been bitten by one of these (not in D), but I quickly found the source.


Re: std.string.chomp error

2010-08-09 Thread bearophile
Jonathan M Davis:
 Why, because it should be
 
 if(delimiter is null)
 
 
 or just
 
 if(!delimiter)

if (delimiter.length == 0)
Or 
if (!delimiter.length)

Bye,
bearophile


Re: std.string.chomp error

2010-08-09 Thread simendsjo

On 10.08.2010 03:08, bearophile wrote:

Jonathan M Davis:

Why, because it should be

if(delimiter is null)


or just

if(!delimiter)


if (delimiter.length == 0)
Or
if (!delimiter.length)

Bye,
bearophile


Isn't that very different things? You cannot use .length if delimiter is 
null.




Re: std.string.translate using initializing twice?

2010-08-09 Thread Jonathan M Davis
On Monday, August 09, 2010 18:03:48 simendsjo wrote:
 Yeah. Don't remember when, don't remember where, but I too have read
 that preincrement is faster (PS: I don't know any assembler!).
 
 As long as I don't use it in an expression, I always use post-increment
 as it shouldn't make a difference.

post-increment creates a temporary. It's really doing something like

T temp = i;
++i;
//use temp in the expression with i++

The temporary is useless and pointless if i++ is by itself rather than in an 
expression. In the case of primitives, the compiler knows enough to optimize 
out 
the temporary, but in the case of operator overloading in C++, because pre and 
post-increment are overloaded separately, it can't know for sure that it's safe 
to do the optimization, so it doesn't do it, and your code is less efficient. 
That's why code like

for(vectorint::iterator iter = vec.begin(),
   end  = vec.end();
  iter != end;
  iter++)
{
  ...
}

is so bad. You really need to use ++iter in that case. However, in D, this 
isn't 
a problem because pre-increment and post-increment are overloaded by one 
function and the compiler takes care of whether it should be pre or post when 
it's used. So, it should be able to do the optimization just fine. But I've 
programmed in C++ for so long (where it does matter), that I instinctively 
react 
negatively to post-increment where a pre-increment will do even in languages 
like Java (which doesn't have operator overloading) or D where it doesn't 
matter.

I'd argue, that everyone (at least everyone programming in C++) should just be 
in the habit of using pre-increment except the cases where a post-increment is 
necessary (then you never have to worry about whether it's less efficient to 
use 
post-increment in a particular case), but for whatever reason, new programmers 
are pretty much always taught post-increment first, and so that's what most 
programmers are used to using.

In reality, it's becoming less relevant as newer languages are designed in a 
manner than there is no difference in efficiency, but my natural reaction is 
still 
very much that post-increment by itself is evil.

- Jonathan M Davis


Re: std.string.chomp error

2010-08-09 Thread Jonathan M Davis
On Monday, August 09, 2010 18:12:11 simendsjo wrote:
 On 10.08.2010 03:08, bearophile wrote:
  Jonathan M Davis:
  Why, because it should be
  
  if(delimiter is null)
  
  
  or just
  
  if(!delimiter)
  
  if (delimiter.length == 0)
  Or
  if (!delimiter.length)
  
  Bye,
  bearophile
 
 Isn't that very different things? You cannot use .length if delimiter is
 null.

If that's what you're looking for, then the proper thing to do would be to 
import std.array and do this

if(delimiter.empty)

It wille handle both null and length == 0 cases. Not to mention, it's much more 
range-y that way.

- Jonathan M Davis


Re: More constants in std.string?

2010-08-09 Thread Jonathan M Davis
On Monday, August 09, 2010 18:21:21 simendsjo wrote:
 Yeah, I know. I'm really just pointing out very small things here as I
 try to learn the language and library. Still.. I do think that static
 checking is a very good way of eliminating many common bugs. This might
 have been a bad example. I've coded several non-trivial applications in
 scripting languages, and more often than not, I _know_ what kind of
 objects my functions accepts... Why a runtime error when you can have a
 compile time error?

Well, fortunately, D is statically-typed and generally designed to catch bugs 
at 
compile time rather than runtime. It doesn't always succeed (dmd omniscient 
after all), but a lot more errors are going to be found at compile time than 
runtime than you'd get with many other languages - especially scripting 
languages which tend to be dynamically typed.

- Jonathan M Davis


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

2010-08-09 Thread Lutger
simendsjo wrote:

 I took splitlines from std.string, which is a simple, short method.
 
 S[] splitlines(S)(S s)
 {
  size_t istart;
  auto result = Appender!(S[])();
 
  foreach (i; 0 .. s.length)
  {
  immutable c = s[i];
  if (c == '\r' || c == '\n')
  {
  result.put(s[istart .. i]);
  istart = i + 1;
  if (c == '\r'  i + 1  s.length  s[i + 1] == '\n')
  {
  i++;
  istart++;
  }
  }
  }
  if (istart != s.length)
  {
  result.put(s[istart .. $]);
  }
 
  return result.data;
 }
 
 
 I guess it takes less than 30 seconds to fully understand this method.
 Then I rap.. I mean refactored it to this:
 
 S[] mysplitlines(S)(S s)
 {
  const CR = '\r';
  const LF = '\n';
 
  size_t istart;
 
  auto result = Appender!(S[])();
 
  foreach (i; 0 .. s.length)
  {
  immutable c = s[i];
 
  immutable isCR = (c == CR);
  immutable isLF = (c == LF);
 
  if (isCR || isLF)
  {
  auto line = s[istart .. i];
  result.put(line);
 
  istart = i + 1;
 
  // Might be CRLF. In that case we need to consume LF too
  if (isCR)
  {
  immutable hasMoreCharacters = (i + 1  s.length);
  immutable nextIsLF = hasMoreCharacters  (s[i + 1] == LF);
  immutable isCRLF = isCR  nextIsLF;
 
  if (isCRLF)
  {
  i++;
  istart++;
  }
  }
  }
  }
 
  immutable lineNotEmpty = (istart != s.length);
  if (lineNotEmpty)
  {
  auto lastLine = s[istart .. $];
  result.put(lastLine);
  }
 
  return result.data;
 }
 
 
 Yes, I'm reading some books now and don't have much experience :)
 
 It went from a small 26 line, very readable function to 48 lines (85%
 increase!) with many more temporary variables..
 
 So... Do you think this kind of code is (more) readable, or just way too
 verbose and doing more harm than good?

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) )
 
 And will the compiler generate slower code, or should the optimizer be
 able to inline the temporaries?

I don't think it matters much, but you can only tell by testing. There is a 
benchmark function (called benchmark iirc) somewhere in phobos to start with 
and 
dmd has a builtin profiler too.


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

2010-08-09 Thread BCS
We have pure functions, member functions, static functions and global functions; 
but what kind of function can always be used with CTFE?


--
... IXOYE





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

2010-08-09 Thread BCS

Hello BCS,


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



Compile Time Evaluable Function = CTEF? (sounds like CDEF; so testing many 
minor variant of one you get AB CTEF testing :b )


Or not.

--
... IXOYE





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

2010-08-09 Thread Jonathan M Davis
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?

- Jonathan M Davis