Об одномерных динамических массивах.
Чем больше смотрю на их поведение в версии 3, тем больше ощущение, что это те же списки, только с возможностью обращения к каждому элементу по его индексу. Одномерный массив математически прочно ассоциируется с n-мерным вектором, но ведут себя эти массивы отнюдь “не по векторному”, а как последовательности, что еще раз подтверждает написанное выше.
Пусть имеем следующий фрагмент программы:
var a:=Arr(1,2,3,4);
var b:=Arr(5,6,7,8);
var c:=a+b;
Println(c);
С точки зрения математики тут все понятно: вектор с должен быть равен сумме векторов a и b, т.е. c[i]:=a[i]+b[i], i=imin…imax
Но нынешняя реализация языка поступает с массивами, как с последовательностями и приписывает компоненты массива b “в хвост” компонентам массива а, так что запустив программу на выполнение, мы обнаружим на выводе 1 2 3 4 5 6 7 8, а вовсе не 6 8 10 12, как предписывает математика.
Что такое в математике a*2, если a - вектор? Вектор такой же размерности, полученный умножением исходного вектора на скаляр, т.е. a[i]*2, i=imin…imax
А что даст такая конструкция в PascalABC.Net 3.1? Все логично, a*2 равнозначно a+a и мы получим исхдный массив, повторенный дважды, т.е. 1 2 3 4 1 2 3 4 Но хотелось бы получить как в математике- 2 4 6 8
Потому что если бы мы объявили не массивы, а последовательности - вот тут как раз все совершенно логично, тут должно происходить именно приписывание.
А что даст с=a-b (а также c=a*b и c=a/b) в контексте приведенного ранее фрагмента программы. Я думаю, уже все догадались - ошибку при компиляции. А что хотелось бы? Да все по той же аналогии с векторами, чтобы c[i]=a[i] op b[i], где op - знак операции +, -, *, /
Тогда и думать не надо, как инициализировать массив, например, единичным значением, достаточно будет написать c:=1;
Это первое. Далее. Присваивание с=<нечто, приведенное к массиву>.
сейчас оно реализовано присваиванием ссылки. Когда в правой части оператора присваивания стоит выражение, насколько я понимаю, мы чаще всего получаем ленивую операцию и это отлично. Но вот когда там стоит массив, передача ссылки на него всего лишь создает массиву второе имя. А это нехорошо. Ну зачем в программе обращаться к массиву с двумя разными именами? В инструктивных материалах нам объясняют, что “во избежание…” мы можем воспользоватся функцией copy(), но, быть может, для случая явного прямого присваивания вида c:=a вызывать Copy автоматически?
Есть такая мощная штука в массивах… В Фотране она называется “сечением”. Там выражение вида a(3:7) для одномерного массива означает, что из него делается “вырезка”, наследующая свойства своего родителя, но содержащая только переиндексированные элементы a(3), a(4), … a(7). Хочу такое и в Паскале! А если серьезно, очень удобная вещь, особенно для многомерных массивов. Но если начинать, то начинать с одномерных. И подумать, получится ли разрешать сечения в левой части оператора присваивания. Т.е. нечто вроде c[3:5]:=b[1:3]. Подумать потому, что тогда должно корректно работать и a[m:n]:=a[p,q], возможно даже с пересечением областей сечений.
Конечно, это лишь крохи того, что умеет делать с массивами Фортран, но ведь задачи подменить Фортан и не ставится. В то же время, почму не взять из него еще несколько полезных функций? Но об этом пока не стану писать, потому что если разработчики по тем или иным причинам не станут описанного тут (естественно, преломленного к своему проекту) делать, то и предмета для развития темы не будет.