June 02, 2002
"Roland" <rv@ronetech.com> wrote in message news:3CF67636.F550087A@ronetech.com...
>
> > Although I consider c = f(z+(a==b)) quite a neat one liner.
>
> I agree, if
>
>     c = f(z+(a==b))
>
> is less readeable than
>
>     if (a==b)
>     {
>         c = f(z+1);
>     }
>     else
>     {
>         c = f(z);
>     }
>
> 100 lines are _more_ readeable than  500 lines.
>
> roland
>

The dependancy on the if returning 0 for false or
1 for true, then using that boolean value as if it
was an integer seems to me to pose a threat.
Most languages forbid this kind of construction
and I think for good reason.
Booleans are false or true. That D uses 0 and 1
to represent them is an implementation issue,
albeit a very standard one. I think code should
rely on implementation issues as least as possible.

And I do think that the long example was much more
readable that the short example. If there is a
very good reason to use such a construction
(performance perhaps), then by all means, use it.
Just don't use it just because it looks cool...


--
Stijn
OddesE_XYZ@hotmail.com
http://OddesE.cjb.net
_________________________________________________
Remove _XYZ from my address when replying by mail


June 02, 2002
"Sean L. Palmer" <seanpalmer@earthlink.net> wrote in message news:ad5omn$141s$1@digitaldaemon.com...
> The only drawback to this type of loop that I know of is that the count variable *must* be signed or iterating all the way to zero doesn't work.
>
> Oh, and it iterates backwards.  Sometimes the algorithm depends on going forward.
>
> Sean
>

Ah yes, if you try to iterate to zero with
an unsigned value, then it can never become
smaller than zero, so you never leave the
loop! I hadn't thought of that one...


--
Stijn
OddesE_XYZ@hotmail.com
http://OddesE.cjb.net
_________________________________________________
Remove _XYZ from my address when replying by mail



June 02, 2002
"OddesE" <OddesE_XYZ@hotmail.com> wrote in message news:adbqbv$1qo9$1@digitaldaemon.com...

> Booleans are false or true. That D uses 0 and 1
> to represent them is an implementation issue,
> albeit a very standard one. I think code should
> rely on implementation issues as least as possible.

It's not an implementation issue. The "bit" data type is not a boolean - it's a 1-bit unsigned integer, which can hold either 0 or 1. For convenience, true and false are mapped to equal 1 and 0, respectively... I think it was supposed to work this way. =)



June 02, 2002
And of coarse in most ASM set (true) has always been represented by 1 and
unset (false) has always been represented by 0.  So it makes sense to use
those values in the bit type flags.

"Pavel Minayev" <evilone@omen.ru> wrote in message news:adcg9a$2j0d$1@digitaldaemon.com...
> "OddesE" <OddesE_XYZ@hotmail.com> wrote in message news:adbqbv$1qo9$1@digitaldaemon.com...
>
> > Booleans are false or true. That D uses 0 and 1
> > to represent them is an implementation issue,
> > albeit a very standard one. I think code should
> > rely on implementation issues as least as possible.
>
> It's not an implementation issue. The "bit" data type is not a boolean - it's a 1-bit unsigned integer, which can hold either 0 or 1. For convenience, true and false are mapped to equal 1 and 0, respectively... I think it was supposed to work this way. =)
>
>
>


June 02, 2002
"OddesE" <OddesE_XYZ@hotmail.com> wrote in message news:adbqbv$1qo9$1@digitaldaemon.com...

> The dependancy on the if returning 0 for false or
> 1 for true, then using that boolean value as if it
> was an integer seems to me to pose a threat.
> Most languages forbid this kind of construction
> and I think for good reason.
> Booleans are false or true. That D uses 0 and 1
> to represent them is an implementation issue,
> albeit a very standard one. I think code should
> rely on implementation issues as least as possible.
>
> And I do think that the long example was much more
> readable that the short example. If there is a
> very good reason to use such a construction
> (performance perhaps), then by all means, use it.
> Just don't use it just because it looks cool...

Performance is usually an issue one should keep in mind.


I agree, the long one is more readable.  Sometimes that's a larger concern than performance.

For games programming, performance is critical.  Then again, portability is important also.

I think C's mistake is that it was a very general representation of the hardware *at the time C was invented*.  Todays machines are a different style of beast altogether, and a different style of programming is necessary to achieve top performance on today's CPU's.  For this we need access to modern day constructs such as parallel execution, which occurs in forms ranging from SIMD to multithreading.  D addresses many of those issues.

I believe the D spec already specifies the conversion from bool to bit; it's implicit in the conversion from int to bit.  Because on the D webpage it says:

Integer Promotions
The following types are implicitly converted to int:
	bit
	byte
	ubyte
	short
	ushort
	enum

Typedefs are converted to their underlying type.

 But it doesn't specify anything about how to convert actual values of one
type into values of the other type.  Personally I'd prefer that it *did* do
so;  then I'd be absolved of much of the tedium of dealing with porting
issues.  It turns that problem into a language implementation problem rather
than a machine incompatibility problem.  I *like* languages that make
guarantees about how things work in a machine.  If my program says convert
int to float and on this machine, there is no float unit, I want the
compiler to emulate it in software so that my program still works.

Luckily for me, machines don't change *all* that much and so, from year to year, there are certain standards that prosper.  IEEE floating point format, standard two's complement signed integers, and byte sizes of 8 and int sizes (in bytes) which are a power of 2.  But we can't rely on that.  However the language can specify conversion behavior for bit to int and int to bit. However it would have to know whether bit was a signed or unsigned quantity to do it properly.  Both are useful if you think about it:

bit select;
int a,b;
int which = cast(int)select^a + cast(int)!select^b;  // in fact the casts
are unnecessary they're only there to make explicit what's going on.

This is neat because a bit then expands to fill the available space.  For this to work however you need signed bits which expand to int -1 or (for 32 bit ints) 0xffffffff.  If bit 1 == int 1, it won't work at all (but multiply would).  I tend to think of bools as signed bits but that's just me.

I've seen one programming problem which would be neatly solved by a form of integer than replicated downwards, and in fact I believe this is how modern graphics coprocessors work;  the integers represent values to a specified resolution.  Essentially fixed point but the decimal point may be anywhere; depending on the registers and type of cpu it may be 0.0 .. 1.0 or 0.0 .. 255.0 or -128.9999999 to +127.0 or 0.0 to 0.25 or whatever.  Conversion then is based on where the implicit decimal points are.  The neat thing is the fractional part replicates infinitely into a larger fraction.

For instance let's treat a color RGB as unsigned fraction from 0.0 to 1.0. 0.0 == 0 and 1.0 == 255.  Then if we have a color let's say light gray or 0xaaaaaa.  Let's also say we want to paint it onto a bitmap that only has 4 bits of color for each R,G, and B.  The resulting pixel is 0xaaa.  So to convert each 4 bit pixel back to the original, we need something that converts to the original value 0xaaaaaa.

0xaa / ((2^8)-1) = 0xa / ((2^4)-1)
0xaa / 255 = 0xa / 15
0xaa = 0xa * 255 / 15

Anyway I believe basic types should be present which are guaranteed to behave in certain ways by the language spec, but that a machine should also expose any other custom types it possesses which may be governed by other rules of behavior.

Fixed point is a very common pattern in day-to-day programming, and it would be nice if it had some language support.  Emulation of fixed point is something that can be automated by the compiler; it's a very simple algorithm to construct fixed point math on any integer register set.  The compiler would know where the decimal point was for each type and could convert automatically very easily.  The multiplication and division are very solved problems even if the machine doesn't have larger intermediate registers.  Hell I remember when the CPU's didn't even have hardware multiply.  Do you think machines will come out that don't have hardware integer multiply?  Well they also aren't going to make machines that don't have larger intermediate registers for multiplication/division.  And even if they don't, many applications for fixed point only need the add and subtract to be fast and don't care about the final division being fast.

I can see it being used in a variety of fields;  computer graphics would
want binary fixed point and finance would want modulo 100 fixed point.  For
instance if I want to convert the color white to portion of a dollar (so I
can use my GeForce 3 to calculate my spreadsheet ;) it would need 0xff /
((2&8)-1) = 99 / (100-1).

It'd be nice if the compiler could manage the conversions for us.  I recently ported a game where fixed point math was used for the graphics calculations (it was a PS1 game) and it sucked.  Anything that automates this stuff with clean syntax and some hope of portability would be great. This may tie into specifying ranges for scalar types.  Range and precision are closely connected.

int24.8 somefraction = 4.0f;
int16.16 otherfraction = -0x1ad.ee3;
int32 intermediate = somefraction * otherfraction * 100;
extended temp = somefraction * otherfraction + 0.5f;
int32 result = temp * 100;
int0.4 percent = result / intermediate;

Yes I doubt the above syntax would work in practice.  But the concept is neat.  For it to work, it relies on the compiler's ability to convert safely from one type to another;  Right now though we live in an era of computing where we get no guarantees about converting between integral types let alone fixed point types.  I think the language should attempt to give the programmers some safety net within which the world is guaranteed to work a certain way.  If D someday ends up on some radically different hardware where this no longer works and emulation would be too slow, the software is likely to be out of date anyway and there are likely to be bigger porting issues to deal with.  The language can and should morph to the new architectures;  if it can't, someone will invent a new language and we'll repeat this process again.

Sean


June 03, 2002
"anderson" <anderson@firestar.com.au> wrote in message news:adcjol$2mjf$1@digitaldaemon.com...
> And of coarse in most ASM set (true) has always been represented by 1 and
> unset (false) has always been represented by 0.  So it makes sense to use
> those values in the bit type flags.
>


Ofcourse, just not as the expression/return value
for an if...

I know that

if (2)
   printf ('Hello World.');

Will print Hello World, and that

int i = 3 + (2 < 5);

Will assign 4 to i, but in my humble opinion
it is not something that is obviously clear, or
desirable for that matter. It is one of those
features of C often critisised. It has some
advantages, but also opens the door for errors.
most style guides and programming books advise
you to avoid such constructions.


--
Stijn
OddesE_XYZ@hotmail.com
http://OddesE.cjb.net
_________________________________________________
Remove _XYZ from my address when replying by mail



June 07, 2002
"OddesE" <OddesE_XYZ@hotmail.com> wrote in message news:adbqht$1r2f$1@digitaldaemon.com...

> "Sean L. Palmer" <seanpalmer@earthlink.net> wrote in message news:ad5omn$141s$1@digitaldaemon.com...
> > The only drawback to this type of loop that I know of is that the count variable *must* be signed or iterating all the way to zero doesn't work.
>
> Ah yes, if you try to iterate to zero with
> an unsigned value, then it can never become
> smaller than zero, so you never leave the
> loop! I hadn't thought of that one...

for (unsigned int i = container.size(); i>0; ) {
   --i;
   f(container[i]);
}

   Ah! And the braces are your friends. Never be so lazy that you miss to
use them.

Salutaciones,
                         JCAB



June 07, 2002
"Juan Carlos Arevalo Baeza" <jcab@roningames.com> wrote in message news:adqs8d$102t$1@digitaldaemon.com...

> for (unsigned int i = container.size(); i>0; ) {
>    --i;
>    f(container[i]);
> }
>
>    Ah! And the braces are your friends. Never be so lazy that you miss to
> use them.

Hm?

    for (uint i = container.length; i > 0; i--)
        f(container[i]);


June 07, 2002
"Pavel Minayev" <evilone@omen.ru> wrote in message news:adr122$15hu$1@digitaldaemon.com...

> "Juan Carlos Arevalo Baeza" <jcab@roningames.com> wrote in message news:adqs8d$102t$1@digitaldaemon.com...
>
> > for (unsigned int i = container.size(); i>0; ) {
> >    --i;
> >    f(container[i]);
> > }
>
>     for (uint i = container.length; i > 0; i--)
>         f(container[i]);
>

   Nope. That's equivalent to:

for (uint i = container.length; i > 0;) {
    f(container[i]);
    --i;
}

   Unless D differs from C++ in this regard, of course.

> >    Ah! And the braces are your friends. Never be so lazy that you miss
to
> > use them.
>
> Hm?

   I mean always, ALWAYS, use the braces. You're less likely to have (or
cause) problems that way. It's a recommendation. It's good advice.



June 07, 2002
"Juan Carlos Arevalo Baeza" <jcab@roningames.com> wrote in message news:adr3d2$180b$1@digitaldaemon.com...

> >     for (uint i = container.length; i > 0; i--)
> >         f(container[i]);
> >
>
>    Nope. That's equivalent to:
>
> for (uint i = container.length; i > 0;) {
>     f(container[i]);
>     --i;
> }

Okay, then:

     for (uint i = container.length; i-- > 0;)
         f(container[i]);

>    I mean always, ALWAYS, use the braces. You're less likely to have (or
> cause) problems that way. It's a recommendation. It's good advice.

I've already stated my position on this subject a lot of times. =)