I know the usage of anonymous function with () {} but what () {}() mean?
I'm using it in a Text widget like this:
new Text(
() {
return "hello";
}(),
),
It works pretty well but why do I need to add () after the anonymous function?
Without the second set of parentheses, you're just declaring an anonymous function, nothing else. So without that second set, you would be passing a function reference to the Text widget.
Now when you add the second set of parentheses you're actually calling the function that you defined.
If you look at it another way it might make it more clear. If you give that anonymous function a name you'll get the same result.
Function test = () {
return "hello";
};
print(test());
is equivalent to
print(() {
return "hello";
}());
Related
what I mean... when I write code in Flutter (Dart) every time I have to call some callbacks sometimes they are: (_){} while other times they are: (_) => {} .
With or without parameters _ present.
To my knowledge, they should both be called lamda functions; and lambda functions should be other kind of write funtions
(_){} has signature Null Function
(_) => {} has signature Map Function() and it is short form (lambda) for
() {
return {};
}
This variant returns Map.
Full example (dartpad):
typedef SimpleFun = Null Function();
typedef LambdaFun = Map Function();
void main() {
final SimpleFun simpleFun = (){};
final LambdaFun lambdaFun = ()=>{};
print(simpleFun()); // null
print(lambdaFun()); // {}
}
I hope this helps:
(_) => _ is a lamba expression.
A lambda function is a small function containing a single expression. It is used to perform a specific task and it can contain only that one expression
While
(_) {} is a function that can take as many expressions as you want to give it.
Hope this answers your question.
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');
});
}
I am very new to Dart/Flutter and I have a confusion regarding the => notation. The documentation says that the => notation is used as a shorthand to return a single expression.
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;
My doubt comes when I am trying to set state in a flutter application.
RaisedButton(
onPressed: () => {
setState(() {
print('hello');
_products.add('More stuff');
})
},
child: Text('Add Product'),
),
Now when i change the setState method with => notation
RaisedButton(
onPressed: () => {
setState(() => {
print('hello'),
_products.add('More stuff'),
})
},
child: Text('Add Product'),
),
Both methods mentioned above work, that is they set the state as expected. All i had to do was change the semicolons to commas when using the fat arrow notation.
What is the logic behind this ? How is the fat arrow notation working with curly braces which contains multiple expressions within it.
Edit
As mentioned by Hemanth Raj the => returns a set and the code segment containing the => notation can be written as follows.
RaisedButton(
onPressed: () => {
setState(() {
return {
print('hello'),
_products.add('More stuff'),
};
})
},
child: Text('Add Product'),
),
How is the returned set containing a print function and _products.add actually updating the state. Shouldn't it throw some kind of error because usually setState is done by an expression such as _products.add('More stuff');.
This is one of the interesting questions that I would love to answer.
As the official documents say here, yes => is used as a shorthand syntax to { return ... } which means => will just return whatever is produced on the righthand side.
Also from Dart 2.2 and above, a Set can be defined with comma separated values enclosed in a {} as mentioned in docs here.
Hence, the syntax you are using, i.e {} with statements separated with a comma, it is treated as a Set by the => functions. Each element being a function call, () => { f(a) , f(b), g(a),} would return a Set with the elements returned by each function call.
This example might help you understand what is happening under the hood:
dynamic reflect(dynamic a){
return a;
}
void main() {
Function shortHand = () => {reflect(1),reflect('a'),reflect({}),reflect([]),}; // this function when called will return a Set<dynamic>
print(shortHand().runtimeType); // will print `_LinkedHashSet<dynamic>`
}
So the syntax
() => '...' returns a String,
() => [ ... , ..., ...] returns a List
and similarly () => { ... , ... , ... } actually returns a Set
Note: This method of returning set with comma separated function calls is not recommended, would request you also not to use it unless you wanted a Set to be returned as result
Reply to the Edit :
Let me breakdown the function call and results for you. So your code goes like this,
() => {
setState(() {
return {
print('hello'),
_products.add('More stuff'),
};
})
}
Here the => returns a Set with the result of setState, i.e it'll return { (result of setState call) } which might be { null }
As you have call setState the below code gets executed, which again returns a Set with { (result of print), (result of _product.add), }
() {
return {
print('hello'),
_products.add('More stuff'),
};
}
State will update, as you are executing _products.add('More stuff'), where 'More stuff' will be added to _products irrespective of where you call it. When setState is being called, the widget will be rebuilt with the _products with new data added.
Hope this helped!
For the record, the recommended syntax for what you are doing is:
RaisedButton(
onPressed: () {
setState(() {
print('hello');
_products.add('More stuff');
});
},
child: Text('Add Product'),
),
The syntax (args) => { statements } is not how Dart writes function bodies, you do either (args) { statements } or (args) => singleExpression.
Also, you need to terminate statements with semicolons, ;, not commas.
As others have pointed out, the syntax you use (args) => { print("something"), somethingElse } is actually creating a set (a Set<void> because the return type of print is void) and returning that.
This is a perfect storm of small syntax mistakes, which would seem reasonable to a JavaScript programmer, that comes together to actually mean something completely different in Dart.
And, just to make things even worse, the code works. The set literal will evaluate its expression in order, and nobody sees the created set anyway. The syntax just doesn't generalize — you can't change any of the expressions to, say, a for-loop (yet, you will be able to in the next version of Dart).
So, in Dart, never use => { unless you want to return a set or map.
I am trying to create a wrapper for lunr.js (http://lunrjs.com/) in Dart, however, I can find no documentation on how to use this with the Dart js interop.
This is the object I am trying to create:
var index = lunr(function () {
this.field('title', {boost: 10})
this.field('body')
this.ref('id')
})
Currently this is all that I have.
JsObject index = new JsObject(context['lunr'], [()
{
}]);
How am I able to access this from an anonymous function?
Also where do I put the actual lunr.js? I am simply making a wrapper for it so I don't see any reason to have it in a HTML file unless necessary.
EDIT:
I have also tried:
Create a function to allow for using this keyword. (still not sure if this syntax is correct)
_f = new JsFunction.withThis( (t) {
t.callMethod('field', ['title', {boost: 10}])
t.callMethod('field', ['body'])
t.callMethod('ref', ['id'])
});
Then create a JsObject using that function:
JsObject index = new JsObject(context['lunr'], [_f]);
This will give me this error:
Exception: Unhandled exception:
Closure call with mismatched arguments: function 'call'
NoSuchMethodError: incorrect number of arguments passed to method named 'call'
Receiver: Closure: (dynamic) => dynamic
Tried calling: call(Instance of 'JsObject', Instance of 'JsObject')
Found: call(t)
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:45)
Next I tried this:
JsObject index =new JsObject.fromBrowserObject(context['lunr']);
That gives me a different error: Exception: Illegal argument(s): object cannot be a num, string, bool, or null
This may be because I do not have a way to call the _f function when creating the JsObject that way.
You have to use :
context.callMethod('lunr', [_f]);
new JsObject(context['lunr'], [_f]); is the same as new lunr(f) in JS.
I think if you just use it in the function it will be closurized with the function. Otherwise you can try using an emulated function where you pass the this when you instantiate an instance of the emulated function.
class SomeFunction implements Function {
ThisType thisVal;
SomeFunction(this.thisVal);
call(args) {
thisVal.field(...);
}
}
I don't know dart at all, but perhaps you can sidestep the issue of trying to use this entirely. The function you pass to the lunr function has the created index yielded as the first param as well as being the context of the function.
var index = lunr(function (idx) {
idx.field('title', { boost: 10 })
idx.field('body')
idx.ref('id')
})
The above uses the yielded index object rather than relying on the context being set as the index, so you don't need to use this.
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.