1

Тема: Кортежи

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

В самом деле, я не понимаю концепцию кортежей в некоторых языках, где кортеж можно/нужно инициализировать функцией типа tuple(), а потом к его членам можно обращаться по индексу. Чем в этом случае кортежи отличаются от массивов? Авторы языков наверняка придумали какие-то объяснения, но в моих глазах это всегда будет игрой словами.

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

На Хабре есть статья про кортежи в разных языках, ее автор сетует на логическую незавершенность концепции кортежей в Go:

func foo() (r1 int, r2 int) {
     return 7, 4
}
x, y := foo()
x, y = 1, 2
x, y = y, x

func bar(x int, y int) {
}

func barz(x int, y int, z int) {
}

bar(foo())
barz(foo(), 100) <-- так нельзя, не работает

Тот же пример на Канторе:

foo[out Core:Integer r1, r2] of
  return 7, 4;
end;

(x, y) = foo; // кантование
// (x, y) -- функция
// остальные примеры невоспроизводимы

bar(Core:Integer x, y) of
end;

barz(Core:Integer x, y, z) of
end;

bar(foo);
//barz(foo, 100); // не работает

with
  (x, y) = foo;
do
  barz(x, y, 100);
end;

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

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

(x, y) = foo;
a = x; // возвращает 7

Пока не могу понять, является ли это каррированием или его разновидностью.

2

Re: Кортежи

Благодаря кортежам операция целочисленного деления в Канторе соответствует машинной:

(quotinent, remainder) = 10 \ 3;

Для совместимости есть также перегруженная операция деления:

quotinentOnly = 10 \ 3;

Поскольку естественная запись операций в Канторе -- синтаксический сахар вызовов функций, в объектном коде всё выглядит так:

10.Divide(3, quotinent, remainder);
10.Divide(3, quotinentOnly);

В такой записи перегруженные операции уже не кажутся чем-то необычным.