Аналог System.ValueTuple для PascalABC.NET

Написал аналог System.ValueTuple для PascalABC.NET: TuplesABC.rar (17,4 КБ)

У нас давно был разговор на счёт оптимальности использования ссылочных кортежей и было сказано, что это не очень оптимально. Разработчики отказались от использования System.ValueTuple, поэтому предлагаю свой аналог. Только, если это включать в стандартные модули, желательно сделать такой же синтаксис объявления примерно, как и для обычных кортежей (для удобства) и возможность их деконструирования в переменные следующим образом:

uses TupleABC;
begin
  var (x, y) := VRec(2, 5);
end.

Возможный вариант синтаксиса:

uses TupleABC;
begin
  var (x, y) := $(2, 5);
end.

, а для псевдонимов типов:

uses TupleABC;
type
  T = $(integer, integer);

begin
end.
1 лайк

Маленькая поправка: это не у нас был разговор, а у Вас. Разработчики PascalABC.NЕТ не раз замечали, что вопросы оптимизации для них не являются главными и я, к примеру, с ними полностью солидарен в этом мнении.

И всё-же беседовали мы все (активные участники форума) одной компанией. :slight_smile:

А приведите еще раз пожалуйста тесты на быстродействие Tuple vs ValueTuple. Так ли уж Tuple не оптимальны?

Вот одно из сравнений:

Тот тест довольно поверхностный. Самое полезное применение ValueTurple - это возвращаемое значение:

uses System.Runtime.CompilerServices;

[MethodImpl(MethodImplOptions.NoInlining)]
function f1<T1,T2>(a: T1; b: T2) := System.Tuple.Create(a,b);

[MethodImpl(MethodImplOptions.NoInlining)]
function f2<T1,T2>(a: T1; b: T2) := System.ValueTuple.Create(a, b);

begin
  var LC := 100000000;
  
  var sw := new System.Diagnostics.Stopwatch;
  
  var vv1 := 1;
  var vv2 := 'd';
  
  sw.Restart;
  loop LC do
  begin
    
    var t := f1(vv1, vv2);
    vv1 := t.Item1;
    vv2 := t.Item2;
    
  end;
  sw.Stop;
  writeln(sw.Elapsed);
  
  sw.Restart;
  loop LC do
  begin
    
    var t := f2(vv1, vv2);
    vv1 := t.Item1;
    vv2 := t.Item2;
    
  end;
  sw.Stop;
  writeln(sw.Elapsed);
  
  var rv1 := new class(o := new object);
  var rv2 := 'string';
  
  sw.Restart;
  loop LC do
  begin
    
    var t := f1(rv1, rv2);
    rv1 := t.Item1;
    rv2 := t.Item2;
    
  end;
  sw.Stop;
  writeln(sw.Elapsed);
  
  sw.Restart;
  loop LC do
  begin
    
    var t := f2(rv1, rv2);
    rv1 := t.Item1;
    rv2 := t.Item2;
    
  end;
  sw.Stop;
  writeln(sw.Elapsed);
  
  readln;
end.
00:00:00.9450133
00:00:01.1806477
00:00:01.8734180
00:00:01.6393803

Правда, почему ValueTuple работает медленнее с value-типами, чем Tuple - я объяснить не могу.

2 лайка

Хороший тест, спасибо. Но в одном случае на 20 процентов лучше, а во втором на 20 процентов хуже. Шило на мыло.

И под Windows XP - всё ещё распространённой ос для Pascalabc.NET - новые кортежи работать не будут.

Да, поэтому я и предложил самописный их аналог.

А вот посудите сами - это означает, что им никак нельзя будет воспользоваться из программы на C# и наоборот - подключив C#-программу, придётся писать System.Tuple.

Это если полностью заменить на них.

А вам выше предложили этот синтаксис:

begin
  var tuple: (byte, word) := (0,1);
  var value_tuple: $(byte, word) := $(0,1);
end.
1 лайк

Да, спасибо. А в чём смысл двух практически одинаковых синтаксически сахарных конструкций в языке?

Вот те 20% преимущества в случае, если умеешь ими правильно пользоваться.

Дополнительный синтаксический сахар - это замусоривание языка. А без сахара - можно создать свой класс и им пользоваться.

Не придётся, если оформить эти кортежи в виде библиотеки. Тем более в C# есть уже свой System.ValueTuple<T, T2, ...>. Так что по сути это по большей части только для Паскаля делается (в C# и так своя реализация таких кортежей есть). В итоге (если кортежи такие будут включены в язык) и Паскаль будет иметь свои средства для работы с значимыми кортежами. Не везде же держаться за совместимость с C#. Так, у нас, например, операторы могут быть обобщёнными, но в C# - нет. В C# мы не смогли бы использовать такие операторы, но ведь они реализованы в Паскале, не смотря на отсутствие их в C#. И ещё: не должен же быть Паскаль вторым C# - в этом нет смысла, он должен иметь (и уже имеет) свои особенности.

Это дополнительная работа, которая будет ложиться на плечи программиста. Если же эти средства будут в языке, то работать будет легче. Мы ведь не пишем, например, везде обычные свойства - где можно - пользуемся автосвойствами. Это тоже ведь синтаксический сахар. Но ведь, это же не

не правда ли? Да и свойства как таковые - тоже синтаксический сахар по сути - это ведь просто два метода геттер и сеттер. Примеров синтаксического сахара в Паскале можно ещё много привести, например:

  1. loop
  2. lock
  3. срезы
  4. методы расширения (ведь, это фактически просто статические методы, которое можно вызывать в формате objectName.Method({parameters}))
  5. И так далее
1 лайк

13 сообщений перенесены в новую тему: Бесполезные улучшения PascalABC.NET

@Admin, так что на счёт моего модуля?

В смысле включения его как стандартного?

Мне не кажется эта идея хорошей.

Да.

Ну, как выше уже было показано, значимые кортежи - более производительны. Можно включить в стандартный пакет пока только модуль, а синтаксический сахар (предложенный выше) сделать потом. Если Вы можете посоветовать - что доработать - с радостью.

  1. Я не вижу никакой лучшей производительности значимых кортежей. 20% плюс-минус в разных ситуациях.

  2. C#, на который вы ссылаетесь, не имеет двух сахарных конструкций для одной возможности, потому что это плохой дизайн языка.

  3. В C# уже есть System.ValueTuple. Те, кому важна производительность, установят версию .NET 4.7 и будут ими пользоваться.

Конечно, меня радует, что вы сделали такую серьёзную попытку улучшить с вашей точки зрения язык - это - немало труда и мыслей. Но - в другое бы русло.