Undefined types in vala - vala

In Vala, is it possible to declare a function like this
void do_something(object foo) { }
where object stands for any possible type, so that I can for example pass both an integer and a string to this function?
do_something("Foo Bar");
do_something(1234);

You can use a generic if you wanted:
void do_something<T>(T foo) {}
But what are you going to do with a value you can't use?
If you want to store it for later reconstitution, you can use a GLib.Value which will be automatically packed by the compiler:
void do_something(Value foo) {}

Related

Nullable evaluation of function with non-null arguments

S? _nullableEvaluation<S, T>(S Function(T) f, T? nullableArgument) =>
nullableArgument == null ? null : f(nullableArgument);
Is there something in the dart language like the above, some built-in language feature? Not that it's hard to write yourself, just wondering if I'm reinventing the wheel to do something like the below.
import 'dart:convert';
void main() {
String? test = null;
print(_nullableEvaluation(utf8.encode, test));
test = "Test";
print(_nullableEvaluation(utf8.encode, test));
}
There is nothing in the language which allows you to gate a call to a static function depending on the nullability of the argument.
However, if you write your static function as an extension method instead, you can use normal null-aware method invocation:
extension UtfEncode on String {
Uint8List utf8Encode() => utf8.encode(this);
}
// ...
test?.utf8Encode()
You can also declare an extension method where you supply the function to call:
extension ApplyTo<T extends Object> on T {
S applyTo<S>(S Function(T) f) => f(this);
}
which you can then use as:
test?.applyTo(utf8.encode)

Why type inference is not able to infer a type in a function callback?

I have a class:
class Foo<T> {
final void Function(T) bar;
Foo(T t, {required this.bar});
}
and I'm passing int value so that T can be inferred as int, but the issue is in the following code, t is of type Object? and not int. Why is that so?
Foo(0, bar: (t) {
// `t` is of type `Object?`
});
Note: I'm not looking for a solution, which is to use Foo<int>(0, bar: ...). I want to know the reason why t is not inferred correctly
The situation you describe should now be fixed as of Dart 2.18.
Original answer for earlier versions of Dart
Your problem can be more clearly observed with:
class Foo<T> {
final void Function(T) bar;
Foo(T t, {required this.bar});
}
Type staticType<T>(T object) => T;
void main() {
var foo = Foo(0, bar: (x) => print(staticType(x)));
print(staticType(foo)); // Prints: Foo<int>
print(staticType(foo.bar)); // Prints: (int) => void
print(foo.bar.runtimeType); // Prints: (Object?) => void
foo.bar(42); // Prints: Object?
}
I'm not an expert on the inference rules, but (prior to Dart 2.18) inference either could flow top-down (from function to arguments) or bottom-up (from arguments to function). Since you don't supply an explicit type parameter when constructing Foo, Foo's generic type argument T must be inferred from its arguments. However, the argument type to the anonymous function also isn't specified, so it's assumed to be Object?.
For Foo's T to be inferred as int and for the anonymous function to be inferred to be (int) => void would require inference to flow from the positional argument up to the function and back down to the named argument, which Dart (prior to 2.18) did not do. You thus instead ended up with the (Object?) => void anonymous function being implicitly cast to (int) => void.

Is it possible to specify function with optional parameter as function argument in Dart2?

I am using Dart2
What I want to do is to force developer to use callback that accepts no or at most 1 argument.
For example, having following method:
void doYourJob(void onComplete([result])){ //this is what I have tried, buts its wrong - requires ([arg])=> callback
.... do your job
onComplete(result);
}
I would like to be able to use that method in two ways eg:
doYourJob(()=>doStuff);
and
doYourJob((result)=>doMoreStuffWithResult(result));
Is it possible to do something like this?
No. What you are trying to do is not possible.
You want to have a function type which accepts functions taking either zero or one argument. That is, you want to be able to pass a unary function and a nullary function.
That is, a function type which is a supertype of both void Function() and void Function(Object).
That is not the same as a function type with an optional parameter. Such a function type requires that all arguments must be callable both with zero and one argument. You cannot pass a pure unary function to that, because that function cannot be called with zero arguments.
There is no function type which is a supertype of both void Function() and void Function(Object). The nearest supertype is Function, which accepts any function, not just unary and nullary ones. You can use that, but you lose the type checking.
You can do this by creating a typedef
typedef Callback = Null Function([String data]);
void doYourJob(Callback onComplete) {
onComplete('Data');
onComplete();
}
OR
You can pass the Function directly
void doYourJob(Null Function([String data]) onComplete) {
onComplete('Data');
onComplete();
}
You can call this method like this
void main() {
doYourJob(([String data]) {
print('DATA: $data');
});
}

What is the dart equivalent of C#'s Func<bool, String> type, ie how do I declare a strongly typed function variable?

In C# it is possible to strongly type function variables and parameters.
What is the dart equivalent of this c# code?
Func<bool, String> myFunc;
I am aware of the Function type but it doesn't allow me to define my input and output types, is there any way to acheive this in dart?
Function allows you to specify your input and output types, and can be used as method parameters and return types, in generics, or they can be given a name using a typedef.
/// As a method parameter.
void takesACallback(void Function(int, String) callback) {}
/// As a type parameter.
final mapOfFunctions = <int, String Function(bool)>{};
/// Named with a typedef.
typedef MyCallback = void Function(int);
/// Using the typedef
void myMethod(MyCallback myCallback) {}

Syntax error when trying to determine if a variable is of a certain type

Pretty much as the title says: If you have a Type stored in a variable, there's no way to compare your actual object to this type variable, as far as I can tell. I can probably accomplish what I'm trying to do with mirrors, but I'd prefer not to if at all possible.
void example() {
Type myType = String;
String myExample = "Example";
//Syntax error here: The name 'myType' is not a type and cannot be used in an 'is' expression
if (myExample is myType) {
}
}
You can't generally test if a value is of a type using the Type object.
Type objects are reflected types, not real types. They represent the real type, but you can't use them in the code where you need a type: as type assertions, as generic type parameters or with the is/as operators. You must use the name of a type in those places, and not the name of a normal variable that happens to hold a Type object.
Clever stuff using mirrors might get there, but it's likely overkill for most cases (and I understand that you don't want it).
What you might be able to do instead, is to not pass around raw Type objects. You could instead make your own type abstraction, something like:
class MyType<T> {
const MyType();
Type get type => T;
bool isA(Object object) => object is T;
}
Then you can use that to represent types, not a Type object, and do something like:
void main(List<String> args) {
MyType myType = const MyType<String>();
String myExample = "Example";
if(myType.isA(myExample)) {
print('is');
} else {
print('is not');
}
}
That does require that your entire program uses your type objects to pass around types, but it also gives you a lot of control over those objects, so you can implement the functionality that you need.
I tried
library x;
void main(List<String> args) {
Type myType = String;
String myExample = "Example";
if(myExample.runtimeType == myType) {
print('is');
} else {
print('is not');
}
}
and it worked.
I have not much experience with such code in Dart though. Maybe that is not a fail-safe approach.
import 'package:reflection/reflection.dart';
void main() {
var childType = typeInfo(Child);
var baseType = typeInfo(Base);
if(childType.isA(baseType)) {
print("Child is Base");
}
if(baseType.isAssignableFrom(childType)) {
print("Base is assignable from Child");
}
}
class Base {
}
class Child extends Base {
}
Child is Base
Base is assignable for Child
P.S.
The "reflection" package incompatible with dart2js. It work only when used in Dart language.

Resources