|
If you only knew how my mind worked
|
|
|
|
|
My mind doesn't work.
So I would use Python.
|
|
|
|
|
Ron Beyer wrote: works the same way that #define does in c++ to replace types.
In C++ one would use typedef for this purpose. Using #define is just wrong
Within you lies the power for good - Use it!
|
|
|
|
|
My point exactly, typedef would be a legitimate use of it, #define works because of precompiler even if it makes the programmers head hurt.
|
|
|
|
|
It fails totally though for type safety.
using AgeInYears = System.Int32;
using AgeInDays = System.Int32;
...
AgeInYears yearAge = 10;
AgeInDays dayAge = 3650;
var myAge = yearAge + dayAge;
(A better example may involve standard units of measure: inches, miles, meters, temperatures, etc.)
The system should at least prevent naive attempts to assign to incorrect types.
Ideally, the system should be able to perform conversions where possible.
Smalltalk and C++ both offer enough flexibility. In C#, a struct could be declared, but I think you'd struggle to make it semantically sound.
"If you don't fail at least 90 percent of the time, you're not aiming high enough."
Alan Kay.
|
|
|
|
|
You should rewrite it that way.
namespace TestApp1
{
using AgeInYears = System.Int32;
class Program
{
static void Main(string[] args)
{
AgeInYears myAge = 10;
AgeInYears timeUntilOldAge = 10;
AgeInYears oldAge = myAge + timeUntilOldAge;
}
}
}
So you are forever young.
The good thing about pessimism is, that you are always either right or pleasently surprised.
|
|
|
|
|
isn't that akin to a typedef?
David
|
|
|
|
|
Kinda, as I said in a different reply, typedef has valid uses (defining a BOOL for example) that actually creates a new type and can be universal, whereas "using" alias is more like a #define replacement in a single file.
|
|
|
|
|
I suppose typedefs get type checked at compile time and #defines do not. Is that correct? so maybe the typedef equivalent is the safer way to go?
David
|
|
|
|
|
#define will be checked at compile time just like typedefs because the preprocessor will run through and replace all instances of the #define name with the value before compiling.
If typedef had an equivalent c# construct that would certainly be the better way to go, but it doesn't. So the only real way to redefine types as a different name is to use the "using" or to create your own value type that derives from the equivalent type.
|
|
|
|
|
Obviously, you don't mean just time: otherwise, timespan and datetime in c# would do the trick.
For phisical entities (mass, distance, acceleration, ....) there is a C++ library in BOOST:
http://www.boost.org/doc/libs/1_41_0/doc/html/boost_units/Dimensional_Analysis.html[^]
I remember reading an article (which I can't find) that used this to implement classes that allow you to do the following:
Acceleration g = new Acceleration(9.88); Mass m = new mass(25); Force f = m * g;
Is that what you're looking for?
Update: Found it. http://www.boostpro.com/mplbook/metafunctions.html[^].
Pablo.
"Accident: An inevitable occurrence due to the action of immutable natural laws." (Ambrose Bierce, circa 1899).
"You are to act in the light of experience as guided by intelligence" (Rex Stout, "In the Best Families", 1950).
modified 18-Dec-13 9:45am.
|
|
|
|
|
Pablo Aliskevicius wrote: I remember reading an article (which I can't find) that used this to implement classes that allow you to do the following:
Yes, I was just reading about that. There's a CP article that also does some pre-processing for C# that allows units of measure to be specified, very similar to F#.
And yes, that's one piece of the puzzle I'm working on.
Marc
|
|
|
|
|
Yes. F# supports units of measurement[^].
For example, you can do this:
[<Measure>] type years
let myAge = 32<years>
The downside this is strictly language support, and not runtime support. Units are lost at runtime, but it's still pretty handy.
|
|
|
|
|
Phil Martin wrote: Units are lost at runtime
Which is unfortunate because I'd possibly like to be able to reflect on the unit of measure. But it's an interesting avenue to explore. Thanks!
Marc
|
|
|
|
|
Yeah, it is unfortunate.
In the engineering applications I write, I've created a ScalaryQuantity and a VectorQuantity class. They are just the usual numeric structures which support all the normal arithmetic, but supports keeping track of units, and converting units when necessary.
There's a big run time overhead involved, but for me it is worth it because it has helped me catch many errors far earlier in the process of developing new calculations.
|
|
|
|
|
Annoyingly, int is a sealed type in C#, or all you would have to do is provide the implicit cast operators:
class AgeInYears : int
{
public static implicit operator AgeInYears(int i)
{
return (AgeInYears)i;
}
public static implicit operator int(AgeInYears a)
{
return (int)a;
}
} But...what is an age plus an age? It's not really anything useful if you think about it. What you should be thinking of here is an Age plus a Timespan equals a DateTime, but then an Age can't really be assigned an integer value unless it already has a Datetime component - perhaps it is relative to the time at which the Age object is instantiated?
And don't forget that an Age is not a constant value: it will vary as the application runs...
|
|
|
|
|
OriginalGriff wrote: Annoyingly, int is a sealed type in C#, or all you would have to do is provide the implicit cast operators:
Exactly!
OriginalGriff wrote: And don't forget that an Age is not a constant value: it will vary as the application runs...
I know. It was a contrived example.
OriginalGriff wrote: But...what is an age plus an age?
Yeah, this stuff gets one to really think about the meaning of things.
Marc
|
|
|
|
|
You could argue that AgeInYears should be implemented something like this:
class AgeInYears
{
public AgeInYears(DateTime birthdate)
{
_Birthdate = birthdate;
}
private DateTime _Birthdate;
public int Years
{
get
{
return (DataTime.Now - _Birthdate).Days / 365;
}
}
}
Software Zen: delete this;
|
|
|
|
|
|
Yeah, this reeked of prior art but I couldn't be arsed to go looking just to comment on a casual question.
Software Zen: delete this;
|
|
|
|
|
A long time ago, at a defense contractor far, far defunct...
The Ada programming language provided a semblance of semantic typing. You could create an 'Age' type that was a subtype of integer. I'm sure the computer scientists would scoff at Ada's limitations, but it does somewhat fit the bill. I don't know the modern language definition (I used it back in the 80's), so it might be more capable now.
Software Zen: delete this;
|
|
|
|
|
Gary Wheeler wrote: The Ada programming language provided a semblance of semantic typing.
Ah, it does indeed. I've been reading the Ada type stuff - very slick. It's a pity these constructs aren't in other languages. I wonder why not - it seems like it would really help bullet proof code. Then again, like anything else, I bet it can be horribly abused as well.
Marc
|
|
|
|
|
Stroustrup has written somewhere on implementing SI measures in C++ using user-defined literals and simple classes. That would work well, but should really be part of the standard library.
"If you don't fail at least 90 percent of the time, you're not aiming high enough."
Alan Kay.
|
|
|
|
|
Rob Grainger wrote: "If you don't fail at least 90 percent of the time, you're not aiming high enough."
Well. Try this with your employer!
(it's a joke)
|
|
|
|
|
I still feel that would be an improvement on some of the folk whose footsteps I'm following (see various entries in The Wierd and The Wonderful) - at least I'd succeed 10% of the time
"If you don't fail at least 90 percent of the time, you're not aiming high enough."
Alan Kay.
|
|
|
|