I’ve thought the same thing. I think what you’d need is for every variable to be a compound object, with a floating-point piece, and then a bunch of integer pieces, one for each type of physical quantity, with a value for what power that quantity is raised to. So for example, the quantity 1 meter would be stored as 1.00E00, 1, 0, 0, 0, 0 , for “1 meter[sup]1[/sup] second[sup]0[/sup] kilogram[sup]0[/sup] kelvin[sup]0[/sup] coulomb[sup]0[/sup]”. Addition would throw an error if the unit-block didn’t match, and multiplication or division would add or subtract the unit blocks as vectors. Purely mathematical functions like logs, exponentiation, and trig functions would fail if the unit block was nonzero. You’d have preset constants for all of the standard units, so somewhere there’d be something like “foot = 0.3048E00, 1, 0, 0, 0, 0” and “inch = 0.254E-01, 1, 0, 0, 0, 0”, which would let you type something like “height = 5foot + 11inch”.
Actually, this could probably be implemented as a library and header file in something like C++, though you’d still run the risk of the programmer ignoring the unit features and just sticking in old fashioned floats.
Except for the constants, almost every language has that facility in it’s function library or basic syntax. However, most languages are created for general, business oriented usage and don’t necessarily do it efficiently or conveniently. But as I write this post, I realize based on existing hardware, nothing is going to do it all that efficiently. The different components of a floating point object would have to be converted at run-time or whenever the value was changed (except in using the component parts of the internal floating point representation, which can be done in any language that doesn’t have the highly exalted ‘strong’ typing discussed previously). But the number of applications for which efficiency is still a deciding factor with modern hardware dwindle daily.
The strategy is sound. The problem, IMHO, is three-fold:
It’s memory intensive. Every object now needs to store a bunch of extra ints.
It’s slow. Every operation on an object needs to perform additional additions on the unit exponents.
The error-checking is solely at run-time.
The method I tried was similar in that I stored integer exponents of the base units, except that I used C++ template metaprogramming gymnastics to perform the unit checks. This means zero run time memory or perf overhead, and all the errors come out at compile time.
I didn’t succeed at the time, but I didn’t try all that hard (was just a hobby project). Also, I think I was too ambitious: what I really wanted was a truly general-purpose library that could just as easily work with km/h as m/s (not to mention mph). Maybe it’s time to revisit this in slightly simplified form…
Ok. By efficiently I meant with the least processing time physically capable on the particular platform. And language features usually don’t provide that. Am I missing some other point?
It’s been implemented by a few people. F# seems to have something from MSresearch, boost put something in C++ by their standard tactic of template metaprogramming abuse, someone made something for Haskell. No doubt there are fourteen thousand examples for perl on cpan.
Suppose I gave you two programs and asked you which was more efficient. Is your position that this matter is adequately settled by means of a stopwatch?
In terms of processing time, and the two programs provide the same output from the same input, yes. Also provided they exist in the same relative reference frame, or whatever, get the details about that from someone else.
Learning a programming language is similar – there are grammars and vocabulary. However, natural language is MUCH more complex.
However, there is something else – learning PROGRAMMING is much different from learning a PROGRAMMING LANGUAGE. Most people can, with some effort, learn how to write code in any language they please, but bad programmers can be bad programmers in any language, as has been mentioned. Programming has a lot of facets beyond telling a computer how to solve a problem, it also includes:
Making it so that other people can understand your code
Solving the problem in a way that doesn’t take a year
Writing code that’s easy to work with
Sometimes these goals are at odds with each other, and what takes priority depends on what you’re doing (though if you can’t make the code self explanatory for various reasons, a comment should be used).
Personally, I think REAL PROGRAMMING™ is much, much less about performance minutae (though it obviously can be and is important!) and much more about systems design. One in a Game Design term project, I essentially forced my team to redo the entire inner workings of how spells were made, and suddenly our content production sped up from “maybe one new ability every couple weeks” to “you want four new spells? That can be done by tomorrow morning.”
In my opinion, the syntax and rules of a language are just silly things that get in the way of more important things like seeing the project as a whole, and being aware of how other pieces are going to interact with each other. Obviously if you work at Microsoft or Google you’re going to be working on projects so large you’ll never get this kind of knowledge of the whole OS or search engine, but the mark of a good programmer (IMO again) is that they at least know what THEIR code affects, and how they can make the system work as painlessly and productively as possible.
It kind of seems like your question is assuming TriPolar is a rookie, but I’m pretty sure he understands the potential complexity of the performance profile of a solution.
I hadn’t seen that particular Boost library before–thanks for the reference. As expected, it’s zero overhead. My only complaint is that it’s almost too flexible, and thus ends up looking pretty complicated. I’ll have to give it a shot.
The F# stuff looks really cool as well, especially since it’s integrated into the compiler and IDE. Error messages and the like are therefore far more likely to be useful.