-1

I understand that, in Dart, primitives are passed by value and Objects are passed by reference.
So, I expected that

void test(String phrase) {
    const _phrase = phrase;
}

would result in error, but

void test(int amount) {
    const _amount = amount;
}

wouldn't.

However, both of them throws the same compile-time error: Const variables must be initialized with a constant value.

Is this some not implemented feature or there's a reason behind not accepting function arguments in const variables initialization?

Teodoro
  • 1,194
  • 8
  • 22
  • 2
    FYI, in Dart, [*everything* is an object](https://stackoverflow.com/a/64953576/179715). [All arguments are passed by value](https://stackoverflow.com/q/25170094/) (but the value of an object is a reference to it). – jamesdlin Nov 28 '20 at 00:17

2 Answers2

2

I believe the answer is that constants are fixed at compile time rather than run time so function arguments cannot be passed to them as the function only gets executed at runtime.

See also here for example https://stackoverflow.com/a/58877374

A final modifier instead of const would work however.

By the way a String is also a primitive I think. See here https://stackoverflow.com/a/58568542

Pjotr Gainullin
  • 948
  • 1
  • 9
  • 16
  • Dart does not have "primitive types" like, fx, Java. All Dart values are objects. – lrn Nov 30 '20 at 12:36
  • @lrn you are right, I'm not sure what the right term is but what I was referring to is the assignment behaviour which for e.g. int and String would assign the value but for other objects would assign a reference to the other object. To illustrate in DartPad: https://gist.github.com/pgainullin/0ce9d7652217b36416484526fe532192 – Pjotr Gainullin Dec 01 '20 at 08:15
  • 1
    That behavior only matters, and is only visible, for *mutable* objects. If an object is immutable, it doesn't matter whether you copy it or just copy a reference to it (as long as you don't start comparing addresses or object identity). Numbers are immutable, so are strings. The `Complex` object is not, and you change its state without changing its identity, which is why you can *see* that you are only assigning a reference to `bComplex`. You can't tell with the numbers. The Dart language treats all objects the same, it's always references that you assign. Implementations cheat when they can. – lrn Dec 01 '20 at 15:13
2

Dart constant variables must be initialized with compile-time constant expressions. A compile-time constant expression must always have the same value—precisely one value per source location.

Dart doesn't have "constant values" as such. It has constant expressions, which are known to evaluate to precisely one value, and for which it's possible to know this value at compile-time. That allows the compiler to canonicalize those constants values, so different constant expressions evaluating to constant objects with the same state are canonicalized to be the same object.

Your amount variable is not a compile-time constant expression. It can have different values at different times (because it's a function parameter and people might call the function with different arguments), so it cannot be a constant expression.

And therefore it cannot be used to initialize a constant variable, because constant variables can only have one value.

void test(int amount) {
  const _amount = amount;
  const list = [_amount]; // <- MUST ALWAYS HAVE SAME VALUE
}

In short: Dart constant variables must be initialized with a compile-time constant expression. A constant expression must always have the same value. This is the fundamental rule about Dart constant expressions which most other restrictions are derived from. (For example, a constant variable being used is a constant expression, so it must always be bound to the same value, which is why it must be initialized with a constant expression.)

lrn
  • 64,680
  • 7
  • 105
  • 121