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)
Related
I saw a tutorial where he declared a function like this:
class Person {
String name;
Function(String name) doingHobby;
}
What does it mean? how is it differ with common Function with bracket?
This also not even looks like arrow function.
Thanks.
It means that doingHobby is a variable which is allowed to point to as function which returns dynamic (if we don't specify any return value, Dart will assume dynamic which basically means it is allowed to return anything including void) and takes one String argument.
Here is an example where I assign a void Function(String) to it using a constructor and later calls this function by using the doingHobby variable:
class Person {
String name;
void Function(String name) doingHobby;
Person(this.name, this.doingHobby);
}
void main() {
final person = Person(
'Jakob',
(hobby) => print('Doing $hobby'),
);
person.doingHobby('playing football'); // Doing playing football
}
I know about the extension feature in Dart, but how can I use it with functions?
Essentially, I am facing two problems:
What do I extend on (extension FancyFunction on ?)?
I would want to add a function like toAsync that makes the function return a Future of its usual result.
How would I implement calling?
I could create a callAsync member that executes this() or this.call(), but I would like to use regular calling syntax, i.e. just parentheses.
What do I extend on when extending functions?
Dart has a Function type. This can be extended on and you can pass type parameters if you want.
Here is an example from the changelog:
extension CurryFunction<R, S, T> on R Function(S, T) { ... }
Furthermore, you can extend any typedef of a function.
For adding the toAsync and callAsync functionality a generic return type R will do. Note that this will only extend functions without parameters as Function() takes no parameters:
extension FancyFunction<R> on R Function() {
Future<R> Function() toAsync() => () async => this();
}
Now, this could be used like this:
void syncHello() => print('Hello');
void main() {
final asyncHello = syncHello.toAsync();
asyncHello().then((_) => print(', World!'));
}
How do I implement calling?
Every class in Dart can implement the call method. You can either execute this method simply using parentheses or with .call().
Here is an example implementation:
extension FancyFunction<R> on R Function() {
Future<R> call() async => this();
}
Since every Function already implements call, the extension member cannot be called implicitly.
Instead, you will have to explicitly declare your function as a FancyFunction to be able to call it:
void syncHello() => print('Hello');
void main() {
FancyFunction(syncHello)()
.then((_) => print(', World!'));
}
Note that FancyFunction(syncHello)() is the same method call as FancyFunction(syncHello).call().
However, now we have two problems:
We have to explicitly declare our function to be a FancyFunction, which somewhat defeats the purpose of having an extension.
The call method will always return a Future as the regular call method cannot be accessed anymore when we declare a FancyFunction.
Instead, adding a method like callAsync seems like a better solution:
extension FancyFunction<R> on R Function() {
Future<R> callAsync() async => this();
}
Now, callAsync can be used implicitly again:
void syncHello() => print('Hello');
void main() {
syncHello.callAsync()
.then((_) => print(', World!'));
syncHello(); // regular call
}
I have a List<String> of Dart function names. For example, ['func1', 'func2', 'func3']. I want to call each function in the List. How can I go from a String to a Function? The following code does not work, but conceptually it does what I want:
var func1 = Function('func1');
See how it creates a Function from 'func1'.
Edit: I need to deal with Strings because I read the list of functions from a file.
I don't think Dart allows that at the moment (for objects you could use dart:mirrors, but it's currently marked as an unstable library).
An alternative is to use a Map to associate the strings with the functions, as in:
void foo() {
print('foo');
}
void bar() {
print('bar');
}
void main() {
var functions = {
'foo': foo,
'bar': bar
};
// calling foo()
functions['foo']();
// or
var b = functions['bar'];
b();
}
The Dart Editor doesn't seem to recognize $this.keyword, where keyword is a field of a class. The expression is located in a function of a method context. But it does recognize $keyword. The confusion is, why doesn't it recognize $this.keyword, the this keyword should be rigid like in C# or Java.
class TryMe {
String keyword;
void hi(Function callback) {
callback(() => return '$this.keyword');
}
}
If the interpolation part is not an identifier but an expression you need to add {}
callback(() => return '${this.keyword}');
I'm not sure what your code is doing, but you don't usually use this to refer to class fields. You can rewrite your code as:
class TryMe {
String keyword;
void hi(Function callback) {
callback(() => keyword);
}
}
Also note that you don't need a return when using => syntax.
In Dart, is it possible for a function to have a prototype associated with it?
Example Javascript code:
doStuff.prototype.isDefined = true; //is there anything like Javascript's function prototypes in Dart?
function doStuff(){
console.log("The function doStuff was called!");
}
Is it possible to do the equivalent of this in Dart (i.e., create a list of properties for each function?)
Two things to address here:
First, Dart doesn't have prototypes or prototypal inheritance, and instead uses classical inheritance. Rather than a prototype, objects have a class, and instead of a prototype chain, objects have superclasses.
Second, for your specific case, I think we'd have to see more of what you need to do to figure out the idiomatic way to do it in Dart. It should soon be possible to emulate functions with objects so that you can invoke an object and still have state and other methods associated with it.
See this article for more: http://www.dartlang.org/articles/emulating-functions/
When that capability lands you'll be able to do this:
class DoStuff {
bool isDefined = true;
call() => print("The function doStuff was called!");
}
var doStuff = new DoStuff();
main() => doStuff();
Which works if you have a fixed set of metadata about your function that you need to keep track of. It's slightly different from JavaScript because each instance of the function in Dart will have its own state for isDefined. I'm not sure if it's possible or easy to get multiple instances of the function in JavasScript, but you might need to make isDefined static so that the value is shared across all instances.
Dart does not allow you to add or remove member variables from an instance of a class at runtime. Rewriting your example in Dart it might look something like this:
class doStuff {
bool isDefined;
doStuff() {
isDefined = true;
}
void stuff() {
print('The function stuff was called!');
}
}
main() {
new doStuff().stuff();
}
If you wanted to add a property bag to a class in Dart you would write:
class PropertyObject {
Map<String, Dynamic> properties;
PropertyObject() {
properties = new Map<String, Dynamic>();
}
Dynamic operator[](String K) => properties[K];
void operator[]=(String K, Dynamic V) => properties[K] = V;
}
main() {
PropertyObject bag = new PropertyObject();
bag['foo'] = 'world';
print('Hello ${bag['foo']}');
}
Note that you can't access map properties using the '.' operator.