Is "dynamic" a data type in Dart? - dart

I have read that dynamic is a data type in Dart, but is it correct to call it a data type? it doesn't seems like a data type, it seems like it is a way to allow your variable to be of any data type.

In Dart, dynamic is a type. It belongs in the type hierarchy and is related to other types by the subtype relation.
It's a "top" type, which means that every type is a subtype of dynamic. (Including itself, because the "subtype" relation is reflexive - every type is considered a subtype of itself, and the term "proper subtype" is used when only talking about subtypes that are not also supertypes.)
Being a top type, it means any value can be assigned to a variable of type dynamic. So can they to any other top type, which mainly means Object?.
The difference between the two is that:
An expression with static type dynamic can be assigned to any type. That's obviously unsafe, so the runtime inserts a check, a so called "implicit downcast" which works just like doing as TargetType.
You can call any member on an expression with static type dynamic. That's obviously unsafe, so the runtime will throw if the object doesn't have such a member.
That kind of runtime checked unsafe behavior (not static type-checked) is the reason the type is named dynamic. Using dynamic is a way to turn off the static type system. Use with extreme care.
Whether you can call dynamic a "data type" depends on what you mean by "data type". The Dart language specification doesn't use the term "data type" about anything.

Yes. The specifications call it a type (https://www.ecma-international.org/publications-and-standards/standards/ecma-408/)
The type dynamic denotes the unknown type. If no static type
annotation has been provided the type system assumes the declaration
has the unknown type
Type dynamic has methods for every possible identifier and arity, with
every possible combination of named parameters. These methods all have
dynamic as their return type, and their formal parameters all have
type dynamic. Type dynamic has properties for every possible
identifier. These properties all have type dynamic

Related

Dart: dynamic vs nullable Object

Is there any difference between dynamic and Object? in dart?
This question may sound a duplicate of this What is the difference between dynamic and Object in dart?. However, I think it is not. I am not talking about semantic difference or any warnings thrown by the dart analyzer, or anything from a coder's perspective. I want to know is there a real difference between both under the hood.
I can assign any data value to both.
When I run the following:
Object? a;
dynamic b;
print(a.runtimeType);
print(b.runtimeType);
I get:
Null
Null
I know dynamic is a keyword, while Object? is a Object class. But does dynamic infer to Object?.
I'm new to Dart lang. So, please enlighten me.
Yes, there is a difference.
The types dynamic and Object? are equivalent wrt. subtyping. Both are "top types" which means that every type is a subtype of them both, even each other.
So, for subtyping there is no difference.
The difference is entirely in what you can do with an expression that has one of those types.
If an expression has type Object?, then the only methods you can call on it are the methods of Object and Null. The only types you can assign the expression to are top types.
If the expression has type dynamic, it is as if the static type system has been turned off.
You are allowed to call any method (like dynamicExpression.arglebargle()) without any warning. If the method isn't there at runtime, it'll throw an error.
And you can assign the value to any type. If the value turns out to not have that type at runtime, it'll throw an error. (This is usually called "implicit downcast" because it works as if an is ExpectedType was added to the expression by the compiler.)
Also, because a dynamic expression is treated as having any method, you cannot call extension methods on it.
It's like dynamic is a type alias for Object? with the extra effect of turning off static type checking.
When you declare a variable as an Object?, during compile-time the compiler knows that type of the variable is Object? and it remains Object? forever. You can assign any type to this variable because every other type either extends the Object or null.
When you declare a variable as a dynamic, during compile-time the compiler does not know the type of the variable and just ignores it. The compiler will check the type only during run-time and will infer the type according to the value you assigned.
dynamic contains Exception. Object can only represent known data types and Null, (excluding Exception)

Difference between Object, Dynamic and Var in Dart?

There is a discussion about dynamic and var before null-safety. Then what's the Object? between each of them?
Is Object? == dynamic?
How about var? and dynamic??
Any difference between dynamic? and dynamic?
I see the official document about null-safety, but can't find the related topic.
dynamic is a special type that disables static type-checking. You can attempt to call any method on a dynamic type. If the object turns out not to have such a method, then it will result in a runtime failure instead of a compile-time one.
Object? is a base type suitable for referencing any object, including null. Unlike dynamic, it is statically type-checked, so you would get compile-time failures if you attempt to call most methods on it without explicitly checking the runtime type or without performing a cast.
var? is not valid syntax. var is not a type; it declares a variable without explicitly specifying a type, allowing the type to be inferred.
dynamic? is valid but is redundant. (See #3.)
Variables of type dynamic can already include null, so adding a ? to make it nullable is redundant. The Dart analyzer will tell you so.
3: About dynamic vs dynamic?: they are the same.
Since dynamic also represents nullable types, for the compiler it is the same of dynamic?.
From Why operator ==(Object other) accepts a nullable argument?:
You can also see the analyzer and runtime will call it dynamic even if we check the signature of a method declared to return dynamic?:
void main() {
print(test.runtimeType); //runtimeType of the test function: () => dynamic
}
dynamic? test() { }
In fact a hint of the dart linter reports as 'unnecessary' the use of ? in dynamic? (as in Null?):
The '?' is unnecessary because 'dynamic' is nullable without it. (unnecessary_question_mark).
Personally, I don't understand why dynamic? Is only reported by a hint (which many people, myself included, don't notice) keeping it valid as a syntax.
1: A variable declared with Object? type behaves like all other normal variables whose type is specified, such as String? etc. Since every class -apart Null (the type of null)- is a subclass of Object (and since in Dart there are no primitive values as opposed to objects, unlike in Java; in Dart also null, int and bool are objects. But forget this clarification, if you don't know Java), a variable declared with Object? can contain any value. But the compiler will only allow access -after a null check- to the properties of Object (toString(), ==(), runtimeType, etc).
A variable declared with dynamic (or dynamic?, see point 3) instead allows access to any public member: the compiler will not perform any checks (unless the property begins with an underscore _, because in that case it is clear that it is not public); if you try to access a non-existent member you will instead have an error at runtime Note1. Furthermore, with dynamic we also renounce null safety: dynamic is equivalent to dynamic? (in practice the question mark can be considered implicit, it is as if it were always there).
2: using var, or final -if you want an immutable reference- without declare the type, the compiler check the value assigned to the variable (in fact the omission of the type is not allowed if the variable is not initialized immediately) and treats the variable as if it were declared with that type.
dynamic at runtime:
One use of 'dynamic' that can lead to confusion is with generic classes, because dynamic as parametric type exists also at runtime:
with
dynamic obj = true;
obj at runtime has bool type, but with
List list = [bool];
list at runtime has List<dynamic> type.
However, using
var list2 = [true];
the parametric type is inferred correctly (list2 has List<bool> runtimeType).
Note1 More precisely, a invocation such as myDynamicVariable.nonexistentMember cause an invocation of the noSuchMethod() method on the object; noSuchMethod() can also be overridden and not throw any exception; but this is a rare practice, in Dart 2).

Type name as identifier in F#

I just started to study F# and accidentally wrote this binding
let List = 1
Now when I try to obtain List methods such as 'filter' I get this error
error FS0039: The field, constructor or member 'filter' is not defined.
Of course using method with full type name like Microsoft.FSharp.Collections.List.filter is still working.
I'm wondering why it is possible to use type name as identifier in F# and how I can set back name List to type List from Microsoft.FSharp.Collections.
When I tried to reassign like this
type List = Microsoft.FSharp.Collections.List<'T>
I get
Error FS0039: The type parameter 'T is not defined.
Thank you!
In F# you can redefine almost everything and shadow existing definitions. This applies to both types (well actually types have a different behavior regarding shadowing, they shadow their values as you open the namespaces) and values but not interchangeably since values and type (and also modules) can somehow coexist at the same time in the scope. The compiler will do his best to find out which one is.
You are not forced to, but it's a common good practice in F# not to use let bindings in uppercase.
Regarding your second question, you are using a type parameter in the right side which doesn't exist in the left side of the assignment, it should be:
type List<'T> = Microsoft.FSharp.Collections.List<'T>
But notice that filter doesn't belong to the type. It's rather defined in the List module.
You should just rename your let binding from List to something sensible - as Gustavo mentioned, your definition is shadowing the core List module from F# and there is no way to use List to refer both to your integer and to the module. Shadowing core functions will make your code pretty confusing. It's also a good idea to use camelCase for let bindings, but that's a matter of taste.
If you insist on shadowing List, then you won't be able to call List.filter using List.filter. If you wanted something shorter, you could define module alias:
module FsList = Microsoft.FSharp.Collections.List
Note that your attempt to do something similar with List<'T> does not do the same thing, because functions such as filter are in a module named List rather than being static members of the type. With this, you can call filter using FsList.filter.

In Dart, do I annotate a function return value with dynamic or Object if I don't know it's type?

If I have a function that returns a value of an unknown type, do I use dynamic, representing any object, or Object, which is the ancestor of all other types?
The style guide discusses this question for parameters, but not for return values.
How should I annotate the return value and why?
Dart engineer Bob Nystrom writes:
Return types are an interesting twist on this problem. With parameter types, the guidelines are pretty straightforward:
If you use Object as a parameter type, you're saying "my method will safely accept any object and only use it for stuff like toString() that all objects support".
If you use dynamic (or nothing) as a parameter type, you're saying "Dart's type system can't easily express the type that I accept here" or "I didn't bother to annotate".
It's tricky to flip (1) around. For a return type, I guess Object would say "You better not call anything except toString() or other stuff all objects support before doing a type test yourself", where dynamic would I think mean "we can't easily annotate this so you and I better just know what we're doing".
The user would have to "cast" it to a specific type that they expect to see to avoid compiler warning and get an error earlier in checked mode.
For what it's worth, in many cases you wouldn't have to cast even if you return Object. Dart allows implicit downcasting when you initialize a local variable with a type annotation. So you can do:
Object foo() => 123;
main() {
int x = foo(); // Implicit downcast. No type warning.
}
I think in this case, I would probably do dynamic, though. I think that conveys "I don't know what type this returns, but you should" better than Object.

Getting FS0035 => Construct is deprecated

In a fsyacc based project, I have this line:
type 'a cucomment = string
This is the full error description I'm getting:
CALast.fs(117,9): error FS0035: This construct is deprecated: This
type abbreviation has one or more declared type parameters that do not
appear in the type being abbreviated. Type abbreviations must use all
declared type parameters in the type being abbreviated. Consider
removing one or more type parameters, or use a concrete type
definition that wraps an underlying type, such as 'type C<'a> = C of
...'.
Any idea how to solve this?
F# no longer allows type aliases that add generic type parameters to a type without declaring a new type. If you want to define a generic type that wraps some other type, you have to use some constructor. For example, you can use single-case discriminated union:
type 'a Cucomment = CC of string
Unfortunately, this means that you'd have to change all code that uses the type to unwrap the value using pattern matching or by adding Value member to the type.
The only case where generic type aliases are allowed is when you declare a version of type with units of measure, which requires a special attribute. However, this is probably not going to work for you (because units behave quite differently):
[<MeasureAnnotatedAbbreviation>]
type 'a Cucomment = string
If this is in some code generated by fsyacc, then that's a bug in fsyacc that should be fixed (I think this was quite recent change). In that case, report it to fsbugs at microsoft dot com.

Resources