Ошибки PascalABC.NET

Я уже ответил раньше, что спрашивал не про DownTo, а про LineTo с лямбдами, это следующая исправленная версия.

Да, прошу прощения, это другой человек про DownTo говорил.

Это был я. Причина “неисправности” была понятна по исходному коду модуля, Но я не могу исправить её самостоятельно, потому что у всех остальных всё останется по-прежнему. Сейчас всё нормально. Спасибо!

Процедура Sort в версии // PascalABC.NET 3.2, сборка 1361 от 12.12.2016 “сломалась”:

Program1.pas(3) : С данным списком формальных параметров невозможно вызвать
ни одну из перегруженных generic-подпрограмм Sort

Появилась очередная, доступная для обновления сборка 1362 от 14.12.2016. С напрочь поломанным Intellisence. Печально, что отката на предыдущую версию нет. И да, Sort(a,cmp) в ней по прежнему не починена.

Странно. Перезагрузил ПК и Intellisence заработал. Чудеса…

Выше уже было написано, что теперь надо по другому писать:

Я посмотрел исходники, там убрали сортировку с логическим условием. Вроде, её можно было спасти, написав что-то типа

System.Array.Sort(a,(x,y)->less(y,x)?(less(x,y)?0:1):-1); 

хотя это не особо оптимально проверять x=y в два шага через отрицание x>y и y<x.

И получилось весьма малополезно.

В самом деле, обычно нужна не просто сортировка по возрастанию/убыванию, нужна сортировка по некоторому ключу, который совершенно не обязательно приводИм к integer. Если для массива символов еще как-то можно получить integer через Chr, то как отсортировать массив типа real? Как отсортировать массив, элементы которого - символьные строки? Как отсортировать только элементы с четными значениями, оставив на своих местах прочие элементы?

И как после всего этого говорить (см. демо-ролик на сайте)

Стандартные процедуры Sort и Reverse позволяют решать более сложные задачи. Процедура Sort содержит эффективный алгоритм (быстрая сортировка).При реализации этих процедур вручную ученикнередко допускает ошибки.Код на старом Паскале –ужасен

Еще раз: просто сортировка одномерных массивов типа integer не покрывает и половины всех задач, которые сейчас задают школьникам. По-хорошему, нужна сортировка по ключу, причем отнюдь не предварительно втиснутому в кортеж, заранее созданный из массива.

Сейчас решение получается кривым и менее понятным, чем вручную написанная сортировка.

  1. создаем из массива кортеж (<ключ сортировки><сам элемент>)
  2. сортируем кортеж по ключу
  3. создаем на базе кортежа массив

Такой подход не менее полезен и достаточно стандартен. Ведь функция “сравнить” имеет как минимум три варианта (больше, меньше, равно), вот её часто и кодируют тремя числами (-1,0,1) вместо логической переменной. Просто неудобно всё переписывать.

Мы пока думаем, как можно исправить ситуацию с сортировкой. Нам тоже оба варианта не нравятся

Думать можно много, долго и даже полезно)))) Но наверно не самым глупым решением тут может быть “СУБДшный подход”: там ведь сортировка - одно из самых популярных средств при получении выборок для отчетов. Обратите внимание на конструкции во фразе ORDER BY, где как раз и описывается ключ сортировки, который вовсе не обязан существовать, как поле в таблицах базы данных. Ключ - произвольное выражение и его тип не фиксирован, требуется лишь, чтобы ключи можно было сравнивать. Совершенно тривиальный случай, когда сортировка проводится по набору полей, к примеру ORDER BY Kurs, Vozrast DESCENDING, Fam, Nam, Otch, но если придется делать - почему нет?

Обычная сортировка Sort(x) ведь уже есть и она эффективная. А сортировка по ключу нужна для учебных задачек, там нет больших объемов и можно позволить себе и не обязательно эффективнейшую реализацию. Нужна ведь всего лишь процедура, не расширение.

Это всё понятно. Стандартная .NET-функция работает с критерием сравнения, возвращающим целое. И промоделировать его функцией < просто и правильно не получается.

Вариант

я хотел было использовать, но мне он не нравится как неэффективный.

Я не услышал: как предлагается в этих условиях сортировать массив, скажем, фамилий? Через (x,y)->Compare(x,y) ?

Или, как в C#, писать что-то свое, реализующее интерфейс IComparer?

В .NET все встроенные типы реализуют интерфейс IComparable. Это значит, что сортировать придётся так:

Sort(ss,(s1,s2)->s1.CompareTo(s2))

Что собственно эквивалентно

Sort(ss)

В .NET конечно есть и модификация Sort с параметром IComparer, но мы не хотим этот метод выносить на уровень стандартной библиотеки

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

В любом случае, у функции с двумя логическими значениями ограничений больше, чем с целыми. Помнится, ещё в Turbo Pascal в TCollection так уже делали. А что касается баз данных, то SQL Server вроде до сих пор не умеет ORDER BY в представлениях (view) делать. Это всё просто когда индексы уже где-то заранее записаны.

Сортировки во вьюшках умел делать даже Microsoft Visual FoxPro от версии 7.0 (может и раньше, но семерка точно). А для MS SQL надо писать

CREATE VIEW dbo.OrderByDateView
AS
    SELECT TOP 100 PERCENT Field1, Field2, Date1
    FROM Table1
    ORDER BY Date1

Я последний раз столкнулся с “проблемой” сортировки по ORDER BY в SQL Server 2014 и там это явно описано на сайте. Вот вчера очередное обновление SQL Server 2016 поставил, не проверял. Но сам факт говорит, что это не очень просто.

TOP 100 шугает оптимизатор и все получается)) И потом - ну кто мешает по вьюшке сделать SELECT с ORDER BY ?

В любом случае, когда пишешь ORDER BY наивно ожидаешь что тебе результат отсортируют, а потом читаешь где-то внизу:

When used with a SELECT…INTO statement to insert rows from another source, the ORDER BY clause does not guarantee the rows are inserted in the specified order.

Наверное всё-таки

System.Array.Sort(a,(x,y)->less(y,x)?1:(less(x,y)?-1:0));

А по поводу неэффективности, разве нельзя оставить обе функции? Кто-то может пользоваться эффективной, кто-то более наглядной. Или там с перегрузкой проблемы?