Home > Mobile >  How can I use a switch statement when passing an argument to a function? (dart)
How can I use a switch statement when passing an argument to a function? (dart)

Time:12-07

In Dart, one can use switch statements rather than a long if-then-else

var command = 'OPEN';
switch (command) {
  case 'CLOSED':
    executeClosed();
    break;
  case 'OPEN':
    executeOpen();
    break;
  default:
    executeUnknown();
}

but sometimes we just want to provide a value based on a condition. Like, inside of an function call, class instantiation, or setting the value of a variable, etc.

For example

// Doesn't work, but wish it did
MakeNametag(
   adjustFontSize: switch(status) {
     case 'young' : return 'large';
     case 'old' : return 'largest';
     default: return 'normal';
    } //end switch
  }
);

If you just have two options, one can use conditional operator (sometimes called ternary operator)

// Works
MakeNametag(
  adjustFontSize: ['old','young'].contains(status) ? 'larger' : 'normal');

(javascript has the same operator and issue)

CodePudding user response:

In Dart, switch is only a statement, not an expression, so you can't use it as an argument, which must be an expression, and have a value.

What you can do is to either define a helper function:

String fontSizeFromAge(String age) {
  switch (age) {
    case 'young' : return 'large';
    case 'old' : return 'largest';
    default: return 'normal';
  }
}
MakeNametag(
  adjustFontSize: nameTagFromAge(status)
);

or, if you insist on having the switch where the value is used, you can write and call the function at that point:

MakeNametag(
  adjustFontSize: () {
      switch (status) {
        case 'young' : return 'large';
        case 'old' : return 'largest';
        default: return 'normal';
  }(),
);

The (){ ... }() syntax is a zero-parameter function literal () { ... } that is immediately called with zero arguments, ... (). That's the only real way to put statements into expressions in Dart.

CodePudding user response:

Often times instead of a simple switch statement, you can define a map literal and immediately subscript [] into it. Use the if null operator ?? for the default case.

MakeNametag(adjustFont: {'young': 'large', 'old': 'largest'}[status] ?? 'normal');

Often times you can also make the map literal const for a small performance improvement.

MakeNametag(adjustFont: const {'young': 'large', 'old': 'largest'}[status] ?? 'normal');

CodePudding user response:

Yes. I found it while playing around with syntax, and I think the following looks better than most other ways. One can chain the ternary operator.

The following is an example of using the "switch" idea within a parameter passed to a function:

void main() {
  int a=2;
  print(
    a==1 ? "s" :
    a==2 ? "t" :
    a==3 ? 'u' :
    a==4 ? 'v' :
    a==5 ? 'w' :
    'x'
  ); 
}

This is what the above example would look like using the example in the question.

MakeNametag(
   adjustFont: 
     status=='young' ?  'large' :
     status=='old' ?  'largest' :
     status=='funky' ?  'wavy' :
     status=='microsoft' ?  'timesNewRoman' :     
     status=='google' ?  'roboto' :
     'normal',
  }
);

There are many others ways to do this, like creating a class or using a Map object and looking up the value based on a key. But this is the most compact way I know of.

PS. I wrote this up because I found it hard to find the answer of what to call this pattern.

  • Related