Метод расширения Print имеется именно у последовательностей. Список это последовательность. Поэтому список наследует эту операцию.
Переопределять одинаковый Print у разных контейнеров - нецелесообразно.
Метод расширения Print имеется именно у последовательностей. Список это последовательность. Поэтому список наследует эту операцию.
Переопределять одинаковый Print у разных контейнеров - нецелесообразно.
И динамический массив, если его распечатать. превращается в последовательность, т.е если первоначально с массивом можно писать a.Where((x,i)->i.IsOdd).Println, то a.Println.Where((x,i)->i.IsOdd).Println уже не проходит. Как-то это привычно стало и не вызывает вопросов…
Это примерно как отношение “блондинок” к зеркалу: “Зеркало меняет местами право и лево, но не меняет верх и низ - ничего, я привыкла” )))
Метод расширения для последовательностей:
function Println(Self: List): List; extensionmethod;
begin
Println(Self);
Result := Self;
end;
В модуле не компилируется, а в библиотеке всё нормально.
Не знаю, кому и зачем это нужно, но интересно…
А сегодня всё компилируется:
// ПЕЧАТАЕМ ЧИСЛО ТИПА integer
function Println(Self: integer): integer; extensionmethod;
begin
Println(Self);
Result := Self;
end;
// ПЕЧАТАЕМ ЧИСЛО ТИПА BigInteger
function Println(Self: BigInteger): BigInteger; extensionmethod;
begin
Println(Self);
Result := Self;
end;
// ПЕЧАТАЕМ ЧИСЛО ТИПА int64
function Println(Self: int64): int64; extensionmethod;
begin
Println(Self);
Result := Self;
end;
// ПЕЧАТАЕМ СПИСОК
function Println(Self: List): List; extensionmethod;
begin
Println(Self);
Result := Self;
end;
С НОВЫМ ГОДОМ!
С наступившим! Не знаю, относится ли это к теме именно данного поста, но где-то с 10 января проект из GitHub перестал собираться. Вот и сегодняшняя версия тоже. До этого просто загружал PascalABCNET.sln в Visual Studio Community 2015, нажимал пересобрать и получал работающий PascalABCNET.exe
Этот код вызывает внутреннюю ошибку компилятора
[code]procedure insert(var a: array of T; var n:integer; k:integer; value:T); begin a := a[:k] + arr(value) + a[k:]; end;
begin var a := arrrandom(10, 1, 5); a.Println; var n := 9; insert(a, n, 3, 666); a.Println; end.[/code] А если вынести вставку из процедуры и удалить/закомментировать процедуру, все работает
begin
var a := arrrandom(10, 1, 5);
a.Println;
var n := 9;
a := a[:3] + arr(666) + a[3:];
a.Println;
end.
Если процедуру оставить, то ошибка. Это я косячу, или это баг Паскаля?
Внутренняя ошибка компилятора - это всегда баг Паскаля. У нас её нет, но всё равно не работает.
Поместили в Issues:
Исправили. Версия на сайте.
За нахождение бага компилятора - NikitaOdnorob - 3 бонусных балла плюс
Обновил до новой версии. Теперь срез от среза не работает. Как починить?
Program1.pas(7) : Сахарный узел slice_expr не должен обходиться в syntax_tree_visitor. Обратитесь к разработчикам PascalABC.NET
Так можно до рекурсии срезов дойти…
Исправили. Новая версия на сайте
Да, работает. Спасибо за оперативностью.
Увидел на GitHub комментарий a[:][:] и со щенячьим восторгом полез делать срез матрицы. А вот фиг! Какое жестокое разочарование… оказался срез от среза… (((
Синтаксис срезов матриц резонно делать таким: a[2:3,3:5]. Вам такое будет достаточно?
Естественно. Делать срезы с шагом - это экзотика, которая нужна бывает раз в году. И то, не в каждом))). Я себе пока написал модуль вот с такими вещами - это не все, конечно, но часто выручает с задачками.
Реализовал как функции и как расширения.
/// Матрица в динамический массив по строкам
function MatrRowsScatter<T>(a:array[,] of T):array of T;
/// Матрица в динамический массив по столбцам
function MatrColsScatter<T>(a:array[,] of T):array of T;
/// Формирование матрицы из динамическоно массива построчно
function MatrRowsGather<T>(a:array of T;rows,cols:integer):array[,] of T;
/// Формирование матрицы из динамического массива поколонно
function MatrColsGather<T>(a:array of T;rows,cols:integer):array[,] of T;
/// Срез матрицы
function Slice<T>(a:array[,] of T;rfrom,rto,cfrom,cto:integer):array[,] of T;
А я думал, Вы захотите конструкцию с вырезанием из матрицы одной строки и одного столбца, что нужно, скажем, при вычислении определителя
Slice легко вырежет это. Собственно, у меня уже вырезает, но это же только у меня))) Кроме того, есть же Row() и Col(). Но вот подматрицу может вырезать только Slice. A Scatter/Gather позволяет во всей матрице сделать ту или иную выборку, которую можно делать для динамического массива. Можно переформатировать матрицу, например, сделать из 4х5 размер 10х2
Вот пример.
// PascalABC.NET 3.2, сборка 1382 от 06.02.2017
uses Matr;
begin
var n:=ReadInteger('Количество строк в массиве:');
var m:=ReadInteger('Количество столбцов в массиве:');
Writeln('*** Исходный массив [',n,',',m,'] ***');
var a:=MatrRandom(n,m,-10,10);
a.Println(4); Writeln(4*a.ColCount*'-');
var i:=a.MatrRowsScatter.IndexMax;
(var mr,var mc):=(i div m,i mod m);
Writeln('Первый максимум построчно a[',
mr+1,',',mc+1,']=',a[mr,mc]);
i:=a.MatrColsScatter.IndexMax;
(mr,mc):=(i div n,i mod n);
Writeln('Первый максимум поколонно a[',
mc+1,',',mr+1,']=',a[mc,mr]);
end.
Количество строк в массиве: 6
Количество столбцов в массиве: 9
*** Исходный массив [6,9] ***
5 6 1 -2 7 -1 -3 -1 4
-6 3 -9 0 -7 -5 -7 1 -2
0 10 7 1 2 -2 -7 8 -9
10 9 -6 -1 -1 -4 6 9 3
9 -5 -7 6 3 -7 -9 5 9
7 8 -5 -7 5 8 -10 -4 -10
------------------------------------
Первый максимум построчно a[3,2]=10
Первый максимум поколонно a[4,1]=10
Ну, можно для этого сделать метод IndexMax, возвращающий кортеж
Можно. Но “рассыпая” матрицу в одномерный массив по строкам или столбцам, мы сразу получаем для её элементов все, что уже есть для динамических массивов. Причем, разворачивать её можем как по строкам, так и по столбцам. А для “особо одаренных” можно сделать функции преобразования одномерного индекса в двумерный (и наоборот) при известном числе колонок. Вот там кортеж в параметрах и возвращаемом значении - самое оно.
Кстати, еще и для обучения полезно: лишний раз напомнит, что двумерный массив в памяти тоже как одномерный и хранится, и обрабатывается )))