Obscure Dart syntax - dart

While working through the the Dart Route library example for client side coding I came across this snippet.
var router = new Router()
..addHandler(urls.one, showOne)
..addHandler(urls.two, showTwo)
..addHandler(urls.home, (_) => null)
..listen();
My question is how does (_) => null work? It seems to specify a function that returns a null value but what does (_) mean?

(_) means it is a function with one parameter but you don't care about that parameter, so it's just named _. You could also write (ignoreMe) => null. The important thing here is, that there needs to be a function that accepts one parameter. What you do with it, is your thing.

(_) => null means : a function that take one parameter named _ and returning null. It could be seen as a shortcut for (iDontCareVariable) => null.
A similar function with no parameter would be () => null.
A similar function with more parameters would be (_, __, ___) => null.
Note that _ is not a special syntax defined at langauge level. It is just a variable name that can be used inside the function body. As example : (_) => _.

I will try explain this by the example.
void main() {
var helloFromTokyo = (name) => 'こんにちわ $name';
var greet = new Greet();
greet.addGreet('London', helloFromLondon)
..addGreet('Tokyo', helloFromTokyo)
..addGreet('Berlin', helloFromBerlin)
..addGreet('Mars', (_) => null)
..addGreet('Me', (name) => 'Privet, chuvak! You name is $name?')
..addGreet('Moon', null);
greet.greet('Vasya Pupkin');
}
String helloFromLondon(String name) {
return 'Hello, $name';
}
String helloFromBerlin(String name) {
return 'Guten tag, $name';
}
class Greet {
Map<String, Function> greets = new Map<String, Function>();
Greet addGreet(String whence, String sayHello(String name)) {
greets[whence] = sayHello;
return this;
}
void greet(String name) {
for(var whence in greets.keys) {
var action = greets[whence];
if(action == null) {
print('From $whence: no reaction');
} else {
var result = action(name);
if(result == null) {
print('From $whence: silent');
} else {
print('From $whence: $result');
}
}
}
}
}
Output:
From London: Hello, Vasya Pupkin
From Tokyo: こんにちわ Vasya Pupkin
From Berlin: Guten tag, Vasya Pupkin
From Mars: silent
From Me: Privet, chuvak! You name is Vasya Pupkin?
From Moon: no reaction

Related

Passing Class to Function

I’d like to pass the class User as second argument to the load-function.
Maybe someone knows how?
class App {
Map<String, List<Model>> models = {
'users': List<User>()
};
App() {
load('users');
}
void load(resource) {
Directory directory = Directory.fromUri(Uri(path: './app/data/' + resource));
for (FileSystemEntity file in directory.listSync(recursive: false)) {
Map<String, dynamic> fileContent = jsonDecode(File(file.uri.path).readAsStringSync());
models[resource].add(User.fromJson(fileContent));
}
}
}
You can't.
You can pass a Type object as argument, or a type as type argument (load<T>(resource) { ... }), but neither will allow you to call User.fromJson on the type.
What you can do is to pass the User.fromJson function as an argument (or, if that's a constructor, pass (x) => User.fromJson(x) as argument). That is:
void load(String resource, Object? fromJson(Map<String, dynamic> json)) {
...
map[resoruce].add(fromJson(fileContent));
}
and then
load("someName", (map) => User.fromJson(map));

ZF2 inserting data to Db

During saving I recive an error:
values() expects an array of values or Zend\Db\Sql\Select instance
I think error comes from:
$this->tableGateway->insert($procedure);
I don't understand what is wrong.
This is my process function:
public function processAction()
{
if (!$this->request->isPost()){
return $this->redirect()->toRoute(null, array('controller'=>'test', 'action'=>'index'));
}
$post = $this->request->getPost();
$form = new TestForm();
$inputFilter = new \Postepowania\Form\TestFilter();
$form->setInputFilter($inputFilter);
$form->setData($post);
if (!$form->isValid()){
$model = new ViewModel(
array(
'error' => true,
'form' =>$form,
)
);
$model->setTemplate('postepowania/test/index');
return $model;
}
$this->createTest($form->getData());
//return $this->redirect()->toRoute(null,array('controller' => 'test','action' => 'confirm',));
}
and createTest function:
public function createTest(array $data){
$testTable = $this->getServiceLocator()->get('TestTable');
$test = new Test();
$test->exchangeArray($data);
$testTable->save($test);
return true;
}
Save function is very simple:
public function save(Test $procedure)
{
$id = (int)$procedure->id;
if($id == 0)
{
$this->tableGateway->insert($procedure);
}
}
$this->tableGateway->insert()
From looking at the source, insert() requires an array to be passed into it, not an object. I suggest converting your object to an array before passing it in.

Future.then returns unexpected null value

the following method prints a value of a key stored in Redis
Future<String> getValue(String connectionString, String key) {
return RedisClient.connect(connectionString).then((RedisClient client) {
client.get(key).then((value) => print(value));
});
}
but when I try to print the value from main() the method getValue prints null instead of the value (as the method above):
library persistence;
Future<String> getValue(String connectionString, String key) {
return RedisClient.connect(connectionString).then((RedisClient client) {
client.get(key);
});
}
-
import 'package:test/persistence.dart' as persistence;
main () {
persistence.getValue(
"localhost:6379/0",
"key")
.then((value) => print(value)); // **prints null.... WHY???**
}
It seems that the .then((value) => print(value)) is executed too early.
Can anybody help me?
Add a return before client.get(key) or use the short method form => client.get(key) then you don't need the return.

dart reflection call by String

I want to wrote method which call all function in class:
class Example extends MyAbstractClass {
void f1(){...}
void f2(){...}
void f3(){...}
Example(){
callAll();//this call f1(), f2() and f3().
}
}
I have problem in this part of code:
reflectClass(this.runtimeType).declarations.forEach((Symbol s, DeclarationMirror d) {
if (d.toString().startsWith("MethodMirror on ")) {
String methodName = d.toString().substring(16).replaceAll("'", "");
print(methodName);
// How to call function by name methodName?
}
});
instead of
if (d.toString().startsWith("MethodMirror on ")) {
you can use
if (d is MethodMirror) {
You need an InstanceMirror of an instance of the class. I think in your case this would be
var im = reflect(this).invoke(d.simpleName, []);
im.declarations.forEach((d) ...
see also How can I use Reflection (Mirrors) to access the method names in a Dart Class?
Using dson you can do:
library example_lib;
import 'package:dson/dson.dart';
part 'main.g.dart';
#serializable
class Example extends _$ExampleSerializable {
Example() {
_callAll();
}
fn1() => print('fn1');
fn2() => print('fn2');
fn3() => print('fn3');
fn4() => print('fn4');
_callAll() {
reflect(this).methods.forEach((name, method) {
if(name != '_callAll') this[name]();
});
}
}
main(List<String> arguments) {
_initMirrors();
new Example();
}

indexed_db openCursor latest changes

The following code was posted as the new handling for openCursor. Could someone please advise if the following code should work now (Dart r18915), and what is the "values" variable?
store.openCursor(autoAdvance: true).listen(
(cursor) => values.add(onCursor(cursor)),
onDone: () => completer.complete(values),
onError: (e) => completer.completeError(e));
return completer.future;
I'm not sure what your onCursor() function is doing/calling. I'm assuming your values variable is a list.
I do something similar myself but with a callback instead of a future/completer. You only have a small function fragment here. I'm going to flush it out some to hopefully add some details:
// Accept the indexeddb Database, and return a future which
// will provide the list of values from 'someKey'
Future<List<String>> getSomeKeyValues(Database db) {
var values = new List<String>();
var completer = new Completer();
var store = db.transaction('DB_STORE', 'readwrite').objectStore('DB_STORE');
store.openCursor(autoAdvance: true).listen((cursor) {
if(cursor != null && cursor.value != null) {
// Note cursor.value is actually a Map<String, String>
// of collection's key and value
values.add(cursor.value['someKey']); // get the value key 'someKey'
}
}, onDone: () => completer.complete(values),
onError: (e) => completer.completeError(e));
return completer.future;
}
We would then call this function something like this:
getSomeKeyValues(myDatabase).then((results) {
for(var value in results) {
print(value);
}
}

Resources