Multiple Returns: Which One Sets the Final Return Value

Multiple returns: Which one sets the final return value?

Yes, the language spec defines that "2" is the result. If a VM does it differently, it's not spec-compliant.

Most compilers will complain about it. Eclipse, for example, will claim that the return block will never be executed, but it's wrong.

It's shockingly bad practice to write code like that, don't ever do it :)

Return multiple values from function

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.dartlang.org/packages/tuple provides.

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

Should a function have only one return statement?

I often have several statements at the start of a method to return for "easy" situations. For example, this:

public void DoStuff(Foo foo)
{
if (foo != null)
{
...
}
}

... can be made more readable (IMHO) like this:

public void DoStuff(Foo foo)
{
if (foo == null) return;

...
}

So yes, I think it's fine to have multiple "exit points" from a function/method.

How to annotate types of multiple return values?

You are always returning one object; using return one, two simply returns a tuple.

So yes, -> Tuple[bool, str] is entirely correct.

Only the Tuple type lets you specify a fixed number of elements, each with a distinct type. You really should be returning a tuple, always, if your function produces a fixed number of return values, especially when those values are specific, distinct types.

Other sequence types are expected to have one type specification for a variable number of elements, so typing.Sequence is not suitable here. Also see What's the difference between lists and tuples?

Tuples are heterogeneous data structures (i.e., their entries have different meanings), while lists are homogeneous sequences. Tuples have structure, lists have order.

Python's type hint system adheres to that philosophy, there is currently no syntax to specify an iterable of fixed length and containing specific types at specific positions.

If you must specify that any iterable will do, then the best you can do is:

-> Iterable[Union[bool, str]]

at which point the caller can expect booleans and strings in any order, and of unknown length (anywhere between 0 and infinity).

Last but not least, as of Python 3.9, you can use

-> tuple[bool, str]

instead of -> Tuple[bool, str]; support for type hinting notation has been added to most standard-library container types (see PEP 585 for the complete list). In fact, you can use this as of Python 3.7 too provided you use the from __future__ import annotations compiler switch for your modules and a type checker that supports the syntax.

Ignore python multiple return value

One common convention is to use a "_" as a variable name for the elements of the tuple you wish to ignore. For instance:

def f():
return 1, 2, 3

_, _, x = f()

Is it pythonic for a function to return multiple values?

Absolutely (for the example you provided).

Tuples are first class citizens in Python

There is a builtin function divmod() that does exactly that.

q, r = divmod(x, y) # ((x - x%y)/y, x%y) Invariant: div*y + mod == x

There are other examples: zip, enumerate, dict.items.

for i, e in enumerate([1, 3, 3]):
print "index=%d, element=%s" % (i, e)

# reverse keys and values in a dictionary
d = dict((v, k) for k, v in adict.items()) # or
d = dict(zip(adict.values(), adict.keys()))

BTW, parentheses are not necessary most of the time.
Citation from Python Library Reference:

Tuples may be constructed in a number of ways:

  • Using a pair of parentheses to denote the empty tuple: ()
  • Using a trailing comma for a singleton tuple: a, or (a,)
  • Separating items with commas: a, b, c or (a, b, c)
  • Using the tuple() built-in: tuple() or tuple(iterable)

Functions should serve single purpose

Therefore they should return a single object. In your case this object is a tuple. Consider tuple as an ad-hoc compound data structure. There are languages where almost every single function returns multiple values (list in Lisp).

Sometimes it is sufficient to return (x, y) instead of Point(x, y).

Named tuples

With the introduction of named tuples in Python 2.6 it is preferable in many cases to return named tuples instead of plain tuples.

>>> import collections
>>> Point = collections.namedtuple('Point', 'x y')
>>> x, y = Point(0, 1)
>>> p = Point(x, y)
>>> x, y, p
(0, 1, Point(x=0, y=1))
>>> p.x, p.y, p[0], p[1]
(0, 1, 0, 1)
>>> for i in p:
... print(i)
...
0
1

How to assign from a function which returns more than one value?

(1) list[...]<- I had posted this over a decade ago on r-help. Since then it has been added to the gsubfn package. It does not require a special operator but does require that the left hand side be written using list[...] like this:

library(gsubfn)  # need 0.7-0 or later
list[a, b] <- functionReturningTwoValues()

If you only need the first or second component these all work too:

list[a] <- functionReturningTwoValues()
list[a, ] <- functionReturningTwoValues()
list[, b] <- functionReturningTwoValues()

(Of course, if you only needed one value then functionReturningTwoValues()[[1]] or functionReturningTwoValues()[[2]] would be sufficient.)

See the cited r-help thread for more examples.

(2) with If the intent is merely to combine the multiple values subsequently and the return values are named then a simple alternative is to use with :

myfun <- function() list(a = 1, b = 2)

list[a, b] <- myfun()
a + b

# same
with(myfun(), a + b)

(3) attach Another alternative is attach:

attach(myfun())
a + b

ADDED: with and attach

Return multiple values in JavaScript?

No, but you could return an array containing your values:

function getValues() {
return [getFirstValue(), getSecondValue()];
}

Then you can access them like so:

var values = getValues();
var first = values[0];
var second = values[1];

With the latest ECMAScript 6 syntax*, you can also destructure the return value more intuitively:

const [first, second] = getValues();

If you want to put "labels" on each of the returned values (easier to maintain), you can return an object:

function getValues() {
return {
first: getFirstValue(),
second: getSecondValue(),
};
}

And to access them:

var values = getValues();
var first = values.first;
var second = values.second;

Or with ES6 syntax:

const {first, second} = getValues();

* See this table for browser compatibility. Basically, all modern browsers aside from IE support this syntax, but you can compile ES6 code down to IE-compatible JavaScript at build time with tools like Babel.



Related Topics



Leave a reply



Submit