Discussion:
DMD 1.019 and 2.003 releases
(too old to reply)
Walter Bright
2007-07-22 23:26:28 UTC
Permalink
http://www.digitalmars.com/d/1.0/changelog.html
http://ftp.digitalmars.com/dmd.1.019.zip

http://www.digitalmars.com/d/changelog.html
http://ftp.digitalmars.com/dmd.2.003.zip
Robert Fraser
2007-07-22 23:52:03 UTC
Permalink
Beautiful! Just when I think D can't get better, it does! Thanks for all the hard work.

May I ask why you put the road there before traits? I know there's a std.traits, but perhaps a different keyword entirely or just a single underscore might be more appropriate...? It looks a bit like a compiler-specific extension to me...
Post by Walter Bright
http://www.digitalmars.com/d/1.0/changelog.html
http://ftp.digitalmars.com/dmd.1.019.zip
http://www.digitalmars.com/d/changelog.html
http://ftp.digitalmars.com/dmd.2.003.zip
Walter Bright
2007-07-23 03:39:35 UTC
Permalink
Post by Robert Fraser
May I ask why you put the road there before traits? I know there's a std.traits, but perhaps a different keyword entirely or just a single underscore might be more appropriate...? It looks a bit like a compiler-specific extension to me...
I was thinking they should be buried inside of templates.
Sean Kelly
2007-07-23 04:48:50 UTC
Permalink
Post by Walter Bright
Post by Robert Fraser
May I ask why you put the road there before traits? I know there's a
std.traits, but perhaps a different keyword entirely or just a single
underscore might be more appropriate...? It looks a bit like a
compiler-specific extension to me...
I was thinking they should be buried inside of templates.
But does that affect what the name should be?
Walter Bright
2007-07-23 07:18:31 UTC
Permalink
Post by Sean Kelly
Post by Walter Bright
Post by Robert Fraser
May I ask why you put the road there before traits? I know there's a
std.traits, but perhaps a different keyword entirely or just a single
underscore might be more appropriate...? It looks a bit like a
compiler-specific extension to me...
I was thinking they should be buried inside of templates.
But does that affect what the name should be?
Don't need a prominent keyword for it.
Sean Kelly
2007-07-23 07:30:43 UTC
Permalink
Post by Walter Bright
Post by Sean Kelly
Post by Walter Bright
Post by Robert Fraser
May I ask why you put the road there before traits? I know there's a
std.traits, but perhaps a different keyword entirely or just a
single underscore might be more appropriate...? It looks a bit like
a compiler-specific extension to me...
I was thinking they should be buried inside of templates.
But does that affect what the name should be?
Don't need a prominent keyword for it.
True enough. I suppose I'm just used to the double-underscore prefix
being reserved for compiler extensions.


Sean
Robert Fraser
2007-07-23 23:34:44 UTC
Permalink
Post by Walter Bright
Post by Sean Kelly
Post by Walter Bright
Post by Robert Fraser
May I ask why you put the road there before traits? I know there's a
std.traits, but perhaps a different keyword entirely or just a single
underscore might be more appropriate...? It looks a bit like a
compiler-specific extension to me...
I was thinking they should be buried inside of templates.
But does that affect what the name should be?
Don't need a prominent keyword for it.
Hmmmm.... it just seems to disturb the zen of D (having one keyword with two underscores), and I think it'll be used just as much as some other keywords, whether it's buried in templates or not.
Serg Kovrov
2007-07-24 17:15:03 UTC
Permalink
Post by Robert Fraser
Hmmmm.... it just seems to disturb the zen of D (having one keyword with two underscores), and I think it'll be used just as much as some other keywords, whether it's buried in templates or not.
I agree. keywords with underscores (no matter where and how many) are
just wrong.

--serg.
Kirk McDonald
2007-07-23 00:05:59 UTC
Permalink
Post by Walter Bright
http://www.digitalmars.com/d/1.0/changelog.html
http://ftp.digitalmars.com/dmd.1.019.zip
http://www.digitalmars.com/d/changelog.html
http://ftp.digitalmars.com/dmd.2.003.zip
In the spec for the new ForeachRangeStatement, it says:

"If Foreach is foreach, then the variable is set to LwrExpression, then
incremented at the end of each iteration."

What does "incremented" mean, exactly? If have a class or struct that
defines opAddAssign, would it call foo.opAddAssign(1) (as ++foo does)?
Similarly, would the foreach_reverse form call foo.opSubAssign(1)?
--
Kirk McDonald
http://kirkmcdonald.blogspot.com
Pyd: Connecting D and Python
http://pyd.dsource.org
Walter Bright
2007-07-23 03:40:28 UTC
Permalink
Post by Kirk McDonald
"If Foreach is foreach, then the variable is set to LwrExpression, then
incremented at the end of each iteration."
What does "incremented" mean, exactly? If have a class or struct that
defines opAddAssign, would it call foo.opAddAssign(1) (as ++foo does)?
Similarly, would the foreach_reverse form call foo.opSubAssign(1)?
Right now, it doesn't work with structs/classes, but when it does, it'll
be as you wrote.
BCS
2007-07-23 17:00:47 UTC
Permalink
Reply to Walter,
Post by Walter Bright
Post by Kirk McDonald
"If Foreach is foreach, then the variable is set to LwrExpression,
then incremented at the end of each iteration."
What does "incremented" mean, exactly? If have a class or struct that
defines opAddAssign, would it call foo.opAddAssign(1) (as ++foo
does)? Similarly, would the foreach_reverse form call
foo.opSubAssign(1)?
Right now, it doesn't work with structs/classes, but when it does,
it'll be as you wrote.
what will this do

foreach(float f; 1 .. toBigFor1ToIncrement)

loop forever?
Walter Bright
2007-07-23 17:18:05 UTC
Permalink
Post by BCS
what will this do
foreach(float f; 1 .. toBigFor1ToIncrement)
loop forever?
The same thing as:

for (float f = 1; f < toBigFor1ToIncrement; f++)

What foreach ranges buy you is:

1) The type of the loop index is automatically inferred
2) The termination condition is evaluated only once

While these may seem trivial, they are often a source of bugs.
Kirk McDonald
2007-07-23 00:13:49 UTC
Permalink
Post by Walter Bright
http://www.digitalmars.com/d/1.0/changelog.html
http://ftp.digitalmars.com/dmd.1.019.zip
http://www.digitalmars.com/d/changelog.html
http://ftp.digitalmars.com/dmd.2.003.zip
Well, this __traits stuff is certainly going to give me something to
think about. One note: the lexical page doesn't seem to list it as a
keyword.

How many times have I rewritten Pyd? Three? Well, no matter. This should
make things interesting again.
--
Kirk McDonald
http://kirkmcdonald.blogspot.com
Pyd: Connecting D and Python
http://pyd.dsource.org
Walter Bright
2007-07-23 03:41:11 UTC
Permalink
Post by Kirk McDonald
Well, this __traits stuff is certainly going to give me something to
think about. One note: the lexical page doesn't seem to list it as a
keyword.
How many times have I rewritten Pyd? Three? Well, no matter. This should
make things interesting again.
Hey, you asked for it <g>.
Pragma
2007-07-24 13:51:31 UTC
Permalink
Post by Kirk McDonald
Post by Walter Bright
http://www.digitalmars.com/d/1.0/changelog.html
http://ftp.digitalmars.com/dmd.1.019.zip
http://www.digitalmars.com/d/changelog.html
http://ftp.digitalmars.com/dmd.2.003.zip
Well, this __traits stuff is certainly going to give me something to
think about. One note: the lexical page doesn't seem to list it as a
keyword.
How many times have I rewritten Pyd? Three? Well, no matter. This should
make things interesting again.
Kirk, I saw your blog post regarding this. Congrats. Looks like you had a bumper-crop of code reductions!
--
- EricAnderton at yahoo
Kirk McDonald
2007-07-24 18:38:58 UTC
Permalink
Post by Pragma
Post by Kirk McDonald
Post by Walter Bright
http://www.digitalmars.com/d/1.0/changelog.html
http://ftp.digitalmars.com/dmd.1.019.zip
http://www.digitalmars.com/d/changelog.html
http://ftp.digitalmars.com/dmd.2.003.zip
Well, this __traits stuff is certainly going to give me something to
think about. One note: the lexical page doesn't seem to list it as a
keyword.
How many times have I rewritten Pyd? Three? Well, no matter. This
should make things interesting again.
Kirk, I saw your blog post regarding this. Congrats. Looks like you
had a bumper-crop of code reductions!
The linked-to changeset was from last November, when D got tuples. I
haven't committed anything using __traits, yet.
--
Kirk McDonald
http://kirkmcdonald.blogspot.com
Pyd: Connecting D and Python
http://pyd.dsource.org
Pragma
2007-07-24 21:39:32 UTC
Permalink
Post by Kirk McDonald
Post by Pragma
Post by Kirk McDonald
Post by Walter Bright
http://www.digitalmars.com/d/1.0/changelog.html
http://ftp.digitalmars.com/dmd.1.019.zip
http://www.digitalmars.com/d/changelog.html
http://ftp.digitalmars.com/dmd.2.003.zip
Well, this __traits stuff is certainly going to give me something to
think about. One note: the lexical page doesn't seem to list it as a
keyword.
How many times have I rewritten Pyd? Three? Well, no matter. This
should make things interesting again.
Kirk, I saw your blog post regarding this. Congrats. Looks like you
had a bumper-crop of code reductions!
The linked-to changeset was from last November, when D got tuples. I
haven't committed anything using __traits, yet.
D'oh. Shoulda read more carefully... ;)
--
- EricAnderton at yahoo
Jascha Wetzel
2007-07-23 00:47:21 UTC
Permalink
Post by Walter Bright
http://www.digitalmars.com/d/1.0/changelog.html
http://ftp.digitalmars.com/dmd.1.019.zip
http://www.digitalmars.com/d/changelog.html
http://ftp.digitalmars.com/dmd.2.003.zip
new toys! neat! thanks :)
Jarrett Billingsley
2007-07-23 03:31:20 UTC
Permalink
"Walter Bright" <newshound1 at digitalmars.com> wrote in message
Post by Walter Bright
http://www.digitalmars.com/d/1.0/changelog.html
http://ftp.digitalmars.com/dmd.1.019.zip
http://www.digitalmars.com/d/changelog.html
http://ftp.digitalmars.com/dmd.2.003.zip
You're really making it hard for me not to switch to D2.0. __traits looks
absolutely amazing. Just remove const-ness and I'll switch ;)
Jarrett Billingsley
2007-07-23 03:35:44 UTC
Permalink
"Jarrett Billingsley" <kb3ctd2 at yahoo.com> wrote in message
Post by Jarrett Billingsley
You're really making it hard for me not to switch to D2.0. __traits looks
absolutely amazing. Just remove const-ness and I'll switch ;)
A question -- many of the descriptions of the __traits functions say that
"an array is returned." But some of the samples look like tuples are being
used:

alias typeof(__traits(getVirtualFunctions, D, "foo")) b;
foreach (t; b)
writefln(typeid(t));

If this really did return an array, the typeof() it would be a single item,
not a list, and you wouldn't be able to foreach over it. So does this
return a tuple instead?
Walter Bright
2007-07-23 03:42:34 UTC
Permalink
Post by Jarrett Billingsley
A question -- many of the descriptions of the __traits functions say that
"an array is returned." But some of the samples look like tuples are being
alias typeof(__traits(getVirtualFunctions, D, "foo")) b;
foreach (t; b)
writefln(typeid(t));
If this really did return an array, the typeof() it would be a single item,
not a list, and you wouldn't be able to foreach over it. So does this
return a tuple instead?
getVirtualFunctions returns a tuple of expressions.
Max Samukha
2007-07-23 06:09:01 UTC
Permalink
On Sun, 22 Jul 2007 16:26:28 -0700, Walter Bright
Post by Walter Bright
http://www.digitalmars.com/d/1.0/changelog.html
http://ftp.digitalmars.com/dmd.1.019.zip
http://www.digitalmars.com/d/changelog.html
http://ftp.digitalmars.com/dmd.2.003.zip
Thanks for 1300!

There is a typo in the example for hasMember trait: 'm' struct member
should be 'x'.
Walter Bright
2007-07-23 07:18:04 UTC
Permalink
Post by Max Samukha
There is a typo in the example for hasMember trait: 'm' struct member
should be 'x'.
Got it.
Aarti_pl
2007-07-23 07:18:09 UTC
Permalink
Thank you! Great release!

---

I just would wish, that you don't use so much ugly underscores in front
and in the middle of nice D keywords.

It's just a cosmetical issue, but nevertheless why to loose points here
if it should be rather easy to change it? Good chance to change it in
2.0 branch...

Probably it should also include __LINE__, __FILE__ and other Special
Tokens, which essentially *are* compile time reflections.

Regards
Marcin Kuszczak
Post by Walter Bright
http://www.digitalmars.com/d/1.0/changelog.html
http://ftp.digitalmars.com/dmd.1.019.zip
http://www.digitalmars.com/d/changelog.html
http://ftp.digitalmars.com/dmd.2.003.zip
Christian Kamm
2007-07-23 08:06:40 UTC
Permalink
Thanks for fixing bug 668!

With the new __traits, the documentation for getVirtualFunctions states that
it gets the "virtual overloads". What does that mean? If I make some of the
methods final, it lists them anyway.

Does it just get all overloads (and should be named getFunctionOverloads),
or is there some limitation?
Walter Bright
2007-07-23 16:43:55 UTC
Permalink
Post by Christian Kamm
Thanks for fixing bug 668!
With the new __traits, the documentation for getVirtualFunctions states that
it gets the "virtual overloads". What does that mean? If I make some of the
methods final, it lists them anyway.
Final functions are still virtual (since the super classes are still
calling it).
Post by Christian Kamm
Does it just get all overloads (and should be named getFunctionOverloads),
or is there some limitation?
No, just the virtual functions.
Don Clugston
2007-07-23 08:58:05 UTC
Permalink
Post by Walter Bright
http://www.digitalmars.com/d/1.0/changelog.html
http://ftp.digitalmars.com/dmd.1.019.zip
http://www.digitalmars.com/d/changelog.html
http://ftp.digitalmars.com/dmd.2.003.zip
2.0 suddenly becomes very appealing ...

I'm having trouble understanding the difference between "isScalar",
"isArithmetic", and "isIntegral". Is this table correct?

int uint real wchar
Y Y Y N isArithmetic
N N Y N isFloating
Y Y N Y isIntegral
Y Y Y Y isScalar
N Y N N isUnsigned

----------------
Walter Bright
2007-07-23 16:45:57 UTC
Permalink
Post by Don Clugston
I'm having trouble understanding the difference between "isScalar",
"isArithmetic", and "isIntegral". Is this table correct?
int uint real wchar
Y Y Y N isArithmetic
N N Y N isFloating
Y Y N Y isIntegral
Y Y Y Y isScalar
N Y N N isUnsigned
----------------
wchar is arithmetic and unsigned.
Don Clugston
2007-07-23 18:23:35 UTC
Permalink
Post by Walter Bright
Post by Don Clugston
I'm having trouble understanding the difference between "isScalar",
"isArithmetic", and "isIntegral". Is this table correct?
int uint real wchar
Y Y Y N isArithmetic
N N Y N isFloating
Y Y N Y isIntegral
Y Y Y Y isScalar
N Y N N isUnsigned
----------------
wchar is arithmetic and unsigned.
OK. Then is there any difference between scalar and arithmetic ?
Frits van Bommel
2007-07-23 18:35:21 UTC
Permalink
Post by Don Clugston
Post by Walter Bright
Post by Don Clugston
I'm having trouble understanding the difference between "isScalar",
"isArithmetic", and "isIntegral". Is this table correct?
int uint real wchar
Y Y Y N isArithmetic
N N Y N isFloating
Y Y N Y isIntegral
Y Y Y Y isScalar
N Y N N isUnsigned
----------------
wchar is arithmetic and unsigned.
OK. Then is there any difference between scalar and arithmetic ?
I haven't checked DMDs handling of this, but if I understand the terms
correctly then the difference should be in the handling of complex types
(cfloat & friends) which should be arithmetic types but not scalar ones.
Walter Bright
2007-07-23 19:22:32 UTC
Permalink
Post by Don Clugston
Post by Walter Bright
Post by Don Clugston
I'm having trouble understanding the difference between "isScalar",
"isArithmetic", and "isIntegral". Is this table correct?
int uint real wchar
Y Y Y N isArithmetic
N N Y N isFloating
Y Y N Y isIntegral
Y Y Y Y isScalar
N Y N N isUnsigned
----------------
wchar is arithmetic and unsigned.
OK. Then is there any difference between scalar and arithmetic ?
scalar includes pointers.
Derek Parnell
2007-07-23 20:59:35 UTC
Permalink
Post by Walter Bright
Post by Don Clugston
Post by Walter Bright
Post by Don Clugston
I'm having trouble understanding the difference between "isScalar",
"isArithmetic", and "isIntegral". Is this table correct?
int uint real wchar
Y Y Y N isArithmetic
N N Y N isFloating
Y Y N Y isIntegral
Y Y Y Y isScalar
N Y N N isUnsigned
----------------
wchar is arithmetic and unsigned.
OK. Then is there any difference between scalar and arithmetic ?
scalar includes pointers.
And yet one can do (some) arithmetic on pointers ... !?

import std.stdio;
void main()
{
int i;
int* p;
p = &i;
p += 2;
writefln("%s %s", &i, p);
}
--
Derek Parnell
Melbourne, Australia
skype: derek.j.parnell
Walter Bright
2007-07-23 22:02:13 UTC
Permalink
Post by Derek Parnell
Post by Walter Bright
Post by Don Clugston
Post by Walter Bright
Post by Don Clugston
I'm having trouble understanding the difference between "isScalar",
"isArithmetic", and "isIntegral". Is this table correct?
int uint real wchar
Y Y Y N isArithmetic
N N Y N isFloating
Y Y N Y isIntegral
Y Y Y Y isScalar
N Y N N isUnsigned
----------------
wchar is arithmetic and unsigned.
OK. Then is there any difference between scalar and arithmetic ?
scalar includes pointers.
And yet one can do (some) arithmetic on pointers ... !?
Yes. These definitions of integral, arithmetic, and scalar are common in
C derived languages (and is defined in the C standard, too).
Derek Parnell
2007-07-23 20:54:41 UTC
Permalink
Post by Walter Bright
Post by Don Clugston
I'm having trouble understanding the difference between "isScalar",
"isArithmetic", and "isIntegral". Is this table correct?
int uint real wchar
Y Y Y N isArithmetic
N N Y N isFloating
Y Y N Y isIntegral
Y Y Y Y isScalar
N Y N N isUnsigned
----------------
wchar is arithmetic and unsigned.
Are you serious??? Why are we allowed to do mathematics with characters?

dchar r = power( 'a' * 'b' + 'd' * '?') / '$';

Doesn't make sense so why is wchar arithmetic?

If you insist in this wart, then we also need an 'isCharacter' trait to
distinguish characters from numbers.
--
Derek Parnell
Melbourne, Australia
skype: derek.j.parnell
BCS
2007-07-23 21:50:50 UTC
Permalink
Reply to Derek,
Post by Derek Parnell
Are you serious??? Why are we allowed to do mathematics with
characters?
I have done this a few times

char c;
int v = (c - '0')
James Dennett
2007-07-24 04:25:31 UTC
Permalink
Post by BCS
Reply to Derek,
Post by Derek Parnell
Are you serious??? Why are we allowed to do mathematics with
characters?
I have done this a few times
char c;
int v = (c - '0')
Perfectly reasonable, as is character +/- integer, but
character + character is nonsense, just as it makes sense
to subtract two points yielding a vector, or add a vector
to a point (yielding a point) but no sense to "add" two
points in a mere affine space.

-- James
Derek Parnell
2007-07-24 05:15:05 UTC
Permalink
Post by James Dennett
Post by BCS
Reply to Derek,
Post by Derek Parnell
Are you serious??? Why are we allowed to do mathematics with
characters?
I have done this a few times
char c;
int v = (c - '0')
Perfectly reasonable, as is character +/- integer, but
character + character is nonsense, just as it makes sense
to subtract two points yielding a vector, or add a vector
to a point (yielding a point) but no sense to "add" two
points in a mere affine space.
I'm sorry. I am a bit of a pedantic bastard at times.

I use ...

char c;
int v = (cast(int)c - '0')

To me it the same as assuming that boolean values are integers.
--
Derek
(skype: derek.j.parnell)
Melbourne, Australia
24/07/2007 3:13:04 PM
0ffh
2007-07-24 06:39:49 UTC
Permalink
Post by Derek Parnell
I use ...
char c;
int v = (cast(int)c - '0')
To me it the same as assuming that boolean values are integers.
You suggest writing things like

for (int c=0x100;c!=0;--c) {...}

or

for (int c=0x100;cast(bool)c;--c) {...}

?

UGH! :-)

Maybe another example what systems programming language might mean:
A language that encourages the programmer to know what is going on
behind the scenes, after compilation, and allows her to make use of
that knowledge.
If I know that testing a condition is nothing but comparing a number
to zero, writing "if (number!=0)" just becomes redundant.

Regards, Frank
Derek Parnell
2007-07-24 07:03:31 UTC
Permalink
Post by 0ffh
Post by Derek Parnell
I use ...
char c;
int v = (cast(int)c - '0')
To me it the same as assuming that boolean values are integers.
You suggest writing things like
for (int c=0x100;c!=0;--c) {...}
or
for (int c=0x100;cast(bool)c;--c) {...}
?
Yep. That's how I tend to do my non-assembler coding, but with a lot more
white space, less 'jargon', and avoid magic numbers :-)

const MaxWidgetCount = 256;
for (int lRemaining = MaxWidgetCount; lRemaining != 0; lRemaining--)
{
...
}
Post by 0ffh
UGH! :-)
A language that encourages the programmer to know what is going on
behind the scenes, after compilation, and allows her to make use of
that knowledge.
If I know that testing a condition is nothing but comparing a number
to zero, writing "if (number!=0)" just becomes redundant.
I'm different. I write code so other people can read it with as little
effort as possible ... and sometimes I even succeed <G>
--
Derek
(skype: derek.j.parnell)
Melbourne, Australia
24/07/2007 4:53:26 PM
BCS
2007-07-24 16:37:43 UTC
Permalink
Reply to 0ffh,
Post by 0ffh
If I know that testing a condition is nothing but comparing a number
to zero, writing "if (number!=0)" just becomes redundant.
actually ASM usually has built in >, < and = comparisons, some times these
implicitly use 0 for the other side, but it still it is not /just/ a zero
test.
0ffh
2007-07-24 22:01:06 UTC
Permalink
Post by BCS
Reply to 0ffh,
Post by 0ffh
If I know that testing a condition is nothing but comparing a number
to zero, writing "if (number!=0)" just becomes redundant.
actually ASM usually has built in >, < and = comparisons, some times
these implicitly use 0 for the other side, but it still it is not /just/
a zero test.
Forgive me if I am being thick, but given C (or even D), when does
"if (x!=0)" (or "if (x!=null)") ever give a different result from "if (x)"?
I am naturally speaking integral types and pointers, for floating point
numbers the resulting code will obviously depend on the specific format
used (though compilers will usually make it to act as expected, but I know
I have to /know/, not assume).

As to why "if (x)" is (at least historically) a Good Thing (tm):
If "x" is any kind of calculation, that calculation will usually implicitly
set (or clear) the zero flag of the CPU, doing away with the need for any
kind of comparison at all. On some machines just loading the value of a
memory location into a register will work the zero flag. On many, doing
something like OR or AND of the register against itself will do the trick
a bit faster than actually comparing against any number (including zero).
On the x86, at some point of time, TESTing a memory location was faster
than CMPing it (with a very pinch-of-salty IIRC).
Especially "while" does usually gain some benefit from those cases.
(And of cause a good back end optimisation will still exploit those because
it knows that the "(x!=0)" is the same special case as the "(x)", granted.)

So my defense is reduced to it being a good and useful convention, as I
cherish every keystroke I don't have to execute, and it's really easy to
learn and get used to... and, above all else, it /looks/ better! ;-)

Regards, Frank
BCS
2007-07-24 22:32:58 UTC
Permalink
Reply to 0ffh,
Post by 0ffh
Post by BCS
Reply to 0ffh,
Post by 0ffh
If I know that testing a condition is nothing but comparing a number
to zero, writing "if (number!=0)" just becomes redundant.
actually ASM usually has built in >, < and = comparisons, some times
these implicitly use 0 for the other side, but it still it is not
/just/ a zero test.
Forgive me if I am being thick, but given C (or even D), when does
"if (x!=0)" (or "if (x!=null)") ever give a different result from "if (x)"?
Never to my understanding. However this is a good reason to do the more verbose
one in that the compiler gets more info and then can use that for optimization
(maybe). That however is more of a general rule rather than just for this
case.
0ffh
2007-07-24 23:51:49 UTC
Permalink
Post by BCS
Reply to 0ffh,
Post by BCS
Reply to 0ffh,
[...]
[...]
[...]
Never to my understanding. However this is a good reason to do the more
verbose one in that the compiler gets more info and then can use that
for optimization (maybe).
Well, if we agree the semantics are identical, then so is the info the
compiler has (phew, I'm glad that this works both ways...).
Post by BCS
That however is more of a general rule rather than just for this case.
I accept it as a general rule. =)

Kind regards, Frank
Robert Fraser
2007-07-25 00:55:41 UTC
Permalink
Post by 0ffh
Post by BCS
Reply to 0ffh,
Post by BCS
Reply to 0ffh,
[...]
[...]
[...]
Never to my understanding. However this is a good reason to do the more
verbose one in that the compiler gets more info and then can use that
for optimization (maybe).
Well, if we agree the semantics are identical, then so is the info the
compiler has (phew, I'm glad that this works both ways...).
Post by BCS
That however is more of a general rule rather than just for this case.
I accept it as a general rule. =)
Kind regards, Frank
There was a discussion of this on digitalmars.D recently. While that syntax works fine for most cases, it doesn't work in (non-static) asserts for aggregate types with invariants: assert(obj) runs the object's invariant() method, which will segfault if the object is null instead of giving a nice assertion failure.

"if(x != 0)" is just more explicit than "if(x)", but not many people use "if(b != false)" (unless you're that guy where I wrote who wrote "while(m_userSubscribed == Boolean.FALSE.booleanValue())", which I sincerely hope wasn't sincere), so being concise isn't bad as long as you're meaning is clear. I think it looks ugly in for loops, though:

for(int i = 100; i; i--) // Takes a second to mentally figure out what's going on
Derek Parnell
2007-07-25 07:53:39 UTC
Permalink
Post by Robert Fraser
for(int i = 100; i; i--) // Takes a second to mentally figure out what's going on
I'm still not explaining myself I guess. Yes, it doesn't take much to work
out what the compiler is going to generate for that code. But that is not
the issue I'm addressing.

If one see's a line of code like that one has trouble recognising that what
was written may not have been what was intended to be written. How do we
know that the code shouldn't have been ...

for(int i = 100; i>1; i--)

and the coder made a small typo out of (bad?) habits. If however, one gets
used to typing 'i>0' or similar fully specified comparisions, we all have a
better confidence level that the code is written as intended to be written.

Of course, it is not a way to prevent all errors, but just a technique to
reduce coding errors.

And a good compiler can still optimise such constructions without us having
to hold its hand it all the way to the machine-code.

I write program code for humans not for computers. It's the compiler's job
to prepare it for the computer.

Sorry that this sounds so pompous and self-righteous. That is not how I'm
trying to sound.
--
Derek Parnell
Melbourne, Australia
"Down with mediocrity!"
Regan Heath
2007-07-25 10:22:43 UTC
Permalink
Post by Derek Parnell
Post by Robert Fraser
for(int i = 100; i; i--) // Takes a second to mentally figure out what's going on
I'm still not explaining myself I guess. Yes, it doesn't take much to work
out what the compiler is going to generate for that code. But that is not
the issue I'm addressing.
If one see's a line of code like that one has trouble recognising that what
was written may not have been what was intended to be written. How do we
know that the code shouldn't have been ...
for(int i = 100; i>1; i--)
Well.. I'd say that is unlikely.

The more likely meaning was:
for(int i = 100; i > 0; i--)

But! (to support your side of the argument here) the short form:
for(int i = 100; i; i--)

actually means:
for(int i = 100; i != 0; i--)

which is subtly different in the case where i is (mistakenly) set to a
negative value inside the loop!

So, in this case I would have to agree that "i > 0" has a different
meaning to plain "i" and prevents a bug as well.

In general, where the meaning is the same (i.e. "i == 0") I favour "if
(i)" and have no trouble reading either form (which I think is a benefit
we should all acquire you never know whose code you'll be reading next!)

Regan
0ffh
2007-07-25 10:36:25 UTC
Permalink
Post by Derek Parnell
Post by Robert Fraser
for(int i = 100; i; i--) // Takes a second to mentally figure out what's going on
I'm still not explaining myself I guess. Yes, it doesn't take much to work
out what the compiler is going to generate for that code. But that is not
the issue I'm addressing.
I think maybe you wanted to address me here, not Robert.
A second is a looonng time! :)
Post by Derek Parnell
If however, one gets used to typing 'i>0' or similar fully specified comparisions,
we all have a better confidence level that the code is written as intended to be written.
Of course, it is not a way to prevent all errors, but just a technique to
reduce coding errors.
I know the argument well. I use it myself to argue for fully braced
expressions instead of relying on operator precedence (apart from
the usual exceptions). Also, braces will actually help me parsing.

BUT there is a huge difference here: I'll repeat it this once before
stopping to do this (I don't believe in reiteration contests):

Using integers or pointers as bools is

1. /Easy/ to understand and use correctly
2. /Shorter/ - less to type and less to take in - and therefore
3. /Faster/ to parse mentally (once you're used to it), also it's
4. Not obligatory for those who feel uncomfortable with it, but
5. Looks one darn hell better
than having a detrimental tumour of nop characters attached.
Post by Derek Parnell
I write program code for humans not for computers. It's the compiler's job
to prepare it for the computer.
Source code is for humans, machine code for computers, so far we agree.
But source code is for a /subclass/ of humans only: Those who are
knowledgeable in the programming language that was used. If I don't know
Miranda I will sure as heck not complain to Miranda programmers about their
unreadable code, because it is /my friggin fault/.
If I code in Miranda and I produce a bug because I do not understand the
mechanisms involved, it is still /my friggin fault/.
Post by Derek Parnell
Sorry that this sounds so pompous and self-righteous. That is not how I'm
trying to sound.
Blast, don't kick yourself! I'll do that! :)

Regards, Frank The Eternally Distracted
James Dennett
2007-07-26 03:58:57 UTC
Permalink
Post by 0ffh
Post by Derek Parnell
Post by Robert Fraser
for(int i = 100; i; i--) // Takes a second to mentally figure out what's going on
I'm still not explaining myself I guess. Yes, it doesn't take much to work
out what the compiler is going to generate for that code. But that is not
the issue I'm addressing.
I think maybe you wanted to address me here, not Robert.
A second is a looonng time! :)
Post by Derek Parnell
If however, one gets used to typing 'i>0' or similar fully specified comparisions,
we all have a better confidence level that the code is written as intended to be written.
Of course, it is not a way to prevent all errors, but just a technique to
reduce coding errors.
I know the argument well. I use it myself to argue for fully braced
expressions instead of relying on operator precedence (apart from
the usual exceptions). Also, braces will actually help me parsing.
BUT there is a huge difference here: I'll repeat it this once before
Using integers or pointers as bools is
1. /Easy/ to understand and use correctly
2. /Shorter/ - less to type and less to take in - and therefore
3. /Faster/ to parse mentally (once you're used to it), also it's
4. Not obligatory for those who feel uncomfortable with it, but
5. Looks one darn hell better
than having a detrimental tumour of nop characters attached.
And, with a similar amount of evidence, I claim that being explicit
about comparisons with zero or null is

1. Easier to understand and use correctly;
2. More explicit - less to fill in implicitly, and therefore
3. Faster to parse mentally (once you're used to rigor), also it's
4. Not obligatory for those who feel uncomfortable with it, but
5. Looks one darn hell better than having expressions that are
morally, if not technically, type errors left in code.

I suspect, but cannot prove, that it's also less error-prone.
However, without evidence, the debate is pointless.

-- James
0ffh
2007-07-25 09:59:23 UTC
Permalink
Post by Robert Fraser
"if(x != 0)" is just more explicit than "if(x)", but not many people use "if(b != false)" (unless you're that guy
where I wrote who wrote "while(m_userSubscribed == Boolean.FALSE.booleanValue())", which I sincerely hope wasn't
So help me glod I did not, but I consider that code line to be sarcastic
humour! :)
Post by Robert Fraser
for(int i = 100; i; i--) // Takes a second to mentally figure out what's going on
Funny! I claim my brain parses the "i" /faster/ without the "=!0"!

"if (x)" takes me half a glance to parse and understand.
"if (x!=0)" takes at least three quarters of a glance.

Maybe it's just a matter of being used to use this construct?

Regards, Frank
James Dennett
2007-07-26 04:00:18 UTC
Permalink
Post by 0ffh
Post by Robert Fraser
"if(x != 0)" is just more explicit than "if(x)", but not many people
use "if(b != false)" (unless you're that guy
where I wrote who wrote "while(m_userSubscribed ==
Boolean.FALSE.booleanValue())", which I sincerely hope wasn't
sincere), so being concise isn't bad as long as you're meaning is
So help me glod I did not, but I consider that code line to be sarcastic
humour! :)
Post by Robert Fraser
for(int i = 100; i; i--) // Takes a second to mentally figure out what's going on
Funny! I claim my brain parses the "i" /faster/ without the "=!0"!
"if (x)" takes me half a glance to parse and understand.
"if (x!=0)" takes at least three quarters of a glance.
Maybe it's just a matter of being used to use this construct?
No; you'll find that many of those who advocate the explicit
approach are very used to both. It's best not to assume that
people whose opinions differ from our own are less informed.

-- James
0ffh
2007-07-26 05:48:48 UTC
Permalink
Post by James Dennett
No; you'll find that many of those who advocate the explicit
approach are very used to both. It's best not to assume that
people whose opinions differ from our own are less informed.
Wow, next time Derek is feeling afraid about having a pompous
and self-righteous writing style, I'll point you out to him...
0ffh
2007-07-26 06:05:17 UTC
Permalink
Post by James Dennett
No; you'll find that many of those who advocate the explicit
approach are very used to both. It's best not to assume that
people whose opinions differ from our own are less informed.
Wow! Next time Derek is afraid if his writing style might sound
pompous and self-righteous, I'll point yours out to him. Thanks!
0ffh
2007-07-26 06:14:28 UTC
Permalink
Post by James Dennett
No; you'll find that many of those who advocate the explicit
approach are very used to both. It's best not to assume that
people whose opinions differ from our own are less informed.
Wow! Next time Derek is afraid if his writing style might sound
pompous and self-righteous, I'll point yours out to him. Thanks!

Also, of course all of us know perfectly well that ultimately this
debate was pointless, as it's not real probable that anyone changes
his or her opinion. Still we all felt we needed to air those, and
we did so in an (I feel) happy and inoffensive (if lively) way.

Thanks again for blundering in, Frank
0ffh
2007-07-26 07:59:05 UTC
Permalink
Post by James Dennett
Post by 0ffh
Maybe it's just a matter of being used to use this construct?
No; you'll find that many of those who advocate the explicit
approach are very used to both. It's best not to assume that
people whose opinions differ from our own are less informed.
I assume if you really, really tried, you could spot the
difference between offering a noncommittal hypothesis and
making an assumption.
James Dennett
2007-07-24 18:41:38 UTC
Permalink
Post by Derek Parnell
Post by James Dennett
Post by BCS
Reply to Derek,
Post by Derek Parnell
Are you serious??? Why are we allowed to do mathematics with characters?
I have done this a few times
char c;
int v = (c - '0')
Perfectly reasonable, as is character +/- integer, but
character + character is nonsense, just as it makes sense
to subtract two points yielding a vector, or add a vector
to a point (yielding a point) but no sense to "add" two
points in a mere affine space.
I'm sorry. I am a bit of a pedantic bastard at times.
You're in good company.
Post by Derek Parnell
I use ...
char c;
int v = (cast(int)c - '0')
To me it the same as assuming that boolean values are integers.
Subtracting a char from an int, as you appear to be doing
above, also makes no sense... or do casts in D bind insanely
loosely? Subtracting one char from another actually makes
more sense (see analogy above to affine geometry). It's a
reasonable question to ask "which offset must I add to this
char to get to this other char", but not "what's the difference
between the number 27 and the character 'o'?".

(And yes, I feel guilty/contaminated if I ever treat a boolean
value as an integer, or vice versa.)

-- James
BCS
2007-07-24 18:53:46 UTC
Permalink
Reply to James,
(And yes, I feel guilty/contaminated if I ever treat a boolean value
as an integer, or vice versa.)
a while ago I wrote a peice of C++ like this

start:

///

goto {&&start, &&stop}[!!i + 2 * !j];
stop:

but then again it was for a bad code contest
Paul Findlay
2007-07-25 01:54:26 UTC
Permalink
Post by BCS
goto {&&start, &&stop}[!!i + 2 * !j];
*Sigh*. I wish we had those GNU 'label as value' extensions in D

- Paul
0ffh
2007-07-24 06:01:19 UTC
Permalink
Post by James Dennett
Post by BCS
char c;
int v = (c - '0')
Perfectly reasonable, as is character +/- integer, but
character + character is nonsense, just as it makes sense
to subtract two points yielding a vector, or add a vector
to a point (yielding a point) but no sense to "add" two
points in a mere affine space.
So we get:

char +/- int : okay
int +/- char : okay
char - char : okay
char + char : baddie!

I Look at this this way: Nobody in his right mind is gonna
try to put into the compiler, which kinds of calculation
make "sense" and which don't; that would be just insane.

Also, in C at least a char is just another kind of number
that just happens to be about the right size for an ASCII
value, at least that's the way I look at it... ;-)

Regards, Frank
Walter Bright
2007-07-24 18:10:16 UTC
Permalink
Post by 0ffh
char +/- int : okay
int +/- char : okay
char - char : okay
char + char : baddie!
I Look at this this way: Nobody in his right mind is gonna
try to put into the compiler, which kinds of calculation
make "sense" and which don't; that would be just insane.
But I do things like:

c += 'a' - 'A'; // to lower case

The problem with explicit casts is that they are a brute force method,
and subvert static type checking. A well designed systems allows a
balance between implicit casting and strong type checking so that
explicit casts are rarely needed in properly written programs.
James Dennett
2007-07-24 18:45:14 UTC
Permalink
Post by Walter Bright
Post by 0ffh
char +/- int : okay
int +/- char : okay
char - char : okay
char + char : baddie!
I Look at this this way: Nobody in his right mind is gonna
try to put into the compiler, which kinds of calculation
make "sense" and which don't; that would be just insane.
c += 'a' - 'A'; // to lower case
Which is fine according to the above rules: it uses char-char
(giving int, I hope), and then char+int (giving char, with
risk of overflow/wraparound in more general contexts but not
in this case).
Post by Walter Bright
The problem with explicit casts is that they are a brute force method,
and subvert static type checking. A well designed systems allows a
balance between implicit casting and strong type checking so that
explicit casts are rarely needed in properly written programs.
That's why I like the rules above. They permit all sane
uses of arithmetic on characters while disallowing many
erroneous uses, and with no need for casts.

Not that I'm actually seriously suggesting changing D in
this direction. This just isn't worth going against what
most programmers with C/C++/Java-like backgrounds expect.

-- James
BCS
2007-07-24 18:55:57 UTC
Permalink
Reply to Walter,
Post by Walter Bright
c += 'a' - 'A'; // to lower case
this is safer and faster (Ihink)

c |= 0b0010_0000;
James Dennett
2007-07-24 19:02:12 UTC
Permalink
Post by BCS
Reply to Walter,
Post by Walter Bright
c += 'a' - 'A'; // to lower case
this is safer and faster (Ihink)
c |= 0b0010_0000;
Walter's version works on any platform where upper and lower
case letters have the same arrangement, including any gaps;
yours is pretty much tied to ASCII and extensions thereof.

(On the other hand, yours is idempotent, whereas Walter's
depends on knowing that c started as upper case.)

-- James
BCS
2007-07-24 19:34:47 UTC
Permalink
Reply to James,
Walter's version works on any platform where upper and lower case
letters have the same arrangement, including any gaps; yours is pretty
much tied to ASCII and extensions thereof.
good point, OTOH how often are non ASCII derived systems used (I've heard
of a few but never run into any)
(On the other hand, yours is idempotent, whereas Walter's depends on
knowing that c started as upper case.)
James Dennett
2007-07-24 19:41:09 UTC
Permalink
Post by BCS
Reply to James,
Walter's version works on any platform where upper and lower case
letters have the same arrangement, including any gaps; yours is pretty
much tied to ASCII and extensions thereof.
good point, OTOH how often are non ASCII derived systems used (I've
heard of a few but never run into any)
With D, at present, probably none. Some mainframes and
some embedded environments are the only remaining ones
I know about (though my knowledge is, of course, a long
long way from being encyclopedic.)

-- James
Bill Baxter
2007-07-24 19:58:25 UTC
Permalink
Post by James Dennett
Post by BCS
Reply to James,
Walter's version works on any platform where upper and lower case
letters have the same arrangement, including any gaps; yours is pretty
much tied to ASCII and extensions thereof.
good point, OTOH how often are non ASCII derived systems used (I've
heard of a few but never run into any)
With D, at present, probably none. Some mainframes and
some embedded environments are the only remaining ones
I know about (though my knowledge is, of course, a long
long way from being encyclopedic.)
But both simple schemes for lowercasing will fail on things like
accented characters. Seeing tricks like that just to avoid calling
tolower() makes me cringe.

--bb
renoX
2007-07-25 05:23:14 UTC
Permalink
Post by Bill Baxter
Post by James Dennett
Post by BCS
Reply to James,
Walter's version works on any platform where upper and lower case
letters have the same arrangement, including any gaps; yours is pretty
much tied to ASCII and extensions thereof.
good point, OTOH how often are non ASCII derived systems used (I've
heard of a few but never run into any)
With D, at present, probably none. Some mainframes and
some embedded environments are the only remaining ones
I know about (though my knowledge is, of course, a long
long way from being encyclopedic.)
But both simple schemes for lowercasing will fail on things like
accented characters. Seeing tricks like that just to avoid calling
tolower() makes me cringe.
--bb
True, it only work for real ASCII which has no accentuated characters.

renoX
Russell Lewis
2007-07-25 19:30:48 UTC
Permalink
Post by James Dennett
With D, at present, probably none. Some mainframes and
some embedded environments are the only remaining ones
I know about (though my knowledge is, of course, a long
long way from being encyclopedic.)
IBM still builds some machines which use EBCDIC, but with EBCDIC, things
are even worse: the characters aren't even arranged contiguously in the
space! So in EBCDIC
char c;
int i = c - 'a';
won't work!

But you're right, I don't think that D is running on any of
those...unless GDC is portable to one...
BCS
2007-07-25 22:25:54 UTC
Permalink
Post by Russell Lewis
Post by James Dennett
With D, at present, probably none. Some mainframes and
some embedded environments are the only remaining ones
I know about (though my knowledge is, of course, a long
long way from being encyclopedic.)
IBM still builds some machines which use EBCDIC, but with EBCDIC, things
are even worse: the characters aren't even arranged contiguously in the
space! So in EBCDIC
char c;
int i = c - 'a';
won't work!
a-f and A-F are sequential so that works (after case conversion) and
also a & A are different by only one bit so:

c |= 'a' ^ 'A'
c &= ~('a' ^ 'a')

works, as does

c += ('a' - 'A')
Walter Bright
2007-07-24 22:41:36 UTC
Permalink
Post by BCS
Reply to James,
Walter's version works on any platform where upper and lower case
letters have the same arrangement, including any gaps; yours is pretty
much tied to ASCII and extensions thereof.
good point, OTOH how often are non ASCII derived systems used (I've
heard of a few but never run into any)
D kind of explicitly abandons things like EBCDIC anyway.
Post by BCS
(On the other hand, yours is idempotent, whereas Walter's depends on
knowing that c started as upper case.)
0ffh
2007-07-24 21:03:59 UTC
Permalink
Post by James Dennett
[...]
[...]
(On the other hand, yours is idempotent, whereas Walter's
depends on knowing that c started as upper case.)
Wow, idempotent!
I last read that word studying fuzzy logic! ;-)))

Regards, Frank
Georg Wrede
2007-07-24 23:52:18 UTC
Permalink
Post by 0ffh
Post by James Dennett
[...]
[...]
(On the other hand, yours is idempotent, whereas Walter's
depends on knowing that c started as upper case.)
Wow, idempotent!
I last read that word studying fuzzy logic! ;-)))
Yes, a fancy word, indeed.

OTOH, it's as important as "equivalence" and "implies".
Pragma
2007-07-25 13:57:08 UTC
Permalink
Post by Georg Wrede
Post by 0ffh
Post by James Dennett
[...]
[...]
(On the other hand, yours is idempotent, whereas Walter's
depends on knowing that c started as upper case.)
Wow, idempotent!
I last read that word studying fuzzy logic! ;-)))
Yes, a fancy word, indeed.
Indeed. It's a perfectly cromulent word. :)
Post by Georg Wrede
OTOH, it's as important as "equivalence" and "implies".
--
- EricAnderton at yahoo
Walter Bright
2007-07-24 22:40:57 UTC
Permalink
Post by BCS
Reply to Walter,
Post by Walter Bright
c += 'a' - 'A'; // to lower case
this is safer and faster (Ihink)
c |= 0b0010_0000;
On modern processors, there is no speed difference between the two. I
prefer the former only because I can't remember which bit it is <g>.
Frits van Bommel
2007-07-24 22:53:24 UTC
Permalink
Post by Walter Bright
Post by BCS
Reply to Walter,
Post by Walter Bright
c += 'a' - 'A'; // to lower case
this is safer and faster (Ihink)
c |= 0b0010_0000;
On modern processors, there is no speed difference between the two. I
prefer the former only because I can't remember which bit it is <g>.
Well, that's easy:
---
c |= 'a' ^ 'A';
---
:P

Of course, then you'd have to remember whether the bit should be 1 or 0...


And of course both methods will screw up for a lot of characters that
aren't latin letters.
BCS
2007-07-24 23:07:06 UTC
Permalink
Reply to Walter,
Post by Walter Bright
Post by BCS
Reply to Walter,
Post by Walter Bright
c += 'a' - 'A'; // to lower case
this is safer and faster (Ihink)
c |= 0b0010_0000;
On modern processors, there is no speed difference between the two. I
prefer the former only because I can't remember which bit it is <g>.
Odd, I use \dmd\html\d\ascii-table.html to rememeber
Walter Bright
2007-07-25 02:57:52 UTC
Permalink
Post by BCS
Odd, I use \dmd\html\d\ascii-table.html to rememeber
I wrote that because I was tired of googling for "ascii table" and then
getting one filled with popups.
Bruno Medeiros
2007-07-25 13:00:41 UTC
Permalink
Post by Walter Bright
The problem with explicit casts is that they are a brute force method,
and subvert static type checking. A well designed systems allows a
balance between implicit casting and strong type checking so that
explicit casts are rarely needed in properly written programs.
I agree, but on a side note, shouldn't D's cast() operator be used
exclusively to subvert *static* type checking?
(Since currently it's also used to check the runtime type of class,
instead of a separate construct like Java's 'instanceof', C#'s 'is', or
C++'s 'dynamic_cast')
--
Bruno Medeiros - MSc in CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Walter Bright
2007-07-25 17:35:45 UTC
Permalink
Post by Bruno Medeiros
I agree, but on a side note, shouldn't D's cast() operator be used
exclusively to subvert *static* type checking?
(Since currently it's also used to check the runtime type of class,
instead of a separate construct like Java's 'instanceof', C#'s 'is', or
C++'s 'dynamic_cast')
I could argue it either way.
Chris Nicholson-Sauls
2007-07-25 19:51:03 UTC
Permalink
Post by Walter Bright
Post by Bruno Medeiros
I agree, but on a side note, shouldn't D's cast() operator be used
exclusively to subvert *static* type checking?
(Since currently it's also used to check the runtime type of class,
instead of a separate construct like Java's 'instanceof', C#'s 'is',
or C++'s 'dynamic_cast')
I could argue it either way.
Some other interesting examples.

--- Ruby
obj.is_a? Class # Considers all ancestor classes
obj.instanceof? Class # Only considers immediate class
obj.class == Class # Same as above, naturally

--- PHP
is_a(obj, 'Class')


The terms 'is' and 'is a' seem to be everywhere.

(But I'm actually perfectly fine with the cast() style.)

-- Chris Nicholson-Sauls
Don Clugston
2007-07-23 09:18:47 UTC
Permalink
Post by Walter Bright
http://www.digitalmars.com/d/1.0/changelog.html
http://ftp.digitalmars.com/dmd.1.019.zip
http://www.digitalmars.com/d/changelog.html
http://ftp.digitalmars.com/dmd.2.003.zip
extern(System) works on 2.003, but on 1.019, it prints:
xxx.d(13): valid linkage identifiers are D, C, C++, Pascal, Windows
Walter Bright
2007-07-23 16:48:00 UTC
Permalink
Post by Don Clugston
xxx.d(13): valid linkage identifiers are D, C, C++, Pascal, Windows
Oh crud, looks like I didn't fold that one in right.
Christian Kamm
2007-07-23 11:34:07 UTC
Permalink
The extended compile time reflection opens the door for all kinds of cool
things! Here's an RTTI-Visitor, for instance.

It uses compile-time foreach to build a sequence of if-statements that check
the classinfo and call the matching method.

Regards,
Christian
-------------- next part --------------
A non-text attachment was scrubbed...
Name: dispatch.d
Type: text/x-java
Size: 1960 bytes
Desc: not available
Url : http://lists.puremagic.com/pipermail/digitalmars-d-announce/attachments/20070723/099cef60/attachment.java
Jarrett Billingsley
2007-07-23 11:55:59 UTC
Permalink
Post by Christian Kamm
The extended compile time reflection opens the door for all kinds of cool
things! Here's an RTTI-Visitor, for instance.
It uses compile-time foreach to build a sequence of if-statements that check
the classinfo and call the matching method.
Regards,
Christian
That looks like multimethods. :D
Craig Black
2007-07-23 15:29:40 UTC
Permalink
Post by Christian Kamm
The extended compile time reflection opens the door for all kinds of cool
things! Here's an RTTI-Visitor, for instance.
It uses compile-time foreach to build a sequence of if-statements that check
the classinfo and call the matching method.
Regards,
Christian
Cool, but it would be better to implement double dispatch than the Visitor
pattern. It is ultimately more efficient and more flexible.

-Craig
Christian Kamm
2007-07-23 16:08:47 UTC
Permalink
Post by Craig Black
Cool, but it would be better to implement double dispatch than the Visitor
pattern. It is ultimately more efficient and more flexible.
It is simple to implement multiple dispatch using the same method as for the
single dispatch example. The overhead is the same: two virtual function
calls and some ifs doing address comparisons.

Might get less efficient or more complicated if you want to call the closest
match instead of raising an error if there's no exact match.

Christian
Robert Fraser
2007-07-23 23:38:28 UTC
Permalink
Post by Christian Kamm
The extended compile time reflection opens the door for all kinds of cool
things! Here's an RTTI-Visitor, for instance.
It uses compile-time foreach to build a sequence of if-statements that check
the classinfo and call the matching method.
Regards,
Christian
// released into the public domain
import std.stdio;
class A
{}
class B : A
{}
class C : A
{}
class Dispatcher
{
void foo(A a)
{
writefln("A");
}
void foo(B b)
{
writefln("B");
}
mixin Dispatch!("foo");
}
class ExDispatcher : Dispatcher
{
alias Dispatcher.foo foo;
override void foo(B b)
{
writefln("B override");
}
void foo(C c)
{
writefln("C");
}
mixin Dispatch!("foo");
}
void main()
{
auto disp = new Dispatcher;
disp.dispatch(new A); // calls disp.foo(A)
disp.dispatch(new B); // calls disp.foo(B)
Dispatcher exdisp = new ExDispatcher;
exdisp.dispatch(new A); // calls disp.foo(A)
exdisp.dispatch(new B); // calls exdisp.foo(B)
exdisp.dispatch(new C); // calls exdisp.foo(C)
}
class MethodNotFoundException : Exception
{
this(string msg) { super(msg); }
}
template Dispatch(string fname)
{
mixin("alias typeof(" ~ fname ~ ") fsym;");
static if(is(fsym arg_types == function) && is(fsym return_type == return))
{
return_type dispatch(Object o, arg_types[1..$] params)
{
alias typeof(__traits(getVirtualFunctions, typeof(this), fname)) funcs;
foreach(i, func; funcs)
{
static if(is(func it_arg_types == function) && is(func it_return_type == return))
{
static assert(is(arg_types[1..$] == it_arg_types[1..$]) && is(return_type == it_return_type),
"Except for the first argument, the signature of all functions must be identical.");
static assert(is(it_arg_types[0] == class), "First argument must be a class type.");
if(it_arg_types[0].classinfo is o.classinfo)
return __traits(getVirtualFunctions, this, fname)[i](cast(it_arg_types[0]) o, params);
}
else
static assert(false, fname ~ " is not a function");
}
throw new MethodNotFoundException("No matching method '" ~ fname ~ "' found in " ~ this.classinfo.name ~ " for class " ~ o.classinfo.name);
}
}
else
static assert(false, fname ~ " is not a function");
}
Awesome! My first thought was generating hash functions for arbitrary structures, which would make using classes in AAs much easier.

But there's still a niche for runtime reflection!
Bastiaan Veelo
2007-07-23 15:12:08 UTC
Permalink
Congratulations!

With "signals and slots" and now traits it looks like D is ready for a
GUI toolkit to be written for it, complete with drag-and-drop GUI
builder á la Qt Designer[1].

I can't wait to see that happen :-)

Bastiaan.

[1] http://trolltech.com/products/qt/features/designer
Post by Walter Bright
http://www.digitalmars.com/d/1.0/changelog.html
http://ftp.digitalmars.com/dmd.1.019.zip
http://www.digitalmars.com/d/changelog.html
http://ftp.digitalmars.com/dmd.2.003.zip
Craig Black
2007-07-23 15:31:29 UTC
Permalink
Very nice Walter! Question about traits. I'm guessing allMembers returns
both functions and fields? Is there an isField or isFunction to
differentiate?

-Craig
Walter Bright
2007-07-23 16:51:57 UTC
Permalink
Post by Craig Black
Very nice Walter! Question about traits. I'm guessing allMembers returns
both functions and fields? Is there an isField or isFunction to
differentiate?
You can look at the types to see if they are data or functions. But
probably more traits need to be added - I thought I'd wait on that to
see just what was required, rather than throw in a lot of useless
geegaws. It's hard to predict in advance.
Jarrett Billingsley
2007-07-23 18:59:25 UTC
Permalink
"Walter Bright" <newshound1 at digitalmars.com> wrote in message
Post by Walter Bright
Post by Craig Black
Very nice Walter! Question about traits. I'm guessing allMembers
returns both functions and fields? Is there an isField or isFunction to
differentiate?
You can look at the types to see if they are data or functions. But
probably more traits need to be added - I thought I'd wait on that to see
just what was required, rather than throw in a lot of useless geegaws.
It's hard to predict in advance.
If you had

class A
{
void function() f;
void delegate() g;
void foo() {}
}

What would be f's type, g's type, and foo's type?
Walter Bright
2007-07-23 19:23:59 UTC
Permalink
Post by Jarrett Billingsley
If you had
class A
{
void function() f;
void delegate() g;
void foo() {}
}
What would be f's type, g's type, and foo's type?
f: pointer to function returning void
g: delegate returning void
foo: function returning void
Jarrett Billingsley
2007-07-23 21:00:47 UTC
Permalink
"Walter Bright" <newshound1 at digitalmars.com> wrote in message
Post by Walter Bright
f: pointer to function returning void
foo: function returning void
Ahh.. there's the distinction.
Carlos Santander
2007-07-23 20:06:01 UTC
Permalink
Post by Walter Bright
http://www.digitalmars.com/d/1.0/changelog.html
http://ftp.digitalmars.com/dmd.1.019.zip
http://www.digitalmars.com/d/changelog.html
http://ftp.digitalmars.com/dmd.2.003.zip
How can we check specific overloads with __traits? For example,

class A
{
abstract void foo();
int foo(int i) { return i; }
}

void main ()
{
auto isvirtual = __traits(isAbstractFunction, A.foo); // what is it?
}

BTW, the documentation for __traits has isVirtualFunction in the example for
isAbstractFunction.
--
Carlos Santander Bernal
Walter Bright
2007-07-23 23:51:47 UTC
Permalink
Post by Carlos Santander
Post by Walter Bright
http://www.digitalmars.com/d/1.0/changelog.html
http://ftp.digitalmars.com/dmd.1.019.zip
http://www.digitalmars.com/d/changelog.html
http://ftp.digitalmars.com/dmd.2.003.zip
How can we check specific overloads with __traits? For example,
class A
{
abstract void foo();
int foo(int i) { return i; }
}
void main ()
{
auto isvirtual = __traits(isAbstractFunction, A.foo); // what is it?
}
You'll need to split them apart with getVirtualFunctions, or cast the A.foo.
Post by Carlos Santander
BTW, the documentation for __traits has isVirtualFunction in the example
for isAbstractFunction.
Fixed.
Carlos Santander
2007-07-25 03:36:33 UTC
Permalink
Post by Walter Bright
Post by Carlos Santander
How can we check specific overloads with __traits? For example,
class A
{
abstract void foo();
int foo(int i) { return i; }
}
void main ()
{
auto isvirtual = __traits(isAbstractFunction, A.foo); // what is it?
}
You'll need to split them apart with getVirtualFunctions, or cast the A.foo.
As for getVirtualFunctions, I'm guessing abstract foo would not be virtual, and
the other one would. Am I right?

As for casting, cast A.foo to what?
--
Carlos Santander Bernal
Walter Bright
2007-07-25 04:29:24 UTC
Permalink
Post by Carlos Santander
Post by Walter Bright
Post by Carlos Santander
How can we check specific overloads with __traits? For example,
class A
{
abstract void foo();
int foo(int i) { return i; }
}
void main ()
{
auto isvirtual = __traits(isAbstractFunction, A.foo); // what is it?
}
You'll need to split them apart with getVirtualFunctions, or cast the A.foo.
As for getVirtualFunctions, I'm guessing abstract foo would not be
virtual, and the other one would. Am I right?
Abstractness is orthogonal to virtualness - in this case, they're still
virtual.
Post by Carlos Santander
As for casting, cast A.foo to what?
To the type signature of the particular overload you want.
Carlos Santander
2007-07-25 14:04:56 UTC
Permalink
Post by Walter Bright
Post by Carlos Santander
Post by Walter Bright
Post by Carlos Santander
How can we check specific overloads with __traits? For example,
class A
{
abstract void foo();
int foo(int i) { return i; }
}
void main ()
{
auto isvirtual = __traits(isAbstractFunction, A.foo); // what is it?
}
You'll need to split them apart with getVirtualFunctions, or cast the A.foo.
As for getVirtualFunctions, I'm guessing abstract foo would not be
virtual, and the other one would. Am I right?
Abstractness is orthogonal to virtualness - in this case, they're still
virtual.
Lost me here. If both of them are still virtual, how could I "split them apart
with getVirtualFunctions"?
Post by Walter Bright
Post by Carlos Santander
As for casting, cast A.foo to what?
To the type signature of the particular overload you want.
__traits(isAbstractFunction, cast (int delegate (int) ) A.foo) ?
--
Carlos Santander Bernal
Robert Fraser
2007-07-24 00:42:37 UTC
Permalink
Post by Walter Bright
http://www.digitalmars.com/d/1.0/changelog.html
http://ftp.digitalmars.com/dmd.1.019.zip
http://www.digitalmars.com/d/changelog.html
http://ftp.digitalmars.com/dmd.2.003.zip
BTW, is extern(System) mentioned in the docs (it's there under the list of available externs but it doesn't explain exactly what it does). I understand from the discussions before that it means extern(Windows) on Windows and extern(C) on Linux, but is there a generalized definition? What would it mean on Mac or Solaris? (extern(C), I'm guessing....)
Lutger
2007-07-24 13:43:13 UTC
Permalink
Wonderful, thank you very much!

On the subject of traits, would it be possible / helpful to have a trait
to enumerate all members of a module?
Lionello Lunesu
2007-07-26 17:32:08 UTC
Permalink
"Walter Bright" <newshound1 at digitalmars.com> wrote in message
Post by Walter Bright
http://www.digitalmars.com/d/1.0/changelog.html
http://ftp.digitalmars.com/dmd.1.019.zip
http://www.digitalmars.com/d/changelog.html
http://ftp.digitalmars.com/dmd.2.003.zip
Oww, I was quitely hoping that extern (System) would allow one to write

extern (System) char[] bzip2(char[]);

and that the compiler would then insert the necessary code to redirect
stdin/out to the strings...

Oh well.. Still a great release ; )

L.

Loading...