Make initializers and extension methods constant
I do not know whether there is any downside or difficulty connected to implementing this feature, but it would be really helpful, in our opinion, if we can construct instances of fling units as constants such as 0.seconds or milli.grams(15) etc. right now they are not constant (and can therefore not be used as default values in function definitions, etc.)
Comments (4)
-
repo owner -
repo owner It is time for an update based on a little research I’ve done:
The biggest difficulty is that a
const
object cannot perform any work during initialization, and cannot be the result of any function calls (i.e. the result of any function call cannot beconst
). This affects three parts of Fling Units:- Extensions: These are methods by definition. Because method calls cannot return
const
values, I cannot find a way to make something like5.minutes
beconst
. - Prefixes: I have implemented these as method calls. Therefore, they suffer from the same problem. This affects things like
meters(5)
ormilli.grams(3)
. I also cannot find a way to make these beconst
. - Measurement Constructors: In order to remain in a “known” state, I do some work when you initialize a Measurement. In short, I convert from whatever unit you are using to the SI base unit. Since this involves a method call to the
Interpreter
, the constructor cannot be madeconst
.
So, extensions and prefixes are out.
Really, the only way to make a Measurement
const
(that I know of) is to accept an unconverted measurement amount in the constructor. I am able to do this already for some quantities, namely0
andinfinity/-infinity
, since there is no need to convert those values. In order to allow this for all other quantities, I could instead perform the conversions on-demand. This is doable, but requires quite a bit of refactoring. In the end, you would be able to createconst
instances of Measurement classes like this:var myDistance = const Distance(30.0, inches);
I know it’s not as pretty as what the extension methods allow, but it would get us close to what we want. I say “close” because the prefixes would not work here, since they are methods, so this would still not work:
var myDistance = const Distance(30.0, milli.meters); // still refuses to compile!
For that, I would need to turn all of the prefixes into classes with
const
constructors. That would allow something like this:var myDistance = const Distance(30.0, Milli(meters));
One last thing I could do would be to define constants for all of the possible combinations of prefixes and units (or at least the most common ones - not sure how often people use
milli.feet
in their measurements), getting us closest to what you might expect:var myDistance = const Distance(30.0, millimeters);
OK, now the conclusion:
As I mentioned, doing something like this would be a significant endeavor. I might run into other problems I have not foreseen partway through, as well. I also don’t like the partial solutions since they deviate from the standard (e.g. having to use
Milli(meters)
ormillimeters
rather than the standardmilli.meters
). Even then, testing and maintaining the combinatorial explosion of constants becomes more difficult and increases the footprint of the library. In short, I’d prefer to skip this feature for now.If you want to support default values in methods, I might suggest something like the following:
void doIt([Distance? myDistance]) { myDistance = myDistance ?? 50.milli.meters; // do stuff with myDistance }
For constructors, you can do something similar, but you won’t be able to make your constructor
const
:class DoIt { final Distance myDistance; DoIt([Distance? myDistance]) : myDistance = myDistance ?? 50.milli.meters; }
Dart is still evolving, and some things that were not possible before are becoming possible now (e.g. extensions!). It’s also possible that I have missed a new Dart feature that solves this problem, or at least makes it much easier to solve. If you have ideas, please let me know. I’ll keep an eye out as well, and I’ll keep this as a high priority for version 3.0
- Extensions: These are methods by definition. Because method calls cannot return
-
repo owner - changed component to Framework
- marked as enhancement
-
repo owner - changed status to on hold
May be an option with a redesign or new Dart features
- Log in to comment
Thanks Luca!
Believe it or not, I did try to keep things as
const
-able as I could. Unfortunately, not everything is currently set up that way, as you noticed. I can say that Fling currently supportsconst
versions of the zero-valued measurements, e.g.:Infinite and negative infinite values (via
infinite()
andnegativeInfinite()
) are alsoconst
, though I suspect those are less useful.I suspect there are several reasons I was forced to go non-const for the other initializers. Taking a quick look, the first thing that breaks are the
Precision
values: I wanted their initializers to check for negative numbers and throw, but that is a runtime check and thus not allowed inconst
constructors.I do understand your desire for a simple,
const
capable value, so I’ll see what I can work out. Stay tuned.