Why can't a external declaration be used as a type? - js++

In respect to static typing on JS++, why cannot we use external declarations as types? For example:
external Uint8Array;
class ByteArray
{
Uint8Array[] composingArrays;
}
The JS++ compiler terminates erroring that Uint8Array cannot be used "here" and expects a type. Any ideas?

You cannot use JavaScript types as types in JS++.
The concept of the external type (sometimes called the Unified External Type) in JS++ means that all JavaScript types are treated as one type during compilation. (The one type being the external type. At runtime, external unwraps and can be any JavaScript type at runtime.)
The JS++ type system is basically the external types (unified into one external type), internal types (all JS++ types, including primitive types, arrays, user-defined types via classes, and so on), and the conversions between them.
One correct way to write your code would be:
external Uint8Array;
class ByteArray
{
var composingArrays;
ByteArray(int size) {
this.composingArrays = new Uint8Array(size);
}
}
Examples of statements that can declare something with the external type include:
external - used for importing JavaScript libraries
var - used for declaring variables with the external type
function - used for declaring functions that return values with the external type
Since Uint8Array has type external, you need the types to match (or have a possible conversion between them). Since var creates a variable with type external, and an instantiated Uint8Array has type external, the types will match.
In a more advanced usage, you might look at which types have a conversion available from the static external type and the runtime Uint8Array type.

Related

Is "dynamic" a data type in 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

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).

Dart generics not reified as per the docs

I'm trying to pass a type in order to make use of the type information, but that types doesn't appear to be pass through.
I went back to the docs to double check that Dart generics are in fact reified and according to the docs, they are:
I call hydrate on a response which morphs the content of response object:
response.hydrate<BoqVO>();
I'm expecting T to be of type BoqVO:
class Response {
...
void hydrate<T>() {
print(T.runtimeType); // always prints _Type
if (T is BoqVO) {
print("IF");
} else {
print("ELSE"); // always goes into ELSE block
}
}
...
}
... but it's not.
Replacing response.hydrate<BoqVO>(); with response.hydrate(new BoqVO()); and changing the method signature to
void hydrate(T t) {
works if i now use lowercase t, but one shouldn't have to instantiate the object in order for reified generics to be available.
Any ideas why Dart is doing this or what i'm missing for reified generics to work correctly?
PS: I'm not on Dart 2 yet, currently on Dart 1.24.3
As Günther Zöchbauer has said, the type parameter doesn't work in Dart 1.24.
The following explains what would happen if you tried the same code in Dart 2.0, where it would also not work, because it uses the type parameter incorrectly.
The code T.runtimeType treats T as an expression. When a type, including a type parameter, is used as an expression, it evaluates to an instance of the class Type. What you print is the runtime type of that Type object (where _Type is an internal platform implementation of Type).
To print the real type, just print(T) (that still converts T to a Type object, but one representing the type BoqVO and with a toString that includes the BoqVO name).
Likewise for T is BoqVO, you evaluate T to a Type object, and since Type doesn't implement BoqVO, that test is always false. There is no simple way to test if the type of a type parameter implements a specific other type, but you can hack around it as <T>[] is List<BoqVO>.
Generic collections were supported from the beginning and they got some type support, but generic methods were only experimental in Dart 1 and reified type parameters were only added in Dart 2 pre releases.

What does external mean in Dart?

What does external mean in Dart? For example: external DateTime._now();
I'm new to Dart, I can't find documentation for external, so can you give an example to help explain?
9.4 External Functions
An external function is a function whose body is provided separately from its
declaration. An external function may be a top-level function (17), a method
The body of the function is defined somewhere else.
As far as I know this is used to fix different implementations for Dart VM in the browser and Dart VM on the Server.
When we make an external function inside a class like toString()
external String toString();
means this method is abstract and the child of the parent class will add the function body, that's because in Dart we only can make an abstract class.
Summary:
external function = abstract function in not abstract classes
I don't think external keyword is meant to be used to mark methods as abstract, even if that's possible
It's enough to leave a method with no implementation to set it abstract, inside an abstract class
It's the equivalent of declare in TypeScript, and extern in C#, those are used for interoperability with other runtimes, which means you're telling the compiler "Don't worry about this method's implementation, I promise it will exist at runtime", the runtime may be in C or Javascript or whatever
In case, if you are wondering why or where should I even use external keyword, here is a one more example for Flutter.
class MyStruct extends Struct {
#Int32()
external int a;
#Float()
external double b;
external Pointer<Void> c;
}
Sometimes, but not often when you play with native libraries, in this case with Struct to access native struct's field in memory. Under Struct We must declare all fields as external because it will be external fields from dart:ffi (C / C++).
So, external is more than just way to declare "abstract method".
9.4 External Functions
An external function is a function whose
body is provided separately from its
declaration.
What this does mean is that you define the function, but without implementation. It's exactly how you define the abstract method, but the only difference is that with external you don't implement the method in dart but in C or something else.
Something like String class it can be considered as external functions except that the String class it marked with #pragma('vm:entry-point') which make the entire class use native code.
See the following example to understand:
This dart's side.
https://github.com/dart-lang/sdk/blob/main/sdk/lib/core/string.dart#L711
This the implementation in C++.
https://github.com/dart-lang/sdk/blob/main/runtime/lib/string.cc#L467-#L472
In my opinion it is an equivalent of Java native keyword. For example, since current time milliseconds is implemented differently on Android, iOS, Linux etc, DateTime.now().millisecondsSinceEpoch will be linked to different implementations at runtime. So it is not initially known how this method will look like. For this reason it is marked as external meaning it is platform dependent.

How to reference 'generated' types created by a TypeProvider

I am trying to implement a type provider for Excel files that creates generated types. My goal is to be able to reference these types from C#.
If I create the type provider using erased types, I can reference it from F# using this syntax:
type DataTypesTest = ExcelFile<"tests\ExcelProvider.Tests\DataTypes.xlsx">
If I mark my types as generated. The above syntax produces this error:
A direct reference to the generated type 'ExcelFile' is not permitted. Instead, use a type definition, e.g. 'type TypeAlias = <path>'. This indicates that a type provider adds generated types to your assembly.
How do I reference a parameterized generated type in my F# code? The source for this type provider is available on GitHub
I believe the problem may be due to how you're constructing the type in the Type Provider, not your code at the usage site. The code to use the type provider should be identical for generated or erased type providers. I had similar errors occur when trying to get the type construction correct with my generated type providers.
In your case, your type derives from ExcelFileInternal, so you need to use BaseConstructorCall, not just the constructor logic. This should look something similar to:
// add a parameterless constructor which loads the file that was used to define the schema
let ctor = ProvidedConstructor([])
ctor.BaseConstructorCall <- fun [] -> <## ExcelFileInternal(resolvedFilename, range) ##>
providedExcelFileType.AddMember(ctor)
Note that all constructors would need this type of change.

Resources