141

Is there a way to return several values in a function return statement (other than returning an object) like we can do in Go (or some other languages)?

For example, in Go we can do:

func vals() (int, int) {
    return 3, 7
}

Can this be done in Dart? Something like this:

int, String foo() {
    return 42, "foobar";
} 
4
  • I don't know if any languages truly return multiple values. Python, which uses the same syntax as you used above, returns a tuple, which is just a simple object. I suspect Go is similar. Commented Jul 26, 2017 at 12:00
  • Relevant: groups.google.com/a/dartlang.org/forum/m/#!topic/misc/… Commented Jul 26, 2017 at 12:08
  • 1
    Lua can also return multiple values. Commented May 28, 2020 at 17:50
  • These now exist in Dart 3.0: stackoverflow.com/a/76257744/1759443 Commented May 15, 2023 at 20:32

11 Answers 11

224

Updated for Dart 3.0

In Dart 3.0 records can be used

(int, String) foo() {
    return (42, "foobar");
} 

void main() {
  var (a,b) = foo();
  print("int: ${a}");
  print("String: ${b}");
}

Original answer

Dart doesn't support multiple return values.

You can return an array,

List foo() {
  return [42, "foobar"];
}

or if you want the values be typed use a Tuple class like the package https://pub.dev/packages/tuple provides.

See also either for a way to return a value or an error.

Sign up to request clarification or add additional context in comments.

7 Comments

+1 for tuple which does most closely what Go does with its built-in. It's just not built into Dart, presumably not much needed yet and they keep the language as light as possible.
There were other priorities. Features like this were discussed several times. Currently it's about Dart 2.0 with strong mode and generic functions and a lot of preparation for faster iteration after 2.0 (unified front end, kernel). Next hopefully non-nullable types and others. I prefer to not add too many features, but I have full trust in the Dart team to make the right decisions.
Also either is dart 2.0 INCOMPATIBLE.
Change the return type to List<dynamic> or List<Object>
This answer is no longer true now that Dart 3 has records.
|
29

I'd like to add that one of the main use-cases for multiple return values in Go is error handling which Dart handle's in its own way with Exceptions and failed promises.

Of course this leaves a few other use-cases, so let's see how code looks when using explicit tuples:

import 'package:tuple/tuple.dart';

Tuple2<int, String> demo() {
  return new Tuple2(42, "life is good");
}

void main() {
  final result = demo();
  if (result.item1 > 20) {
    print(result.item2);
  }
}

Not quite as concise, but it's clean and expressive code. What I like most about it is that it doesn't need to change much once your quick experimental project really takes off and you start adding features and need to add more structure to keep on top of things.

class FormatResult {
  bool changed;
  String result;
  FormatResult(this.changed, this.result);
}

FormatResult powerFormatter(String text) {
  bool changed = false;
  String result = text;
  // secret implementation magic
  // ...
  return new FormatResult(changed, result);
}

void main() {
  String draftCode = "print('Hello World.');";
  final reformatted = powerFormatter(draftCode);
  if (reformatted.changed) {
    // some expensive operation involving servers in the cloud.
  }
}

So, yes, it's not much of an improvement over Java, but it works, it is clear, and reasonably efficient for building UIs. And I really like how I can quickly hack things together (sometimes starting on DartPad in a break at work) and then add structure later when I know that the project will live on and grow.

2 Comments

A common patter from functional programming for that use case is pub.dartlang.org/packages/either
+1 for not reinventing the wheel, let's use a package, because next thing is that someone wants a 3 element tuple, then there's Tuple3, and so on...
20

Create a class:

import 'dart:core';

class Tuple<T1, T2> {
  final T1 item1;
  final T2 item2;

  Tuple({
    required this.item1,
    required this.item2,
  });

  factory Tuple.fromJson(Map<String, dynamic> json) {
    return Tuple(
      item1: json['item1'],
      item2: json['item2'],
    );
  }
}

Call it however you want!

Tuple<double, double>(item1: i1,item2: i2);
or
Tuple<double, double>.fromJson(jsonData);

Comments

8

You can create a class to return multiple values Ej:

class NewClass {
  final int number;
  final String text;

  NewClass(this.number, this.text);
}

Function that generates the values:

 NewClass buildValues() {
        return NewClass(42, 'foobar');
      }

Print:

void printValues() {
    print('${this.buildValues().number} ${this.buildValues().text}');
    // 42 foobar
  }

Comments

5

Dart is finalizing records, a fancier tuple essentially.
Should be in a stable release with Dart 3.
It's already available with experiments flags.

2 Comments

A month, you say?
@claudekennilol Seems executives pushed it back for Google IO which was a couple days ago so it's now available on stable. Making a package with examples soon. Might see this pattern with macros too.
3

As other answers have noted, Dart 3.0 adds records, which can be used to return multiple values in a type-safe way.

For earlier versions of Dart, the proper way to return multiple values would be to store those values in a class, whether your own custom class or a Tuple. However, defining a separate class for every function is very inconvenient, and using Tuples can be error-prone since the members won't have meaningful names.

Another (admittedly gross and not very Dart-istic) approach is try to mimic the output-parameter approach typically used by C and C++. For example:

class OutputParameter<T> {
  T value;

  OutputParameter(this.value);
}

void foo(
  OutputParameter<int> intOut,
  OutputParameter<String>? optionalStringOut,
) {
  intOut.value = 42;
  optionalStringOut?.value = 'foobar';
}

void main() {
  var theInt = OutputParameter(0);
  var theString = OutputParameter('');
  foo(theInt, theString);
  print(theInt.value); // Prints: 42
  print(theString.value); // Prints: foobar
}

It certainly can be a bit inconvenient for callers to have to use variable.value everywhere, but in some cases it might be worth the trade-off.

Comments

1

This is now available in Dart 3.0 (Flutter 3.10.0). They are called "Records" (full doc here).

Here are some of my favorite examples:

Return types

(int x, double y) geoLocation(String name) =>
    return (-1, 36.8219);

Accessing them:

var record = ('first', a: 2, b: true, 'last');

print(record.$1); // Prints 'first'
print(record.a); // Prints 2
print(record.b); // Prints true
print(record.$2); // Prints 'last'

Variables

// Record type annotation in a variable declaration:
(String, int) record;

// Initialize it with a record expression:
record = ('A string', 123);

Named args!

// Record type annotation in a variable declaration:
({int a, bool b}) record;

// Initialize it with a record expression:
record = (a: 123, b: true);

Comments

0

you can use Set<Object> for returning multiple values,

Set<object> foo() {
     return {'my string',0}
}

print(foo().first) //prints 'my string'

print(foo().last) //prints 0

3 Comments

I don't think Sets are ordered so using first/last is incorrect imho
sets are ordered as I believe , so you will get the items in the order that you return
Apparently, the default Set is indeed ordered (see api.dart.dev/stable/2.19.6/dart-core/Set-class.html). Note however that not all Sets are ordered in Dart. (unfortunately, I can't remove my downvote)
0

you can use dartz package for Returning multiple data types

https://www.youtube.com/watch?v=8yMXUC4W1cc&t=110s

2 Comments

Answers on Stack Overflow should provide enough detail to answer the question on their own. External links should only be used to provide supplemental information or used as a citation to your answer.
Instead of providing a video you can provide enough detail answer.
0

Dart allows to return multiple values.

dart --version
Dart SDK version: 3.9.0 (stable) (Mon Aug 11 07:58:10 2025 -0700) on "macos_arm64"
(String, String) _getErrorMessageAndCode(ErrorType errorType) {
switch(errorType) {
case ConnectionError: return ('Failed to connect: Connection Timeout Error', 'ERR10001'
case GenericError: return ('Internal Server Error: Failed to process', 'ERR10002'
case NetworkTimeout: return ('Network timeout: Possible offline', 'ERR10004'
}

Caller can call this as normal function

final errorMessageAndId = _getErrorMessageAndCode(ErrorType.ConnectionError);

As the function _getErrorMessageAndCode returns multi values, the syntax to retrieve the values are using $ notation

final errorMessage = errorMessageAndId.$1 and final errorCode = errorMessageAndId.$2

Comments

-1

In this type of situation in Dart, an easy solution could return a list then accessing the returned list as per your requirement. You can access the specific value by the index or the whole list by a simple for loop.

List func() {
  return [false, 30, "Ashraful"];
}

void main() {
  final list = func();
  
  // to access specific list item
  var item = list[2];
  
  // to check runtime type
  print(item.runtimeType);
  
  // to access the whole list
  for(int i=0; i<list.length; i++) {
    print(list[i]);
  }
}

1 Comment

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.