5 ms·
To answer the question, one has to define precisely what "returning multiple values" should mean. It's hard to see how this is indistinguishable from returning
by jfarmer 13y ago
To answer the question, one has to define precisely what "returning multiple values" should mean.
It's hard to see how this is indistinguishable from returning a list/array/tuple plus supporting list destructuring syntactically, even in a limited way. This works in Ruby, for example:
name, email = ["Jesse Farmer", "jesse@20bits.com"]
So, you can have a function which returns an Array and the caller can "act" as if it's returning multiple values of mixed types. Python can do the same thing. Does this count as supporting "multiple return values?"
One might think about this mathematically "as if" returning multiple values were the (functional) composition of returning a list and list destructuring. If your language supports lists, you'll always have the ability to return a list, so in a world where one wants to support returning multiple values, why add support for it "directly" when you can add support for something simpler and more broadly applicable and get the same results?
I think that's the practical, language-designy answer. I don't like appealing to the mathematical definition of a function, since that doesn't account for languages like Ruby and Python which presumably wouldn't fall into the original poster's bucket of languages that support "returning multiple values."
And yet, I could (in principle) return a tuple of a different length each time I called a function in either language. This means functions in Python and Ruby are about as far away from the mathematical definition of a function as one can get, so that couldn't be why they don't support multiple return values in the sense that the original poster meant.
Lua is one of the few languages I know which differentiates both syntactically and semantically between "returning a list" and "returning multiple values."
function return_multiple()
return 1,2,3
end
function return_list()
return {1,2,3}
end
a,b,c = return_multiple()
print(a) -- prints out "1"
a,b,c = return_list()
print(a) -- prints out, e.g., "table: 0x7fc991500d20"
Note that I'm using the word "list" where Lua would use the word "table" and using the word "multiple return values" where Lua would use the word "list." That is, in Lua "return 1,2,3" is "returning a list" and "return {1,2,3}" is "returning a table." However, lists aren't values in Lua, i.e., I can't assign a Lua-list to a variable and pass it around, so for clarity's sake I'm using terms that make more sense in non-Lua languages.
The interesting thing about Lua's "multiple return values" is that they almost behave like splatted lists in Ruby — like a chunk of syntax.
function add(a,b)
return a + b
end
function return_multiple()
return 1,2
end
sum = add(return_multiple())
-- sum is now 3
-- add({1,2}) would throw an error, however
In Lua, one can use "unpack" to destructure/splat lists like {1,2,3}, so
sum = add(unpack({1,2}))
would work.
At the end of the day, these approaches all tend to be isomorphic to each other. Given Lua's design considerations (small, fast, easy to move in and out of C, etc.) I'm guessing it makes these distinctions for performance/memory management reasons, but I don't know enough about Lua's internals to say whether that's the actual justification. Outside of that I think Lua's choices are strange since you now have functions which don't return a particular value, but rather these non-syntactic entities called "multiple return values."
- plorkyeran 13y agoLua's weird return values are basically just exposing the fact that it's a stack-based VM and letting the user take advantage of that. foo(1, return_two_values(arg), 2) pushes 1 onto the stack, pushes arg onto the stack, calls return_two_values (which pops one value from the stack and pushes two new ones), pushes 2 onto the stack, and then calls foo, resulting in foo being called with four arguments. With this design you get zero-overhead (you save the construction of a table) multiple return values for free, since it simply requires a trivial bit of syntax and no error checking to verify that a function only left zero or one values on the stack. Lists aren't exposed as concrete things that can be passed around because the really aren't things at all.
- anonymoushn 13y agoActually, foo(1, return_two_values(arg), 2) will call foo with only three values. The , truncates (or extends) the left expression to exactly one value. > return (function() end)(), 5 nil 5 > return (function() return 1,2,3,4 end)(), 5 1 5 > return 5, (function() end)() 5 > return 5, (function() return 1,2,3,4 end)() 5 1 2 3 4 > return 5, (function() return nil end)() 5 nil
- djur 13y agoAnother language that distinguishes between returning a list of values and multiple values is Go. Return variables have to be declared and can be named.