type checking for conditional expression - dart

In the following code:
main() {
print('Starting....');
int x = 10;
int y = x > 3 ? 'aaa' : 7;
print(y);
}
This is the output:
Starting....
Unhandled exception:
type 'String' is not a subtype of type 'int'
#0 main (file:///tmp/main.dart:4:12)
#1 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:301:19)
#2 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
why isn't there a compile time error on the assignment to y? Why only runtime error?
version: Dart VM version: 2.8.4 (stable) (Unknown timestamp) on "linux_x64"
Thanks!

The reason is that Dart does still try to make implicit type casts as default behavior. So in this case, Dart will automatically assume you can cast the String into a int. This behavior can be disabled and will also be disabled by default when non-nullable types are supported:
https://dart.dev/guides/language/analysis-options#enabling-additional-type-checks
You can add the following to analysis_options.yaml (I do also recommend to add implicit-dynamic: false but this is not necessary for this specific issue):
analyzer:
strong-mode:
implicit-casts: false
And you will then get an error from the analyzer:
Analyzing bin/stackoverflow.dart...
error • A value of type 'Object' can't be assigned to a variable of type 'int'. • bin/stackoverflow.dart:4:11 • invalid_assignment
1 error found.
The reason why the error are saying Object is because Dart has analyzed x > 3 ? 'aaa' : 7 into the return type of Object since that is the only thing in common for int and String.

You are trying to parse the string 'aaa' in a type called int. 'aaa' is not a number so error.
String y = x > 3 ? 'aaa' : '7';
or do:
int y = x > 3 ? 2 : 7;

Related

Abstract over int and double using num is broken with new Dart version

The following code used to work in Dart 2.6 (very simplified example!):
T plus<T extends num>(T a, T b) => a + b;
Now it fails with: A value of type 'num' can't be returned from method 'plus' because it has a return type of 'T'.
Is there a way to abstract over double/int like intended in the example?
I'm assuming you are passing the --no-implicit-casts flag to the analyzer in order to get this error. The code is correct in the current Dart language, but it contains an implicit cast, so if you choose to disable those, the code will not be accepted.
The reason the code does not work is that the static type of a + b is num (both have type T which is only known to extend num, so they are treated as num, and num.operator+ returns num), and the return type is T which may extend num.
So, the code does an implicit cast from num to T if you allow it.
To make the code compile even without implicit casts, you have to turn it into an explicit cast:
T plus<T extends num>(T a, T b) => (a + b) as T;

Passing a F# struct to C#

I have the following error:
Library.fs(86, 40): [FS0193] Type constraint mismatch. The type 'struct (DateTime * Intervals * float * float) option list' is not compatible with type 'Collections.Generic.List<struct (DateTime * Intervals * float * float)>'
The issue is that the F# generates a struct option list and the C# is expecting an IEnumerable with the same types instead.
How can that be converted?
Edit:
here is the full error message:
Library.fs(80, 40): [FS0001] The type 'struct (DateTime * Intervals * float * float) option list' is not compatible with the type 'Collections.Generic.List'
Library.fs(80, 40): [FS0193] Type constraint mismatch. The type 'struct (DateTime * Intervals * float * float) option list' is not compatible with type 'Collections.Generic.List'
Library.fs(81, 16): [FS0001] The type ''a option' does not match the type 'unit'
If I fill the structure with fields I know are not optional, I get the same error:
struct (DateTime.MinValue, Intervals.Tick, 0.0, 0.0)
Screenshot added:
Edit:
I added the ToList() conversion, but it didn't help:
To create List<T> out of any other enumerable (including F# list) use the .ToList extension method from System.Linq.Enumerable:
open System.Linq
...
db.AddQuotesList(Candle.Intervals.Tick, output.ToList())
Another way is to use one of List's own constructors, which takes an enumerable as argument:
open System.Collections.Generic
...
db.AddQuotesList(Candle.Intervals.Tick, List(output))
Keep in mind, however, that doing this means memory allocation: List is not "lazy" like IEnumerable is, it will allocate a block of memory for all items when you construct it.

Indexing expression is invalid because subscript type 'float' is not an integral or Objective-C pointer type

I've taken the task of converted a legacy 32-bit app to 64-bit. It's an open source application, and I've ran into the following issue.
Indexing expression is invalid because subscript type 'float' is not an integral or Objective-C pointer type
It occurs on the line
- (FlxObject *) getRandom;
{
return ((FlxObject *)(members[[FlxU floor:[FlxU random] * members.length]]));
}

cast a column in $filter using Odata v3

I'm trying to do a cast on a query but it's throwing me a error 500
http://source/service/odata.svc?$filter=(cast(Value,'Edm.Int32') eq 1)
Where column 'Value' is a Edm.String
Note that i'm using v3 of OData
I think you may get error message like from service:
No coercion operator is defined between types 'System.String' and 'System.Nullable`1[System.Int32]'.
Which was thrown by Linq's Expression.Convert, which does try to convert a string value to int value.
This is because numeric types are only supported to be cast to numeric types. (This was explicitly called out in v4 spec 5.1.1.4.29 cast).
Please also note that other strong typed languages would also not allow 'CAST' from string to int directly. Thus the following code won't compile:
string a = "3";
int b = (int) a;
A better solution could be manually casting the const here:
http://source/service/odata.svc?$filter=Value eq '1'

F# int64 to int

How can I convert an Int64 to an Int32 type in F# without using the Microsoft.FSharp.Compatibility.Int32.of_int64?
I'm doing this because interactive doesn't seem to work when I try:
open Microsoft.FSharp.Compatibility
With FSharp.PowerPack added as a reference it says:
error FS0039: The namespace 'Compatibility' is not defined.
Edit: Does anyone have an answer to the question? The suggestions about the int types are useful and informative, but I'm having the same issue opening the powerpack namespace in F# interactive.
F# 1.9.6 has a type conversion function so you can do this:
let num = 1000
let num64 = int64(num)
Notice that in this type of conversion, when you reduce the size of a value, the most significant bytes are thrown away, so your data might be truncated:
> let bignum = 4294967297L;;
val bignum : int64
> let myint = int32(bignum);;
val myint : int32
> myint;;
val it : int32 = 1
Note that the functions for converting to each integer type have the same names as the types themselves, and are defined in the library spec (see below). (With the release of the CTP (1.9.6.2), a lot of the library and the namespaces changed a bit compared to previous releases, but it will probably be more 'stable' moving forward.)
http://research.microsoft.com/fsharp/manual/FSharp.Core/Microsoft.FSharp.Core.Operators.html

Resources