Почему функции в некоторых популярных языках возвращают только один тип результата? - PullRequest
6 голосов
/ 16 июля 2010

Почему функции в некоторых популярных языках возвращают только один тип результата?

Т.е. я имею в виду, почему компиляторы выдают ошибку при следующем синтаксисе

public int int  returnTwoIntegers(){
.......
........
}

Ответы [ 13 ]

22 голосов
/ 16 июля 2010

Функции возвращают только одно значение, потому что его "они" изобрели в старые времена ассемблера. В основном происходит то, что функция помещает возвращаемое значение в стек. Затем вызывающая сторона извлекает значение из стека. Если бы функция возвращала больше значений, вызывающая сторона не знала бы, сколько значений выскочить, и стек будет разбалансирован (что приведет к сбою программы).

18 голосов
/ 16 июля 2010

Функция (на языках, которые вы указали в своих тегах) имеет один вывод , но этот вывод не обязательно должен быть единственным значением . Ваш вывод может легко быть классом, который инкапсулирует любое количество данных, которое вы хотите.

Также обратите внимание, что вы также можете передавать множественные входные аргументы по ссылке в вашу функцию, увеличивая тем самым количество возвращаемых выходов.

10 голосов
/ 16 июля 2010

Чтобы упростить материю.

Вы всегда можете вернуть T[], Pair<L,R>, Set<E> и т. Д. На этих языках, чтобы эмулировать возврат нескольких значений. Это учитывает большинство сценариев с несколькими return значениями.

Не стоит так сильно менять семантику языка для такой выгоды.

Похожие вопросы

6 голосов
/ 16 июля 2010

Мое лучшее предположение, что оно перенесено из математики.Там вы можете иметь функцию с несколькими параметрами и значением, которое является результатом.

f(x1, x2, ...) = y (the formula might be something like x1 + x2^2 + x3^3 + ...)

Даже если вы хотите отобразить многомерный домен в многомерный диапазон, вы обычно пишете как:

f1(x1, x2, ...) = y1 (perhaps y1 = x1 + x2^1 + ... like above)
f2(x1, x2, ...) = y2 (and y2 = x1 - x2^2 + x3^3 - x4^4 +...)
...

так как каждый y получает свою собственную математическую формулу на основе входных данных, которые в программировании просто переводят на несколько функций, имеет смысл разделить ее следующим образом.

Иногда проблема заключается в формулах для y1 и y2может быть очень похожим или полагаться на повторение одного и того же или чего-то еще, что их совместное выполнение может иметь больше смысла.В python вы можете

вернуть a1, a2;

и затем назвать его как

x, y = f ();

, но в большинствеЯзыки вы можете вернуть только одну переменную.Это не мешает вам сделать его сложным объектом с несколькими значениями.

2 голосов
/ 18 июля 2010

Даниэль Вайнреб - который работал над обоими диалектами Лисп (который имел несколько возвращаемых значений) и Java (который не имел), объясняет, почему :

Когда мы добавилиЯ полагаю, что функция возврата нескольких значений на Lisp-машину Lisp (откуда она пошла в Common Lisp) была одной из серьезных причин.В то время у нас не было хорошей технологии GC, и написание программ на Лисп для тщательного минимизации использования было очень распространено.

Другая причина была в выразительности: чтобы было ясно, что функция действительно возвращает более одного результатавместо того, чтобы вводить небольшой список «type» (например, «два списка дескриптора файла и логическое значение, чтобы сказать, будет ли ...»).

В Java я видел определения маленьких классовединственная цель которого - вернуть несколько значений.Преимущество этого подхода заключается в том, что типы и значения возвращаемых значений документируются (по крайней мере, если вы выберете четкие имена и добавите комментарии!).Но, на мой взгляд, это довольно многословно.

Когда я впервые просматривал раннюю спецификацию Java, я с удивлением обнаружил, что не было никакого способа вернуть несколько значений.Я хотел лоббировать добавление этого, поэтому я попытался придумать вариант использования, который был бы и простым, и очень убедительным.Я не смог этого сделать!Поэтому я не пытался лоббировать это.Дизайнеры Java довольно явно старались избегать множества наворотов (и синтаксического сахара), и за это наверняка можно многое сказать.

2 голосов
/ 16 июля 2010

Google's Go поддерживает несколько возвращаемых значений

1 голос
/ 18 июля 2010

Lua также поддерживает несколько возвращаемых значений: например, вы можете написать следующее:

function foo()
    return 1, 2, 3
end

a, b, c, d = foo()

после выполнения a, b, c будет содержать значения 1, 2, 3, а d будет равно нулю. Таким же образом вы можете сделать следующее:

function bar()
   return true, 2, 3
end

if bar() then
   -- do something intelligent
end

оператор if в этом случае будет работать только с первым возвращенным значением - если вам нужны другие значения, вам придется хранить их в переменных, как обычно:

a, b, c = bar()
if a then
   -- do something intelligent
end

так что вы видите: в Lua все возвращаемые значения, которые не нужны, отбрасываются (как 2, 3 в примере с if).

1 голос
/ 16 июля 2010

Функция должна выполнять четко определенную задачу.Помимо того факта, что вы всегда можете вернуть массив: возможно, что-то не так с вашим дизайном программного обеспечения, если вам нужно возвращать разные значения из разных типов данных.

Кроме того, человеку гораздо легче читатьфункция с одним возвращаемым значением.

1 голос
/ 16 июля 2010

Я думаю, что в большинстве случаев достаточно одного возвращаемого значения, и у математического понятия функции (или лямбда-исчисления) тоже есть одно возвращаемое значение, поэтому понятно, что разработчики языка пытаются придерживаться «стандарта». Фактически наличие нескольких функций, для которых требуется несколько возвращаемых значений, может сбивать с толку и может быть признаком плохого дизайна, например, отсутствующий составной класс.

«Классический» подход для возврата нескольких значений использует кортежи. Некоторые языки имеют встроенный тип Tuple (например, Scala), но вы можете определить его самостоятельно на всех языках, которые поддерживают параметры типа в той или иной форме (шаблоны, шаблоны ...). Для Java есть хороший JavaTuple lib.

0 голосов
/ 20 июля 2010

Я думаю, что вопрос касается выделения памяти и организации стека. Главное - переключение контекста во время вызова функции.фрейм функции хранится в стеке, фрейм содержит переменные функции, регистры общего назначения и возвращаемые значения. Я знаю, что много

...