const String IP_ADDRESS = "http://192.168.1.103:8088/";
const String HOME_EXPECTED = IP_ADDRESS + "index.html";
This code returns unexpected error message from Dart Editor.
An expression of type 'num' was expected
Why? and how can I fix it?
I tried using 'final', 'final const', and static. but failed :(
Update
http://dartbug.com/15853 says
So String+ String is a constant (and has been for a while). String* int isn't and is not expected to be.
I created http://dartbug.com/22408
Original
In Dart it is very limited how you can construct consts. The + operator on String isn't whitelisted for const creation.
Try this instead:
const String HOME_EXPECTED = "${IP_ADDRESS}index.html";
or
final String HOME_EXPECTED = IP_ADDRESS + "index.html";
if const is not required.
I don't know this language 'Dart' but looking at the language description, it is not possible to achieve what you want using 'const':
Use const for variables that you want to be compile-time constants. If the const variable is at the class level, mark it static const. (Instance variables can’t be const.) Where you declare the variable, set the value to a compile-time constant such as a literal, a const variable, or the result of an arithmetic operation on constant numbers.
Your second variable declaration is not a literal, a simple assignment to another const variable, nor is it an arithmetic operation of such.
Source: https://www.dartlang.org/docs/dart-up-and-running/ch02.html
Related
I was going through the Dart language tour and noticed that they have the statement
final constantSet = const {
'fluorine'
};
and I was just wondering whether there is a programmatic difference in declaring the constant as final or whether that has a specific purpose. I can see that we can place const either before or after the variable declaration, is this the same thing, considering that when you declare a variable as final it is only able to be initialized once anyway?
There is a difference.
A final constantSet = const {'fluorine'}; declares a non-constant final variable bound to a value which happens to be a compile-time constant.
A const constantSet = const {'fluorine'}; declares a constant variable bound to a compile-time constant value (and the second const can be omitted).
The latter allows you to use constantSet in constant expressions, so const [costantSet] is only valid with the latter declaration.
That also means that declaring a variable as const is something you cannot take back. Changing a const declaration to final may break code using the const variable in constant expression. That's a reason for not making every variable const, just because it can be. You might not want to promise that it stays constant forever.
I want to send a Function as a parameter to an annotation like this:
#JsonKey(fromJson: ...)
final int variable;
where fromJson is a Function, but it gives me this error:
Arguments of a constant creation must be constant expressions.
what is the solution? any help would be greatly appreciated.
You didn't write what you wanted for ..., and that's the part that causes the problem.
The argument to the fromJson parameter must be a compile-time constant value because annotations must be constant.
The only constant function values are top-level or static functions, so you need to declare the function type want, let's say as static:
class MyClass {
#JsonKey(fromJson: _variableFromJson)
final int variable;
static int _variableFromjson(dynamic json) => ...;
...
}
You can't write the function in-line as (fromJson: (json) => ...) because function expressions are not compile-time constant.
As per this excellent explanation const expressions in Dart are "deeply immutable" meaning that nothing inside can ever change and therefore the entire expression will always denote the same thing. This is useful for the compiler, because it can generate the entire object graph once and re-use it every time such an expression occurs, and it is useful for the programmer to know that such an expression –even when it is deeply nested– still follows value-semantics and won't do anything behind my back.
I am using those optimizations by the compiler to use a well-structured object model (instead of hand-encoding it in a bit-vector, for example) and still get good performance. Since we can get some of those benefits also by "explicitly hashing" some values by making them run-time constants with the static final idiom, the question arises which of the two is good style to use in which case?
Consider the following example:
enum ShaftType { RING, SUN, CARRIER }
class Shaft {
final int index;
final ShaftType type;
Shaft(this.type, this.index) {
assert((type == ShaftType.CARRIER) == (index == null));
}
const Shaft.CARRIER()
: type = ShaftType.CARRIER,
index = null;
const Shaft.RING(this.index) : type = ShaftType.RING;
const Shaft.SUN(this.index) : type = ShaftType.SUN;
}
class GearPath {
final Shaft input, output, fixed;
GearPath({this.input, this.output, this.fixed}) {
// input and output must be set
assert(null != input && null != output);
// fixed shaft can't be anything else
assert(fixed != input && fixed != output);
}
GearPath.carrierToFirstRingFixedSun(int i)
: input = const Shaft.CARRIER(),
output = const Shaft.RING(0),
fixed = new Shaft.SUN(i) {}
static final singleFixedSunUp = new GearPath(
input: const Shaft.CARRIER(),
output: const Shaft.RING(0),
fixed: const Shaft.SUN(0),
);
static final directDrive = new GearPath(
input: const Shaft.CARRIER(),
output: const Shaft.CARRIER(),
fixed: null,
);
// ...
}
I can't make the main Shaft(..) and GearStage(..) constructors const because I want to check some constraints, but I can provide special-case constructors (such as Shaft.SUN(int i), Shaft.CARRIER()) which comply with those constraints (at least partially) by design and provide users legible shorthands for those common values.
On the other hand, when a const constructor would have no arguments, then I can as well write it as a static final member as I have done with GearStage.directDrive. If all users refer to this static member instead of re-creating the value again, we also get the benefit of sharing memory and fast comparisons (reference to same object). I can't declare the right-side of this definition as const, because it uses the non-const constructor, but developers can see from context that this is indeed a constant value and not global mutable singleton hidden in the static field. So for practical purposes it should be just as good as a const constructor, right?
Since I haven't found this described any where as a best practice my question is simply if this is indeed a good way to combine and trade-off between const constructors and static final "named value instances"?
Finally, I wonder if there is a way to declare GearPath.carrierToFirstRingFixedSun(int i) also as a const constructor? Currently I can't because const Shaft.SUN(i) complains about i not being constant.
(full code of example)
Dart 2 will allow you to have asserts in const constructors (as long as your condition can be computed as a const expression).
Then you will be able to write:
GearPath({this.input, this.output, this.fixed})
: // input and output must be set
assert(null != input && null != output),
// fixed shaft can't be anything else
assert(!identical(fixed, input) && !identical(fixed, output));
Until then, you can't have both validation and const expressions.
You still will not be able to make GearPath.carrierToFirstRingFixedSun(int i) const because it i is not constant. The const Shaft.SUN(i) is still not a valid const expression, even if i is the parameter of a const constructor. Each const Constructor(...) invocation must still create exactly one object, even if it occurs in the initializer list of another const constructor.
As a rule-of-thumb, you should consider whether exposing a value as const instead of final is something you want to commit to. When you make the variable const, it means that someone else can use the value in another const expression, and then changing the variable to final will be a breaking change. Saying that something is const is a commitment that you should choose deliberately, not just because you can. So, consider the use-cases of your variable. If you don't see it being used in other const expressions, then just make it final.
The analyzer doesn't say final var is illegal.
but dart2js says final var is illegal
What is correct? Why?
The keyword var means mutable variable with explicit dynamic type specifier.
The explicit type specifier means that this is not possible specify another type in declaration.
The keyword final means val or immutable variable with unspecified type, with implicit dynamic type.
The implicit type specifier means that this is possible specify other type in declaration.
More precisely variable that declared as val are the value and variable at once.
It are variable because has the runtime storage.
But it are also immutable value that can be retrieved from associated storage just once and can be used anywhere.
Now consider the following code:
final var foo;
This is the same as the following pseudo code:
immutable mutable dynamic foo;
Of course, this will not work.
That is probably a bug in the analyzer. final and var are mutual exclusive.
One of the following is allowed
final identifier
final type identifier
const identifier
const type identifier
var identifier
type identifier
Dart Programming Language Specification (1.2) - Variables
finalConstVarOrType:
final type?
| const type?
| varOrType
;
varOrType:
var
| type
;
EDIT
My DartEditor (Dart VM version: 1.3.0-dev.3.2 (Mon Mar 10 10:15:05 2014) on "linux_x64") shows an error for final var xxx (Members can not be declared to be both 'final' and 'var'.)
I have a global variable:
const double myvar = 5.1;
Now, I'm converting this to read these values from Lua.
However, I can't simply do:
const double myvar = lua_tonumber(L,1);
Since main() must first execute to start the Lua intepreter etc., but if I declare myvar afterwards, it will not be global.
Is there any way to do achieve a global const variable which takes it's value from Lua?
The subtle ramifications of const can be fully understood only by language lawyers, but the basic idea of a const variable is that its value is specified at compile time. Lua values cannot be created until there is a Lua interpreter, which requires calling lua_open(), which cannot be done until run time. So no, there is no (safe, sane) way of having a const variable whose value is determined by Lua.
You can violate constness like this:
*(double*) & myvar = lua_tonumber(L,1);
but it's a -very- bad practice.
Edit: Instead of declaring const variables you can do this:
static double myvar() {
// todo: check if global L is init
return lua_tonumber(L,1);
}
or even this:
static double myvar() {
return 1.15;
}