Функции, возвращающие кортежи, против процедур с выходными параметрами
Если подпрограмма вычисляет несколько выходных значений, то ее можно оформить либо как процедуру с передаваемыми по ссылке выходными параметрами, либо как функцию, возвращающую кортеж.
Сравним оба способа по читаемости и производительности.
Задача. Пусть нам следует вычислить периметр и площадь треугольника со сторонами x и y.
Решение 1. Составим процедуру с двумя входными и двумя выходными параметрами. Измерим производительность:
procedure CalcPerimeterSquare(x,y: integer; var P,S: real);
begin
P := 2*(x+y);
S := x*y;
end;
begin
var n := 100000000;
var sw := new Stopwatch;
sw.ReStart;
loop n do
begin
var P,S: real;
CalcPerimeterSquare(2,3,P,S);
end;
sw.Stop;
Print(sw.ElapsedMilliseconds);
end.Данный код выполняется очень быстро:
46 мс
Решение 2. Реализуем вычисления в виде функции, возвращающей кортеж из двух значений:
function PerimeterSquare(x,y: real) := (2*(x+y), x*y);
begin
var n := 100000000;
var sw := new Stopwatch;
sw.Start;
loop n do
begin
var (P,S) := PerimeterSquare(2,3);
end;
sw.Stop;
Print(sw.ElapsedMilliseconds + ' мс');
end.Код гораздо короче, но будет ли он быстрее?
292 мс
Однако вычисления здесь - простые: для вычисления площади и периметра используется два умножения и одно сложение.
Если рассмотреть более сложные вычисления, то именно они примут на себя основной удар, и разница по времени станет ничтожно мала:
procedure CalcPerimeterSquare(x,y: integer; var P,S: real);
begin
P := Sin(Exp(x) + Ln(y));
S := Tan(Exp(y)-Cos(x));
end;
begin
var n := 100000000;
var sw := new Stopwatch;
sw.ReStart;
loop n do
begin
var P,S: real;
CalcPerimeterSquare(2,3,P,S);
end;
sw.Stop;
Print(sw.ElapsedMilliseconds + ' мс');
end.function PerimeterSquare(x,y: real)
:= (Sin(Exp(x) + Ln(y)), Tan(Exp(y)-Cos(x)));
begin
var n := 100000000;
var sw := new Stopwatch;
sw.Start;
loop n do
begin
var (P,S) := PerimeterSquare(2,3);
end;
sw.Stop;
Print(sw.ElapsedMilliseconds + ' мс');
end.Время работы примерно одинаково.
Заключение. Функции, возвращающие кортежи, - заманчивая синтаксическая возможность, укорачивающая код. Если вычисления достаточно долгие, то функции, возвращающие кортежи, - предпочтительный выбор. Если же вычисления - простые, то процедуры с параметрами-переменными работают значительно эффективнее.