Useless Tips for Dart you probably never need. (Part 1)
Tags: programming, flutter, dart, productivity
Published: 2022-01-13 17:03:19


There exist a lot of great articles highlighting the most useful tips and tricks for Flutter and Dart. They provide great value for both beginners and advanced developers. 

This article is not one of them.

This is about the useless tips, the weird quirks, the boring facts and not needed tricks. They are either so absurd you won't ever need them, or so abstruse you don't wish to need them. But they deserve some love, too.

---

## Symbols


Symbols in Dart are a neat way to represent a name. You can create a Symbol using its constructor: `var mySymbol = Symbol('someName');`. They are great when normal strings are too mainstream for you.

When you want to flex in front of your coworkers, use the symbol literal. It is another way to construct Symbols without using the boring constructor. Just prefix your name with a hip hashtag (`#`) and you are good to go: `var myFancySymbol = #someName;`. You also can use the dot syntax (`#some.name`) or any standard operator like `#+`.

Since two Symbols with the same name are identical regardless of whether you used the constructor or literal syntax, they make for some fancy comparisons. So next time when you have some static String comparison, just use Symbols (or don't).

```dart
void fancySwitch(String value) {
  switch(Symbol(value)) {
    case #foo: print('Found foo');
    case #bar.baz: print('Found bar.baz');
  }
}
```


##Never


Wanna know another useless tip? I would **Never** tell you!

Never in Dart is used as a function return type that safely tells the compiler, that this function will never return. It is most notably used in the `exit()` function from `dart:io`, which will just exit the program and therefore never returns. It is great when you want to just randomly quit your application and leave the user confused. It is also very effective when you want to reduce battery usage of your app.

Now you are probably like 'Woah, how awesome is that. How can I use this in my own method?'. And fear not, I got you covered. Two great ways to use Never is to either have an infinite loop that never returns or breaks in your method, or a method that just always throws.

```dart
Never roundRoundBaby() {
  while(true) {
    print('You spin me round round baby.');
    sleep(Duration(seconds: 1));
  }
}
Never thisIsFine() {
  print('This is fine.');
  throw '🔥🔥🔥 (╯°□°)╯︵ ┻━┻ 🔥🔥🔥';
}
```


## Function.apply()


Do you know how you can call a function in Dart? Probably. But did you know there are more sophisticated ways you can achieve this?

And I'm not talking about the `call()` method, because that is [actually very useful](https://www.educative.io/edpresso/what-is-dart-call).

I'm talking about `Function.apply()`. Instead of boringly calling a function directly, you can use this handy helper to completely ignore any parameter constraints and backstab the compiler. It works by providing it a `Function`, a `List` of positional parameters, and a `Map` of named parameters:

```dart
// instead of
foo(1, 2, 3, f: 4, g: 5)
// do this
Function.apply(foo, [1, 2, 3], {#f: 4, #g: 5});
```

Notice how we use symbol literals for the named parameters. How ironic.

Now when you want to make absolutely sure that your function is properly applied (or you hate your coworkers), you can pass the whole invocation to `Function.apply` a second time. Then it would look like this: 

```dart
Function.apply(Function.apply, [foo, [1, 2, 3], {#f: 4, #g: 5}]);
```

Next are two very interesting use-cases that I could come up with. They are particularly designed to solve quite common problems.


### Currying (kind of)

Currying is a fancy functional programming term. With currying, instead of providing all parameters at once, we take it real slow and provide one argument after another. This gives you the time to get some coffee or reflect on your past life choices.

Say we have a simple function greet:

```dart
void greet(String name, String msg) {
  print('Hi $name, $msg');
}
```

We might want to call this function multiple times with the same name, but a different message. Instead of behaving like a normal person and just calling the function with the appropriate parameters, we can write ourselves an overcomplicated currying helper function. Also let's use an extension on `Function` just because we can.

Since we want to partially provide parameters, we need to keep track of the already provided parameters on each curry call. We then want to repeatedly provide a single parameter in each subsequent method call and add this to our list of provided parameters. To signal the end of parameters, we do another last call with no parameters. The resulting extension looks like this:

```dart
extension CurryFunction on Function {
  // starting point, empty parameters
  Function get curry => _curry([]);
  // creates the curry function
  Function _curry(List params) {
    // returns a function with one optional parameter p
    // when there is a next parameter (p != null), add to list
    // else invoke original function using Function.apply
    return ([p]) => p != null 
      ? _curry([...params, p]) 
      : Function.apply(this, params);
  }
}
```

We can now call our `greet` function like this:

```dart
void main() {

  // get the currying function
  var greetWho = greet.curry;

  // provide the first parameter
  // this will return another function
  var greetTom = greetWho('Tom');

  // provide the second parameter
  // and call again to terminate currying
  // prints 'Hi Tom, how are you?'
  greetTom('how are you?')();

  // provide a different second parameter
  // prints 'Hi Tom, want some curry?'
  greetTom('want some curry?')();

  // also works with more parameters
  // prints 'a-b-c-d'
  concat.curry('a')('b')('c')('d')();
}

// another function with more parameters
void concat(String p1, String p2, String p3, String p4) {
  print('$p1-$p2-$p3-$p4');
}
```


### Double-Braces

Now the last example was all about increasing your usage of these shiny little emoji smiles `(` and `)` . But what if those keys are broken on your keyboard, or you just don't like parentheses. This seems like a reasonable problem we should look into.

When we discovered `Function.apply` a few sections back, we had this neat package of our function and parameters we could use: `[foo, [1, 2, 3], {#f: 4, #g: 5}]`. A great starting point, since there are no parentheses in sight. However we still needed them to pass this information to the `apply` method. So we need to come up with another way to pass some information to a method, without using `(` or `)`. 

We are rescued by operator overloading. Any Dart class can define custom methods that are called when we use simple operators like `+` or `-`. Another operator we can overload is `[]` used i.e. get or set values in a `Map`. We then just need to write a class that overloads the `[]` operator to receive a function and passes it to `Function.apply`:

```dart
class CallProxy {
  const CallProxy();

  // overload the [] operator to receive a function package
  // passes all data to Function.apply and returns the result
  dynamic operator [](List list) {
    return Function.apply(
      // the function
      list[0] as Function, 
      // positional parameters
      list[1] as List, 
      // named parameters, optional
      list.length == 3 ? list[2] as Map<Symbol, String> : null,
    );
  }
}

// a static instance of this class we can use later
const call = CallProxy();
```

Now we can simply call any function like this:

```dart
call[[foo, [1, 2, 3], {#f: 4, #g: 5}]];
```

The outer `[]` are from the operator overloading, and the inner `[]` are from the list literal.

With the new [Dart 2.15 constructor tear-offs](https://medium.com/dartlang/dart-2-15-7e7a598e508a) we can even call constructors with this syntax: 

```dart
var bananas = call[[List.filled, [10, 'banana']]];
```

Lastly, the concat currying from above would look really edgy with all those brackets: 

```dart
call[[call[[call[[call[[call[[concat.curry,['a']]],['b']]],['c']]],['d']]],[]]];
``` 

If you are paid by lines of code, this is for you!

> [**Yes, this is actually works. Try it out here.**](https://dartpad.dev/?id=c2441088cec360004237a33715eee366) 

---

{% post schultek/useless-tips-for-dart-you-probably-never-need-ki3-temp-slug-8133962 %}

---

_Do you know any more useless or abstruse tricks? Please leave a comment._

_Also I wanted to experiment with something you won't read everyday in contrast to the thousands of 'Tips & Tricks' articles out there. So please show some love in case you liked it or give some feedback._