LINUX.ORG.RU

В каких ЯПах существуют функции, способные возвращать несколько значений?

 , , ,


0

0

Вроде такого:

int, double, double add (int a) {
    return (a+1), (a+2.2), (a+3.3);
}

int a = 8;
int b;
double c, d;

b, c, d = add(a);

А вообще, в чем проявлялась бы неэффективность подобной возможности? Могу представить разве то, что она не так хорошо приспособлена к трансляции в ассемблерный код как функция с единичным возвращаемым значением. Так по конвенции все кладут результат в RAX да и все, а с множественными значениями придется еще что-то изобретать и ломать ABI.

Ответ:

Список япов:

  1. go
  2. lua
  3. haskell
  4. rust и проч.

Реализованы - через тульпы/структуры, поэтому в abi ничего не меняется. Но есть и более интересные вариации: так, например, в SBCL первые три возвращаемых значения передаются через регистры (RDX, RDI, RSI), а остальные через стек



Последнее исправление: x86- (всего исправлений: 6)
Ответ на: комментарий от xmikex

создавать структуру - это что-то изобретать?

Структура - это такой себе объект, можно считать. И в RAX все так же кладут ссылку на этот единый объект, а не сами значения ее полей.

x86-
() автор топика

Наверно во всех, в которых есть кортежи. И это не какая-то магия, это же просто анонимная структура из 3-х полей.

anonymous-angler ★☆
()

О, все же такие есть, и не один.

  • c++17
  • питон
  • go
  • rust

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

x86-
() автор топика
Ответ на: комментарий от x86-

Там происходит примерно то же, что здесь:

#include <stdio.h>
#include <stdlib.h>

typedef struct {
    int a;
    double b;
    double c;
} Foo;

Foo add(int a) {
    return {
        a + 1,
        a + 2.2,
        a + 3.3
    };
}

int main() {
    int a = 8;
    
    int b;
    double c, d;
    
    Foo foo = add(a);
    
    b = foo.a;
    c = foo.b;
    d = foo.c;
    
    printf("%d %lf %lf", b, c, d);
    
    return 0;
}
anonymous-angler ★☆
()
Ответ на: комментарий от anonymous-angler

А, поняла. Ну все, тему помечаю решенной

x86-
() автор топика
Ответ на: комментарий от x86-
...
mov     eax, dword ptr [rsp + 8]
mov     ecx, dword ptr [rsp + 12]
mov     edx, dword ptr [rsp + 20]
mov     dword ptr [rsp + 24], edx
mov     dword ptr [rsp + 28], ecx
mov     dword ptr [rsp + 32], eax
mov     eax, dword ptr [rsp + 32]
mov     edx, eax
mov     rax, qword ptr [rsp + 24]
add     rsp, 40
ret
sudopacman ★★★★★
()
Последнее исправление: sudopacman (всего исправлений: 1)

Почти во всех есть, вот в haskell:

add a = (a, fromIntegral a + 2.2, fromIntegral a + 3.3)

...

a = 8
(b, c, d) = add a

Waterlaz ★★★★★
()

В каких ЯПах существуют функции, способные возвращать несколько значений?

а зачем?

anonymous
()
Ответ на: комментарий от sudopacman

Это с раста скомпилировано? А результат как я и ожидала, возвращаемая тульпа передается через стек, а в rax засовывают адрес тульпы

x86-
() автор топика

Нужна именно функция? Чем процедура для разнотипных переменных не устраивает?

grem ★★★★★
()
Ответ на: комментарий от anonymous

а зачем?

Ну теоретически интересно стало для расширения кругозора. Я из ЯПов в основном засиживаюсь на с/с++(младших стандартов). Но судя по тому, что это реализовано в каждом втором языке, фича чем-то полезна, хотя и является просто синтаксическим сахаром

x86-
() автор топика

В c++ есть std::make_tuple.

grem ★★★★★
()
Ответ на: комментарий от grem

Нужна именно функция? Чем процедура для разнотипных переменных не устраивает?

Типа процедуры с параметрами-указателями? Вообще всем устраивает, но вдруг интересно стало, может где-то это возможно провести без побочек нативными методами языка.

x86-
() автор топика
<?php
/**
 * @return array{0: int, 1: float, 2: float}
 */
function add (int $a): array
{
	return [$a + 1, $a + 2.2, $a + 3.3];
}
$a = 8;
[$b, $c, $d] = add($a);
fernandos ★★★
()
Ответ на: комментарий от x86-

Расширить кругозор можно, изучив, например, Рефал. Вот это будет расширением кругозора. А это все из пустого в порожнее.

является просто синтаксическим сахаром

собственно, и все, что за этим стоит.

фича чем-то полезна

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

anonymous
()
Ответ на: комментарий от x86-

Типа процедуры с параметрами-указателями?

В некоторых языках всегда по ссылке передаются значения, не нужно возиться с указателями.

grem ★★★★★
()
Ответ на: комментарий от WitcherGeralt

Ну вот,пришёл и всё испортил :)

grem ★★★★★
()
Ответ на: комментарий от Harald

Нет, питон возвращает тапл. Просто ты тут же делаешь деструктуринг и даже не знаешь об этом.

WitcherGeralt ★★
()
Последнее исправление: WitcherGeralt (всего исправлений: 1)
Ответ на: комментарий от grem

В некоторых языках всегда по ссылке передаются значения, не нужно возиться с указателями.

Это ты о джаве сейчас с ее implicit ссылками на объекты? Брр.

x86-
() автор топика
Ответ на: комментарий от x86-

В 2003 стандарте появился атрибут value.

Угу, просто сразу не вспомнил когда именно.

grem ★★★★★
()
Последнее исправление: grem (всего исправлений: 1)
Ответ на: комментарий от x86-

В C со структурой то же самое. Но стоит учитывать, что код может оптимизироваться компилятором.

sudopacman ★★★★★
()
Последнее исправление: sudopacman (всего исправлений: 1)
Ответ на: комментарий от fernandos

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

WitcherGeralt ★★
()
Последнее исправление: WitcherGeralt (всего исправлений: 2)
Ответ на: комментарий от WitcherGeralt

Мне интересны были именно варианты синтаксического сахара, которые в том же С, например, отсутствуют. Так-то понятное дело, везде под капотом тульпы/структыры.

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

x86-
() автор топика
Ответ на: комментарий от WitcherGeralt

Тут проще будет назвать ЯП в которых нельзя вернуть массив.

Господи, вы серьёзно? Какая разница, в чём передаются данные, важно лишь, что нужно программисту для достижения цели.

Или вы думаете, что в плюсах значения магическим образом перепрыгуют в переменные?

fernandos ★★★
()
Ответ на: комментарий от x86-

варианты синтаксического сахара

В данном случае сахар — это destructuring assignment, и он вообще к возврату из функции никакого отношения не имеет. Так развернуть можно любой тапл. И не только тапл.

В Go, например, всё легально. Понятно, что под капотом тоже наверняка есть какой-то враппер, но на уровне языка возвращается именно несколько значений, а никакой не массив.

WitcherGeralt ★★
()
Ответ на: комментарий от fernandos

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

WitcherGeralt ★★
()

Паскаль же

program ololo;
uses sysutils;

procedure add(a: integer; out b: integer; out c, d: double);
begin
    b := a + 1;
    c := a + 2.2;
    d := a + 3.3;
end;

var
  a: integer = 8;
  b: integer;
  c, d: double;

begin
  add(a, b, c, d);
  writeln(format('%d %d %n %n', [a,b,c,d]))
end.

superuser ★★★★☆
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.