Open icatalud opened 5 years ago
So symbol id;
would introduce an identifier id
bound to a unique value per declaration. The value would be the same each time the same declaration is evaluated, but different between different declarations. In practice it is always treated like a static declaration, even if it occurs in a non-static context.
The value of the identifier could be something like the Capability
class from dart:isolate
, but also usable as a compile-time constant.
Effectively it is as if there is a class UniqueObject
with enough state that each instance of it can be globally unique (say, parameterize it by a library URI string and a file position), so symbol id
becomes const UniqueObject id = UniqueObject._(currentLibraryUriString, positionInFile);
.
Effectively it is as if there is a class UniqueObject with enough state that each instance of it can be globally unique (say, parameterize it by a library URI string and a file position), so symbol id becomes const UniqueObject id = UniqueObject._(currentLibraryUriString, positionInFile);.
Yes, I think UniqueObject is what should be incorporated, because doing const Object()
does not work as it is the same object everywhere. This issue was discussed here. Giving open access to UniqueObject would allow creating unique const constructors. I think “unique id” is more suitable than “symbol id” as a shorthand for “var id = const UniqueObject()”.
A more general approach would be to create an additional keyword unique that can be used instead of const. Like:
var c1 = const [1, 2, 3];
var c2 = const [1, 2, 3];
assert(c1 == c2);
var u1 = unique [1, 2, 3];
var u2 = unique [1, 2, 3];
assert(u1 != u2 && u1 != c1 && u2 != c1);
unique id; // inferred as var o = unique Object();
That's an interesting idea - compile-time constant without canonicalization.
Dart constants are a composite of three or four features (depending on how you count):
and there are use-cases where you need a constant value (mainly for creating other constants).
Users use the features for one or more of these features. What you are asking for here is a way to get compile-time evaluation (one value per expression, not one per time it is evaluated) and deep-immutability (maybe?), but without canonicalization.
It is an interesting idea to see if we can split the const feature into its component parts.
The "static expression" proposal is a way to ask for one-time evaluation. An expression of the form static e
would evaluate only the first time it's encountered, caching the value for next time (like a lazily initialized variable, which is a valid implementation strategy).
This proposal asks for a non-canonicalizing, and compile-time evaluated expression to be allowed where const expressions are required.
Maybe there are other combinations that also make sense.
What you are asking for here is a way to get compile-time evaluation (one value per expression, not one per time it is evaluated) and deep-immutability (maybe?), but without canonicalization.
That sums it up. They should definitely be deep-immutable. I don't know how the internals are implemented, but I would expect that underneath the compiler forcefully creates a new const when the unique keyword is used (it doesn't try to reference an already created const). Every const constructor should be able to be invoked as either const or unique.
I'm thinking that somehow it could be a useful thing that with this unique keyword class methods could be related to unique symbols.
cc @jacob314 who has a related use case.
Concreting this feature:
unique id; // unique id = Symbol('id');
unique obj = Object();
unique id2 = Symbol('id');
assert(id!=id2);
// invalid
unique foo = 'foo' // natives types cannot be unique
// it should also be possible to shortcut
map[unique id] = 55;
print(map[id]);
If I understood it correctly, this is what is being asked for in #183.
Sometimes I have required a constant value where I don’t care about the value, but I want it to be unique (as if it were a single value enum), so I create a var for the static type safety convenience. This has been useful for creating constant map keys or in #183 there is another use case. Currently this can be done either by creating an enum type (which can be a bit clumsy) or by defining a var:
static var myIdentifier = Object()
(static when inside objects)The drawback of this is that myIdentifier cannot be declared constant, it is a bit verbose and a prone to errors if forgetting to write
static
. It would be useful if it were possible to create constant identifiers like:symbol
should be scoped as any var but it remains constant within the scope of a class or method.I use the word symbol as an illustration, but I do not think it is appropriate as it conflicts with Symbol. When I required this feature I investigated and arrived to the Symbol type, however Symbol type didn’t make much sense to me, I think doing #mySymbol should just be a shorthand for creating a single word string, so
#mySymbol == 'mySymbol'
. I read a similar comment on #251. Would it be possible to change the Symbol behavior in future Dart releases?