D - typedef behavior question
- Scott Pigman (5/5) Jan 19 2003 Is the error on line 2 a bug or a feature?
- Alix Pexton (6/15) Jan 19 2003 Feature!
- Scott Pigman (12/31) Jan 19 2003 i understand that typedef really means "Define a new type", and i see th...
- Mike Wynn (5/9) Jan 19 2003 if you don't want a new type you can use alias
- Scott Pigman (14/27) Jan 19 2003 i want a new type. i don't want an alias. i support the current model
- Mike Wynn (25/37) Jan 19 2003 why do you draw a distiction between a literal and a variable.
- Scott Pigman (38/70) Jan 19 2003 Mike -
- Mike Wynn (51/106) Jan 19 2003 I still don't understand why you are using a typedef and not an alias
- Scott Pigman (33/42) Jan 20 2003 basically my position is this:
- Mike Wynn (66/100) Jan 20 2003 I partially agree, I was quoteing the D spec, which defines how a typede...
- Ilya Minkov (14/76) Jan 21 2003 Hm. Why don't you overload assignment operator so that when you assign a...
- Scott Pigman (3/5) Jan 21 2003 i'll look into it when i get a chance. let me know what you discover.
- Ilya Minkov (17/24) Jan 20 2003 If you want to create a type you need to be proficient in typing :>
- Walter (4/5) Jan 20 2003 It is, and you're right. Overloading on typedefs is one of the major poi...
- Ilya Minkov (8/17) Jan 20 2003 But then this means that Scott simply has to overload assignment for
Is the error on line 2 a bug or a feature? typedef double money; money m = 0.0; // ERROR "cannot implictly convert double to money" m = (money)0.0; // Correct -scott
Jan 19 2003
Feature! In D typedef makes a completly new type, unlike in C/C++. C-style typedefs can be created using alias instead. Alix Pexton... Webmaster, www.thedjournal.com Scott Pigman wrote:Is the error on line 2 a bug or a feature? typedef double money; money m = 0.0; // ERROR "cannot implictly convert double to money" m = (money)0.0; // Correct -scott
Jan 19 2003
i understand that typedef really means "Define a new type", and i see that having to cast a numeric constant to the type of the typedef is locically consistant and follows what happens with class heirachies, but i don't like it. if i said "double d = 0", i wouldn't have any problem, even though "0" is and int, not a double. who would want to always type "double d = (double)0.0"? so why have to cast 0.0 to type "money", when it really doesn't add any information or safety so far as i can see. when it comes to assigning variables to one another or passing them to functions i see the benefit, but i would expect to be able to assign numeric contants to my typedefed variable without having to cast. -scott On Sun, 19 Jan 2003 15:26:01 +0000, Alix Pexton wrote:Feature! In D typedef makes a completly new type, unlike in C/C++. C-style typedefs can be created using alias instead. Alix Pexton... Webmaster, www.thedjournal.com Scott Pigman wrote:Is the error on line 2 a bug or a feature? typedef double money; money m = 0.0; // ERROR "cannot implictly convert double to money" m = (money)0.0; // Correct -scott
Jan 19 2003
"Scott Pigman" <scottpig1 attbi.com> wrote in message news:b0effv$2rqk$1 digitaldaemon.com...Is the error on line 2 a bug or a feature? typedef double money; money m = 0.0; // ERROR "cannot implictly convert double to money" m = (money)0.0; // Correctif you don't want a new type you can use alias alias double money; money m = 0.0;
Jan 19 2003
i want a new type. i don't want an alias. i support the current model 100% when it comes to assigning variables to each other or for parameter types. but i think it's a pain and not terribly useful to have to cast a literal number (not a variable) to the type of my typedef. it seems to be an excersise in typing - what else could be your intention for that number other than to be assigned to that lvalue? what does it really mean if you cast a number to the wrong type? why does it make the program any better/clearer/safer to require a cast in this case? i guess i would propose that numbers are automatically considered to be of any type derived from their actual type, or of any type derived from a type they can be implicitly cast to. i.e. "0" would be a valid rvalue for any lval typedef'd from int or float. -s On Sun, 19 Jan 2003 16:52:36 +0000, Mike Wynn wrote:"Scott Pigman" <scottpig1 attbi.com> wrote in message news:b0effv$2rqk$1 digitaldaemon.com...Is the error on line 2 a bug or a feature? typedef double money; money m = 0.0; // ERROR "cannot implictly convert double to money" m = (money)0.0; // Correctif you don't want a new type you can use alias alias double money; money m = 0.0;
Jan 19 2003
"Scott Pigman" <scottpig1 attbi.com> wrote in message news:b0eop9$302q$1 digitaldaemon.com...i want a new type. i don't want an alias. i support the current model 100% when it comes to assigning variables to each other or for parameter types. but i think it's a pain and not terribly useful to have to cast a literal number (not a variable) to the type of my typedef. it seems to be an excersise in typing - what else could be your intention for that number other than to be assigned to that lvalue? what does it really mean if you cast a number to the wrong type? why does it make the program any better/clearer/safer to require a cast in this case?why do you draw a distiction between a literal and a variable. why should literals be less type safe than variables. and you've said you want a typedef and not an alias, but the behaviour you have mentioned is what you get from an alias rather than a typedef; can you expain why you need a typedef.i guess i would propose that numbers are automatically considered to be of any type derived from their actual type, or of any type derived from a type they can be implicitly cast to. i.e. "0" would be a valid rvalue for any lval typedef'd from int or float.it depends on what your new type is, does 'typedef int myint;' mean that myint is a specialised form of 'int' (thus supports less values) or that myint is an extension to 'int' (thus supports a greater range). or either ? as it stands conceptually 'typedef int myint;' is the former, you can always assign a myint to an int because it is a specialised form typedef int foo; const foo a = cast(foo)2; int b = a; the cast is required because not all int's are foo's; but all foo's are ints the fact that there is no int that is not a foo is not the point, becuase conceptually there does exists an int that is not a foo. in the D doc's you have A typedef can be implicitly converted to its underlying type, but going the other way requires an explicit conversion. what is missing is the ability to write 'foo.cast(int)' or tell the compiler that an implicit cast foo->int exists and it should use that.
Jan 19 2003
Mike - i'm not convinced yet. i think you're correct in a theoretical sense, but in a practical sense, i don't see the benefit of having to be so explicit with literals. anyway, comments are embedded within. -scott On Sun, 19 Jan 2003 19:24:37 +0000, Mike Wynn wrote:why do you draw a distiction between a literal and a variable. why should literals be less type safe than variables. and you've said you want a typedef and not an alias, but the behaviour you have mentioned is what you get from an alias rather than a typedef; can you expain why you need a typedef.i draw a distinction because i see typedefs as a means of clarifying and enforcing programmer intent. but i don't think it helps the programmer's intent any to force him or her to cast a literal to a typdef. i think the intent of somebody writing "money m = 1000" is pretty clear and doesn't need casts to clutter it up. but something like printMyIntVal( getYourIntVal() ) // probably an error... does benefit from checking the types. but i can't see how forcing printMyIntValue( (MyIntVal)1000 ) over printMyIntValue( 1000 ) benefits anybody. can you show me a bug introduced by using money m = 0.0; instead of money m = (money)0; ???but they *can't* support more or less values with anything i see in the doc - they're still ints underneath it all. they're not new classes which could restrict or extend the possible range of values. the only extra functionality a typedef type can have over a regular type is the default initializer -- which isn't at issue here.i guess i would propose that numbers are automatically considered to be of any type derived from their actual type, or of any type derived from a type they can be implicitly cast to. i.e. "0" would be a valid rvalue for any lval typedef'd from int or float.it depends on what your new type is, does 'typedef int myint;' mean that myint is a specialised form of 'int' (thus supports less values) or that myint is an extension to 'int' (thus supports a greater range). or either ?as it stands conceptually 'typedef int myint;' is the former, you can always assign a myint to an int because it is a specialised form typedef int foo; const foo a = cast(foo)2; int b = a; the cast is required because not all int's are foo's;what literal integer value is illegal to assign to foo? and if there is one, you couldn't cast it to anything that was legal, could you?but all foo's are ints the fact that there is no int that is not a foo is not the point, becuase conceptually there does exists an int that is not a foo.conceptually, maybe - but practically?in the D doc's you have A typedef can be implicitly converted to its underlying type, but going the other way requires an explicit conversion. what is missing is the ability to write 'foo.cast(int)' or tell the compiler that an implicit cast foo->int exists and it should use that.that would help, and i could possibly go along with it for implicit conversions between myInt and myOtherInt, but i still think literals deserver to be a special case, will lead to nothing but unintended errors if they aren't, and won't lead to any unintended errors (i think ;-) if they are. -scott
Jan 19 2003
"Scott Pigman" <scottpig1 attbi.com> wrote in message news:b0f11t$37h$1 digitaldaemon.com...Mike - i'm not convinced yet. i think you're correct in a theoretical sense, but in a practical sense, i don't see the benefit of having to be so explicit with literals. anyway, comments are embedded within.I still don't understand why you are using a typedef and not an alias ('alias' is almost directly equivilent to C 'typedef') typedef in D creaetes a theoretical new type.On Sun, 19 Jan 2003 19:24:37 +0000, Mike Wynn wrote:youwhy do you draw a distiction between a literal and a variable. why should literals be less type safe than variables. and you've said you want a typedef and not an alias, but the behaviouryouhave mentioned is what you get from an alias rather than a typedef; canbut that's exactly what is does, you want money to be a new type, that is realy a double; 1000 is an int, is that realy what the programmer wanted assign to the variable the compiler is not sure, so you have to tell is that yes, you realy do want to assign the int,float, double value to the money type.expain why you need a typedef.i draw a distinction because i see typedefs as a means of clarifying and enforcing programmer intent. but i don't think it helps the programmer's intent any to force him or her to cast a literal to a typdef. i think the intent of somebody writing "money m = 1000" is pretty clear and doesn't need casts to clutter it up. but something likeprintMyIntVal( getYourIntVal() ) // probably an error... does benefit from checking the types. but i can't see how forcing printMyIntValue( (MyIntVal)1000 ) over printMyIntValue( 1000 ) benefits anybody. can you show me a bug introduced by using money m = 0.0; instead of money m = (money)0;no, but just because that code does not introduce a bug, does not mean that its wrong/right. I use numeric typedef rarely, I don't see how typedef double money benifits the code in any way I think I've only ever used the eqiv of typedef uint UID; when I need a unique ID field for some comms (Delphi not D) but never found it that useful its only use was warning me that I should take care with the operations I was performing. and in your example you have to put `money m = cast(money)0;` // "C" casts i.e. `(type)var` should be banned, they cause problems to the parser because unlike C the D compiler can not tell if // (id) is a typecast or not because the type 'id' can be declared after the statement. if you just put `money m = 0;` you get an error, which alerts you to check that 0 is realy a valid value for m.ofi guess i would propose that numbers are automatically considered to bevalues)any type derived from their actual type, or of any type derived from a type they can be implicitly cast to. i.e. "0" would be a valid rvalue for any lval typedef'd from int or float.it depends on what your new type is, does 'typedef int myint;' mean that myint is a specialised form of 'int' (thus supports lessdocor that myint is an extension to 'int' (thus supports a greater range). or either ?but they *can't* support more or less values with anything i see in the- they're still ints underneath it all. they're not new classes whichcouldrestrict or extend the possible range of values. the only extra functionality a typedef type can have over a regular type is the default initializer -- which isn't at issue here.whether they can or can not support a greater or lesser range of values in reality is not relevant a typedef is a concept, you have created a new type, and the rules of that new type are all values of the new type are valid values of the underlying type NOT all values of the underlying type are valid values of the new typebecuasebut all foo's are ints the fact that there is no int that is not a foo is not the point,write in asm or C them, if you dont like the constucts of a programming language that has such rules.conceptually there does exists an int that is not a foo.conceptually, maybe - but practically?thein the D doc's you have A typedef can be implicitly converted to its underlying type, but goingcompilerother way requires an explicit conversion. what is missing is the ability to write 'foo.cast(int)' or tell theif you look at it right you will see it is you that should bend and not the spoon ! (even if the spoon is imperfect) creating special cases leads to more special cases and in the end leads to confusion.that an implicit cast foo->int exists and it should use that.that would help, and i could possibly go along with it for implicit conversions between myInt and myOtherInt, but i still think literals deserver to be a special case, will lead to nothing but unintended errors if they aren't, and won't lead to any unintended errors (i think ;-) if they are.
Jan 19 2003
basically my position is this: i can't imagine anyone ever saying, "gee, thank goodness the compiler forced me to write 'myFloat mf = (myFloat)0.0' because that really saved me from getting into trouble later on". on the other hand, i can see lots of people saying, "Dammnit, i forgot to cast 0.0 to myFloat when i initialized my variable, arrggghhh, now where the hell was that..." it won't be a big error surely, and not difficult to fix, but i don't see the point of forcing the programmer to have to do that. i can see that it is indeed more conceptually pure to force the cast -- and you can work out the syntax of the cast yourselves, right now i don't care -- but i don't see any practical advantage to slavishly following the most conceptually pure paradigm in this instance.I still don't understand why you are using a typedef and not an alias ('alias' is almost directly equivilent to C 'typedef')yes, i'm quite sure i want typedef, not alias. i want D-style typedef for all the other things it does for us, even if i really must cast literals. in fact, i'm not convinced i would even want to see alias in the final language, seems to me like it would hide errors.I use numeric typedef rarely, I don't see how typedef double money benifits the code in any wayI have used, and intend to continue using, numeric typedefs. in C, they help to me keep track of my intentions. in D they'd enforce those intentions. the example of "typedef double money" was a simplistic, contrived example, the kind usually used for discussions like this. a simplistic, contrived example of how that would help me is: tyedef double money; typedef double velocity; void setVehicleVelocity(velocity v){...} money getAccountBalance(){...} setVehicleVelocity( getAccountBalance() ) // Error in D, legal in Cif you look at it right you will see it is you that should bend and not the spoon ! (even if the spoon is imperfect) creating special cases leads to more special cases and in the end leads to confusion.i never claimed to be uri geller ;-) i think we'll just have to agree to disagree. Even if i convince nobody about this (which seems the most likely outcome ;-), i still think D looks to be a *very* promising language, and would love to make a living using it someday, superfluous literal castings and all. regards, Scott
Jan 20 2003
"Scott Pigman" <scottpig1 attbi.com> wrote in message news:b0i46g$1u2v$1 digitaldaemon.com...basically my position is this: i can't imagine anyone ever saying, "gee, thank goodness the compiler forced me to write 'myFloat mf = (myFloat)0.0' because that really saved me from getting into trouble later on". on the other hand, i can see lots of people saying, "Dammnit, i forgot to cast 0.0 to myFloat when i initialized my variable, arrggghhh, now where the hell was that..." it won't be a big error surely, and not difficult to fix, but i don't see the point of forcing the programmer to have to do that. i can see that it is indeed more conceptually pure to force the cast -- and you can work out the syntax of the cast yourselves, right now i don't care -- but i don't see any practical advantage to slavishly following the most conceptually pure paradigm in this instance.I partially agree, I was quoteing the D spec, which defines how a typedef works, and I dislike any special cases if it works for a foo, it should work for a foo; literal or variable. the more I think about it the more I come to the conclusion that numeric typedefs should be the other way around typedef int foo; all int's are foo's not all foo's are ints so you have to cast foo's to int's (now literals don't need casts). however that's a bit backwards it's like allowing you to declare a class that is a super class to Object without being a super class to anything that sub classes Object!I find alias very useful alias int delegate ( int, int ) myCallback; class foo { int cbfunc( int a, int b ) { return a+b; } } int func( myCallBack cb, int i ) { return cb( i ); } foo myfoo = new foo(); int i = func( &myfoo.cbfunc ); if you typedef, then you have to cast; adding the cast makes the code error prone, if you change the params then the compiler will not warn you because you have forced the type with a cast. if there was a way to declare a method in the class def as being of a type that is a typedef of its actual type then I would be more (but not totally) in favor of ditching alias. (again reversing the typedef rule solves this problem)I still don't understand why you are using a typedef and not an alias ('alias' is almost directly equivilent to C 'typedef')yes, i'm quite sure i want typedef, not alias. i want D-style typedef for all the other things it does for us, even if i really must cast literals. in fact, i'm not convinced i would even want to see alias in the final language, seems to me like it would hide errors.I use numeric typedef rarely, I don't see how typedef double money benifits the code in any wayI have used, and intend to continue using, numeric typedefs. in C, they help to me keep track of my intentions. in D they'd enforce those intentions. the example of "typedef double money" was a simplistic, contrived example, the kind usually used for discussions like this. a simplistic, contrived example of how that would help me is:tyedef double money; typedef double velocity; void setVehicleVelocity(velocity v){...} money getAccountBalance(){...} setVehicleVelocity( getAccountBalance() ) // Error in D, legal in Chowever velocity getVehicleVelocity(); money calcInterestOnAccountBalance( double percent ){...} cash = calcInterestOnAccountBalance( getVehicleVelocity() ); // is legal in D (all velocitys are doubles) // which is one reason I think the rule should be reversed (literals being the other) and I hate special cases my one conclusions lead me to (most likely up the garden path and lost in the woods) to think the following should exist `struct name : type;` // same behaviour as typedef has now. all 'name' are 'type', cast needed to get from type to name typedef type name; // opposite behaviour name is now a conceptual super class of type. all type are name, cast need to get from name to type; with a few more changes, you could have long as a modified typedef of int (all ints are longs) and even create a 128 bit number, or bignumber that was a typedef of long (all longs are valid bigger numbers) [too radical, ow well] it would suit both our requirements if typedef was a just little looser, typedef int foo; typedef int bar; int->foo (implicit) foo->int (implicit) int->bar (implicit) bar->int (implicit) foo<->bar (explicit) typedef bar morebar; would require a cast to assign to/from int; and as I said earlier I loath casts, I would instead prefer a compiler generated conv func that only allows a typedef of the underlying type, or underlying type, to be used without warning/error. bar b = bar( 1 ); // not cast(bar)1; foo a = foo( b ); if something changed, i.e. `typedef float bar` you'd now get a warning/error can't make a foo from a bar (float)i think we'll just have to agree to disagree. Even if i convince nobody about this (which seems the most likely outcome ;-), i still think D looks to be a *very* promising language, and would love to make a living using it someday, superfluous literal castings and all.I'm sure Walter will be please to hear that, not wanting to be too cynical but it seems the only way to make a living programming these days if in VB monkey to program in it companies aren't interested. lets end on a good note :) murthy's laws of technology, "if you make a system fool proof, only a fool would want to use it"
Jan 20 2003
Scott Pigman wrote:basically my position is this: i can't imagine anyone ever saying, "gee, thank goodness the compiler forced me to write 'myFloat mf = (myFloat)0.0' because that really saved me from getting into trouble later on". on the other hand, i can see lots of people saying, "Dammnit, i forgot to cast 0.0 to myFloat when i initialized my variable, arrggghhh, now where the hell was that..." it won't be a big error surely, and not difficult to fix, but i don't see the point of forcing the programmer to have to do that. i can see that it is indeed more conceptually pure to force the cast -- and you can work out the syntax of the cast yourselves, right now i don't care -- but i don't see any practical advantage to slavishly following the most conceptually pure paradigm in this instance.Hm. Why don't you overload assignment operator so that when you assign a "float" or a "double" to "MyFloat", automatic conversion is done, cast implicitly? Either it is a legal assignment, which makes sense, or it is prohibited and by circumventing it with a cast you *always* make yourself a bad favor? You will thus make sure it is legal to assign a float to these types, but you won't be able to assign "money" to a "velocity". A good style would be then to get rid of underlying types as soon as possible, and store everything as correct typedef-ed types. BTW, i'll check whether it works like i expect it to. If it's still possible to assign a money var to velocity or vice versa after the assignment has been overloaded for their common underlying type, that'd actually be a design flaw.I still don't understand why you are using a typedef and not an alias ('alias' is almost directly equivilent to C 'typedef')yes, i'm quite sure i want typedef, not alias. i want D-style typedef for all the other things it does for us, even if i really must cast literals. in fact, i'm not convinced i would even want to see alias in the final language, seems to me like it would hide errors.I use numeric typedef rarely, I don't see how typedef double money benifits the code in any wayI have used, and intend to continue using, numeric typedefs. in C, they help to me keep track of my intentions. in D they'd enforce those intentions. the example of "typedef double money" was a simplistic, contrived example, the kind usually used for discussions like this. a simplistic, contrived example of how that would help me is: tyedef double money; typedef double velocity; void setVehicleVelocity(velocity v){...} money getAccountBalance(){...} setVehicleVelocity( getAccountBalance() ) // Error in D, legal in Cif you look at it right you will see it is you that should bend and not the spoon ! (even if the spoon is imperfect) creating special cases leads to more special cases and in the end leads to confusion.i never claimed to be uri geller ;-) i think we'll just have to agree to disagree. Even if i convince nobody about this (which seems the most likely outcome ;-), i still think D looks to be a *very* promising language, and would love to make a living using it someday, superfluous literal castings and all. regards, Scott
Jan 21 2003
On Tue, 21 Jan 2003 19:51:50 +0100, Ilya Minkov wrote:Hm. Why don't you overload assignment operator so that when you assign a "float" or a "double" to "MyFloat", automatic conversion is done, casti'll look into it when i get a chance. let me know what you discover. -sp
Jan 21 2003
Scott Pigman wrote:Mike - i'm not convinced yet. i think you're correct in a theoretical sense, but in a practical sense, i don't see the benefit of having to be so explicit with literals. anyway, comments are embedded within. -scottIf you want to create a type you need to be proficient in typing :> (pun not originally mine) I really think that casting constants has no purpose, because it doesn't get a "think again" effect as with variables and especially expressions, and it might lead to the effect that the programmer would be typing these casts without further thinking, even on expressions, which are most evil. Let's see. If it was a struct, you could write a method that would allow you to read the type safely. And make requiered conversions. This is useful, for example, do define a fixedpoint type. It is built out of an integer, but represents data in a "shifted" manner, so you can not assign an integer to it directly. You write an assignment method then, which makes a shift. You can also write one for the floats, as they can be converted into fixedpoint. Say, is operator overloading possible on typedef-s? IMO it should. -i.
Jan 20 2003
"Ilya Minkov" <midiclub 8ung.at> wrote in message news:b0h1eb$15pl$1 digitaldaemon.com...Say, is operator overloading possible on typedef-s? IMO it should.It is, and you're right. Overloading on typedefs is one of the major points of it.
Jan 20 2003
Walter wrote:"Ilya Minkov" <midiclub 8ung.at> wrote in message news:b0h1eb$15pl$1 digitaldaemon.com...But then this means that Scott simply has to overload assignment for typedef "money". And that it doesn't make a difference whether one tries to assign a constant or a variable or an expression, it shouldn't be allowed on a typedef, reminding: "don't forget to overload assignment, possibly making some changes to data to make a type work correctly!" --"don't forget to call free..." :>Say, is operator overloading possible on typedef-s? IMO it should.It is, and you're right. Overloading on typedefs is one of the major points of it.
Jan 20 2003