www.digitalmars.com         C & C++   DMDScript  

D - Cast syntax

reply "Angus Graham" <agraham_d agraham.ca> writes:
This was discussed in another thread, but I think it's worth it's own topic:

I beg you Walter _please_ don't use C style casts.  I hate them with a
purple passion.

Bad enough that parentheses are used for function declarations and function
calls and order of operations and for and while and macros and whatever
else, but using them for casts too is awful.

How many times have you had to look at

myfunc((*(qFlag*)((*it)->m_bar)) & (~(flag | flag2) & (int)not_flag));

What does this thing mean?  Are these parentheses even balanced?  I'm not
going to count them to find out because it hurts my brain.

Now let's use C++ style casting:

myfunc((*static_cast<qFlag*>((*it)->bar)) & (~(flag|flag2) &
static_cast<int>(not_flag)))

We didn't save any parentheses, but it's a little easier to see where they
are.  I can see one or two I didn't need now.

What if we simply use <> instead of () for static casts?

myfunc((*<qFlag*>((*it)->bar)) & (~(flag|flag2) & <int>(not_flag)))

There isn't that nice?  Those casts just pop right out at you.  The way they
should.

Let me suggest an even better notation:

myfunc((*static_cast:qFlag*<(*it)->bar> & (~(flag|flag2) &
static_cast:int<not_flag>))

Oh yeah, that's the ticket.  Now, you are not used to looking at that, but
compare it to the first one.  I would much rather look at this than that all
day.

Angus Graham
Aug 20 2001
next sibling parent reply "Walter" <walter digitalmars.com> writes:
Using the < and > as brackets causes too much grief in the scanner (as is >>
a nested bracket or a right shift?). I had tried:

    cast(int)(expression)

but it just didn't look too good.

Angus Graham wrote in message <9lsnhn$1k3t$1 digitaldaemon.com>...
This was discussed in another thread, but I think it's worth it's own
topic:
I beg you Walter _please_ don't use C style casts.  I hate them with a
purple passion.

Bad enough that parentheses are used for function declarations and function
calls and order of operations and for and while and macros and whatever
else, but using them for casts too is awful.

How many times have you had to look at

myfunc((*(qFlag*)((*it)->m_bar)) & (~(flag | flag2) & (int)not_flag));

What does this thing mean?  Are these parentheses even balanced?  I'm not
going to count them to find out because it hurts my brain.

Now let's use C++ style casting:

myfunc((*static_cast<qFlag*>((*it)->bar)) & (~(flag|flag2) &
static_cast<int>(not_flag)))

We didn't save any parentheses, but it's a little easier to see where they
are.  I can see one or two I didn't need now.

What if we simply use <> instead of () for static casts?

myfunc((*<qFlag*>((*it)->bar)) & (~(flag|flag2) & <int>(not_flag)))

There isn't that nice?  Those casts just pop right out at you.  The way
they
should.

Let me suggest an even better notation:

myfunc((*static_cast:qFlag*<(*it)->bar> & (~(flag|flag2) &
static_cast:int<not_flag>))

Oh yeah, that's the ticket.  Now, you are not used to looking at that, but
compare it to the first one.  I would much rather look at this than that
all
day.

Angus Graham
Aug 20 2001
next sibling parent Axel Kittenberger <anshil gmx.net> writes:
Walter wrote:

 Using the < and > as brackets causes too much grief in the scanner (as is
 a nested bracket or a right shift?). I had tried:
i /*a and is this i divided by content of a? or is it a comment? In case of nested typecases you'll just have to add a space between > > just one has to add a space between / and content of *. BTW: Do nested typecasts in pratice make any sense? If in some obscure cases they do, how often does that occur?
Aug 20 2001
prev sibling parent reply "Angus Graham" <agraham_d agraham.ca> writes:
"Walter" <walter digitalmars.com> wrote

 Using the < and > as brackets causes too much grief in the scanner (as is

 a nested bracket or a right shift?).
It's a right shift. If the person meant to close two casts, well now it doesn't compile and issues the error message "cast not closed, perhaps you used >> when you should have used > >?" Where's the grief in that?
 I had tried:

     cast(int)(expression)

 but it just didn't look too good.
My eyes! My eyes! Aaaaa... Angus Graham
Aug 19 2001
parent reply Dan Hursh <hursh infonet.isl.net> writes:
Angus Graham wrote:
 
 "Walter" <walter digitalmars.com> wrote
 
 Using the < and > as brackets causes too much grief in the scanner (as is

 a nested bracket or a right shift?).
It's a right shift. If the person meant to close two casts, well now it doesn't compile and issues the error message "cast not closed, perhaps you used >> when you should have used > >?" Where's the grief in that?
 I had tried:

     cast(int)(expression)

 but it just didn't look too good.
My eyes! My eyes! Aaaaa... Angus Graham
I the cast of the '<' '>' usage, I bet Walter is trying not to make the error that was made in C++ with templates. (Or he may not be as uncomfortable with the C cast syntax as you.) Shift operators aside, there are cases in C++ where use have to use the template keyword in a function call (Yes, I said cll.) because the compiler doesn't look far enough ahead to see that you are using a template function and not doing a less than operation on a function pointer. Thing.get<int>(); // I believe this bombs Thing.template get<int>(); // Bjarne smiles upon us. This was the first time I really admitted to myself that C++ really isn't the end-all-be-all compiled language. In a feeble attempt to maintain C compatibility they created a nasty grammar bug. The fix sucks. I suspect that by maintaining C compatibility, Walter can be sure he isn't introducing a similar bug. There are worse things than the C casting syntax. No really, there is. :-) Dan
Aug 25 2001
next sibling parent Eric Gerlach <egerlach canada.com> writes:
 Angus Graham wrote:
 
 	Thing.get<int>();		// I believe this bombs
 	Thing.template get<int>();	// Bjarne smiles upon us.
Gad! Make the evil go away! I hate that bug, though to be honest, I've only ever run into it with the GCC compiler. The Microsoft one and the MIPSpro compiler seem to handle it fine. Now, admittedly I've used GCC way more than the other two, but maybe there is a way to handle it, it just isn't pretty.
Aug 26 2001
prev sibling parent reply "Walter" <walter digitalmars.com> writes:
Dan Hursh wrote in message <3B889511.AE07677A infonet.isl.net>...
 I suspect that by maintaining C compatibility, Walter can be sure he
isn't introducing a similar bug.  There are worse things than the C
casting syntax.  No really, there is. :-)
foo(bar); Is it a declaration? Is it a function call? Is it a constructor call? Gak.
Aug 28 2001
parent "Serge K" <skarebo programmer.net> writes:
"Walter" <walter digitalmars.com> wrote in message
news:9mged4$1d4p$1 digitaldaemon.com...
 foo(bar);

 Is it a declaration? Is it a function call? Is it a constructor call? Gak.
I guess, from C++ point of view - it's a function call, even if it's used as a type cast. int a = int(b); In this case, 'int' is a type and a bunch of functions to convert different types to 'int':
Aug 28 2001
prev sibling parent reply "Anthony Steele" <asteele nospam.iafrica.com> writes:
"Angus Graham" <agraham_d agraham.ca> wrote in message
news:9lsnhn$1k3t$1 digitaldaemon.com...
 This was discussed in another thread, but I think it's worth it's own
topic:
 I beg you Walter _please_ don't use C style casts.  I hate them with a
 purple passion.
Having used Delphi/Pascal for a while (I'm on Java now thanks), The notion of having special syntax for casts seems a bit silly to me. What is a cast to integer but a function that takes one parameter, and returns an integer (ok, so the code generated is different, but semantically it's the same thing) - why do you need new syntax for that? That's what works for me: myInt := int(myFloat);
How many times have you had to look at
myfunc((*(qFlag*)((*it)->m_bar)) & (~(flag | flag2) & (int)not_flag));
That's partly a language thing and partly a lazy programmer thing - I'd prefer to see somemeaningfullvarname = (~(flag | flag2) & (int)not_flag); thebarparam = *(qFlag*)((*it)->m_bar); myfunc(thebarparam & somemeaningfullvarname);
Sep 09 2001
parent reply Axel Kittenberger <axel dtone.org> writes:
Anthony Steele wrote:

 
 "Angus Graham" <agraham_d agraham.ca> wrote in message
 news:9lsnhn$1k3t$1 digitaldaemon.com...
 This was discussed in another thread, but I think it's worth it's own
topic:
 I beg you Walter _please_ don't use C style casts.  I hate them with a
 purple passion.
Having used Delphi/Pascal for a while (I'm on Java now thanks), The notion of having special syntax for casts seems a bit silly to me. What is a cast to integer but a function that takes one parameter, and returns an integer (ok, so the code generated is different, but semantically it's the same thing) - why do you need new syntax for that? That's what works for me: myInt := int(myFloat);
How many times have you had to look at
myfunc((*(qFlag*)((*it)->m_bar)) & (~(flag | flag2) & (int)not_flag));
That's partly a language thing and partly a lazy programmer thing - I'd prefer to see somemeaningfullvarname = (~(flag | flag2) & (int)not_flag); thebarparam = *(qFlag*)((*it)->m_bar); myfunc(thebarparam & somemeaningfullvarname);
The main argument against Pascal style typecasts is, they are difficult to parse, at least I guess they're acutallly very difficult to parse for a c like language. Pascal is easier since it types are simpler defined. Try following C code with it: a = (char **) b; a = char**(b); // Looks also very ugly doesn't it? According to a function paradigm I guess following would in example be proper: cast<char**>(a); Well looking at the parser, and because we're lazy types you can cut the cast keyword away. People are lazy, and that's why they don't want to write BEGIN and END all the time, in my eyes that's all behind it :/ In my presonal view the discussions from Pascal vs. C where battled on another field than where the programmers hearts lay, they discussed for typedefs again type, structs agains records, include against uses, etc. but I think in reality it was only the feeling for '{' vs 'BEGIN'. :o) - Axel
Sep 09 2001
next sibling parent reply "Anthony Steele" <asteele nospam.iafrica.com> writes:
"Axel Kittenberger" <axel dtone.org> wrote in message
news:9ngav1$1jfn$1 digitaldaemon.com...

 The main argument against Pascal style typecasts is, they are difficult to
 parse, at least I guess they're acutallly very difficult to parse for a c
 like language. Pascal is easier since it types are simpler defined.

 Try following C code with it:
 a = (char **) b;
 a = char**(b); // Looks also very ugly doesn't it?
Trying that in Delphi .. right, it can't be compiled in Delphi without a type alias, which IMHO is no great loss to Delphi, ie type pchar = ^char; ppchar = ^pchar; procedure Test; var p: pointer; i: integer; begin i := 42; p := ppchar(i); // this works // this doesn't compile p := ^pchar(i); end;
 According to a function paradigm I guess following would in example be
 proper:
 cast<char**>(a);
Maybe, but the (type)(expr) syntax just strikes me as very wrong. Why not cast(type, expr), ie a = cast(char**, b);
 In my presonal view the discussions from Pascal vs. C where battled on
 another field than where the programmers hearts lay, they discussed for
 typedefs again type, structs agains records, include against uses, etc.
but
 I think in reality it was only the feeling for '{' vs 'BEGIN'. :o)
Maybe so. { } instead of BEGIN & END is one of the things that I'm liking about Java :)
Sep 09 2001
parent reply Russ Lewis <russ deming-os.org> writes:
Anthony Steele wrote:

 Maybe, but the (type)(expr) syntax just strikes me as very wrong. Why not
 cast(type, expr), ie

 a = cast(char**, b);
Nice...I like that syntax because it gives a clear division between the type, the data, and the surrounding code. How about using the property paradigm? a = b.cast(char**); Comments?
Sep 11 2001
next sibling parent reply James Gilbert <jgrg sanger.ac.uk> writes:
Russ Lewis wrote:
 
 Anthony Steele wrote:
 
 Maybe, but the (type)(expr) syntax just strikes me as very wrong. Why not
 cast(type, expr), ie

 a = cast(char**, b);
Nice...I like that syntax because it gives a clear division between the type, the data, and the surrounding code. How about using the property a = b.cast(char**); Comments?
I like treating cast just like a function. Once novice programmers have learned about functions, they don't have to learn about cast syntax, only what the cast function does. You might also consider: cast(expr, type) This feels more natural to me; "cast this to that". Maybe the type is too important to be hidden after a big expression? Not sure about the property paradigm. Looks as if you could overwrite the cast function in your class.
Sep 12 2001
parent Russ Lewis <russ deming-os.org> writes:
James Gilbert wrote:

 You might also consider:

   cast(expr, type)

 This feels more natural to me; "cast this to that".
 Maybe the type is too important to be hidden after
 a big expression?
At first I liked your idea...but yeah, now that you mention it, I do prefer to have the type in front as it seems more readable.
 Not sure about the property paradigm.  Looks as if
 you could overwrite the cast function in your class.
That might not be altogether a bad thing....dunno
Sep 12 2001
prev sibling parent reply Charles Hixson <charleshixsn earthlink.net> writes:
Russ Lewis wrote:

 Anthony Steele wrote:
 
 
Maybe, but the (type)(expr) syntax just strikes me as very wrong. Why not
cast(type, expr), ie

a = cast(char**, b);
Nice...I like that syntax because it gives a clear division between the type, the data, and the surrounding code. How about using the property paradigm? a = b.cast(char**); Comments?
Nice. But in that case, how about: a = b.cast("char**"); This would allow the function parsing rule to remain unaltered. Of course it would appear to open one up to: char [] castVar; castVar = "char [5]" if flag then castVar = "int"; a = b.cast(castVar); And that might not be so nice.
Sep 12 2001
next sibling parent reply Axel Kittenberger <axel dtone.org> writes:
 Nice.  But in that case, how about:
 a = b.cast("char**");
Well to allow easy parsing how about bracing types always in <> squares. a = b.cast<char**>; if you want to cast to char ** or a = b.cast(a); if you want to cast to the typeof a. same paradigm for sizeof, sizeof<char> ---> 1 sizeof(a) ---> if a is an int32 in example 4 if prefix or postfix is better gets more obvious if you've longer chains suppose you want to cast a to an int, but over an extra step over typeof b. a = 3 + a.cast(b).cast<int>; or a = 3 + cast<in> cast(b) a; okay it isn't obvios as both have +es and -es.... - Axel
Sep 12 2001
parent Russ Lewis <russ deming-os.org> writes:
Axel Kittenberger wrote:

 if you want to cast to char **
 or
 a = b.cast(a);

 if you want to cast to the typeof a.

 same paradigm for sizeof,
 sizeof<char>    ---> 1
 sizeof(a)       ---> if a is an int32 in example 4
(cheer) Good thinking, I *like*!
Sep 12 2001
prev sibling parent "Anthony Steele" <asteele nospam.iafrica.com> writes:
"Charles Hixson" <charleshixsn earthlink.net> wrote in message
news:3B9F6EF2.2030709 earthlink.net...


 This would allow the function parsing rule to remain unaltered.
   Of course it would appear to open one up to:

 char [] castVar;
 castVar = "char [5]"
 if flag then castVar = "int";
 a = b.cast(castVar);

 And that might not be so nice.
or in the functional style a = cast(castVar, b); Sorry, a few weeks of Java have convinced me even more that while OO is the most powerfull tool in a programmer's toolbox, it shouldn't be the only one :) Sometimes a function is all you need. I haven't read the spec too closely, but I would have thought that this is impossible - as the cast is actually done at compile time for simple types - it's just a compile-time check, since all pointers are untyped in machine code. The type param might have to be a type (syntactically checkable at compile time), not a string (can't make sure that it's a valid type at all). Using a string can cause confusion - if you cast a var to a type unknown at compile-time, where do you put the value returned? In the example above, what is a sensible type for 'a', given that castVar can contain any type, even one that the program's user just entered. I could see this possibly working somehow for 'soft' casts on COM interfaces or class types & using a base type to recieve the value, but not with primitive types like char** ; Axel Kittenberger wrote
 a = b.cast(a);
 if you want to cast to the typeof a. - same paradigm as for sizeof,
or a = cast(b, a); Nice. Would make coding simple & flexible and like sizeof, it can be resolved at compile time. I hope Walter sees that!
Sep 12 2001
prev sibling parent "Walter" <walter digitalmars.com> writes:
Axel Kittenberger wrote in message <9ngav1$1jfn$1 digitaldaemon.com>...
Well looking at the parser, and because we're lazy types you can cut the
cast keyword away. People are lazy, and that's why they don't want to write
BEGIN and END all the time, in my eyes that's all behind it :/
In my presonal view the discussions from Pascal vs. C where battled on
another field than where the programmers hearts lay, they discussed for
typedefs again type, structs agains records, include against uses, etc. but
I think in reality it was only the feeling for '{' vs 'BEGIN'. :o)
My trouble with Pascal is I found that I spent half my programming time trying to get around some language prohibition. C was a breath of fresh air for that. I don't want to lose that in D.
Sep 22 2001