Конкретнее выражайтесь, это ничего не говорит.
И - та функция всё равно дубль, оригиналы всех для работы с путями к файлам - в классе System.IO.Path.
Конкретнее выражайтесь, это ничего не говорит.
И - та функция всё равно дубль, оригиналы всех для работы с путями к файлам - в классе System.IO.Path.
Наверное вы её неправильно использовали
Вот к примеру небольшой код, использующий стороннюю библиотеку для распаковки архива. Исходник лежит в папке с игрой Skyrim.
{$reference 'SharpCompress.dll'}
uses SharpCompress, SharpCompress.Archives;
begin
try
var archive: SharpCompress.Archives.IArchive := SharpCompress.Archives.ArchiveFactory.Open(ExtractFilePath(GetEXEFileName) + 'Skyrim\Updates\Enhanced_Blood_Textures_LITE.rar', nil);
var EO := new SharpCompress.Common.ExtractionOptions;
EO.ExtractFullPath := true;
EO.Overwrite := true;
foreach var entry in archive.Entries do
if not entry.IsDirectory then entry.WriteToDirectory(ExtractFilePath(GetEXEFileName) + 'Mod Organizer\mods\', EO);
except
on System.DivideByZeroException do
writeln('Деление на 0');
on e: System.IndexOutOfRangeException do
writeln(e.Message);
on System.FormatException do
writeln('Неверный формат ввода');
else writeln('Какое-то другое исключение');
end;
end.
Если в настройках не отрубить функцию “Выходные файлы генерировать в директорию такую-то”, то программа будет сыпать ошибку:
Ошибка времени выполнения: System.IO.FileNotFoundException: Не удалось загрузить файл или сборку “SharpCompress, Version=0.23.0.0, Culture=neutral, PublicKeyToken=afb0a02973931d96” либо одну из их зависимостей. Не удается найти указанный файл. Стек: в 1.Program.$Main() в 1.Program.Main()
По моему уже был разговор про это здесь. Но разработчики то ли не прочитали, то ли проигнорили… В общем сделал issue, теперь точно заметят:
Не помню, предлагалось уже или нет…
function ToDigits(self: integer): sequence of integer; extensionmethod;
begin
if self<0 then
if self=integer.MinValue then
begin
yield 2;
self := 147483648;
end else
self := -self;
var d := 1;
var m := self div 10;
while d<=m do d *= 10;
while d <> 0 do
begin
yield System.Math.DivRem(self,d,self);
d := d div 10;
end;
end;
begin
(12345).ToDigits.Println;
(10000).ToDigits.Println;
integer.MaxValue.ToDigits.Println;
(-12345).ToDigits.Println;
integer.MinValue.ToDigits.Println;
end.
(ну и по аналогии с int64
и может BigInteger
)
Подтолкнуло написать это: http://www.cyberforum.ru/pascalabc-net/thread2551911.html#post14087426
Предложение однозначно хорошее, на мой взгляд, поэтому:
Хорошо бы было (с моей точки зрения), если бы в PascalABC.NET:
ToDo
Git
и возможность работать с GitHub
Я не настаиваю и вряд ли стал бы по следующей причине - PascalABC.NET не гонится за такими гигантами, как Visual Studio
/Rider
(хотя, некоторые вещи бывает просят перетянуть из них и сюда), также ориентирован на начинающих.
Если бы (возможно, в будущем) данный проект решил бы развиваться по пути профессиональных IDE
, то я бы предложил бы эти два нововведения (хотя, очень вероятно, что заниматься ими начали сами разработчики и без моего напоминания). В то же время, тогда бы встал вполне понятный вопрос: Зачем это всё нужно в IDE, если ниша данного языка - начинающие?
. Да, конечно, иметь дополнительный функционал, который может пригодится - хорошо, но ведь, нишу “производственную” уже заняли другие IDE, такие как Visual Studio
и Rider
и насколько будет он (функционал) использоваться в PascalABC.NET - неизвестно (для ответа на данный вопрос надо чётко знать потребности пользователей), в то время как - это трата времени (вполне возможно впустую) разработчиков, которое они бы могли потратить на увеличение стабильности работы IDE (улучшение Intellisence
, например).
Любые навески к IDE затрудняют работу начинающих (этим разные Студии всегда отпугивают новичков). Потому что видишь непонятный функционал и начинаешь думать, вдруг он нужен тебе, вдруг он - обязательная вещь для работы?. Ну т.е. если мы впервые садимся за управление современного автомобиля, поражает обилие разных кнопочек, ручечек и сигнальчиков. При этом мы догадываемся, что поехать можно, запустив двигатель и нажав на педальку, а вот надо ли использовать остальное и как - это лишь отвлекает.
Или, взять интерфейс SharpDevelop
, он, по сравнению с интерфейсом PascalABC.NET перегружен (хотя, проще IDE для C# я не встречал):
Тут следует добавить ещё ремарку. Если бы разработчики PascalABC.NET действительно взяли такой курс, то несомненно это бы поменяло аудиторию PascalABC.NET в какой-то степени. И, конечно, это уже был бы иной PascalABC.NET, рассчитанный на более продвинутых пользователей, точнее часть людей могла бы просто перестать пользоваться этой IDE, потому что она стала бы больше походить на Visual Studio
своей насыщенностью кнопочек. Надо ли это нам?
- вполне оправданно задавать себе такой вопрос разработчикам. Ведь, если не PascalABC.NET, то что послужит первой ступенью в изучении языка Pascal?.. (Free Pascal
- вариант, но, насколько помню, его интерфейс более “отталкивающий” для новичков.)
И, конечно, предлагаемые мною возможности можно было бы реализовать дополнениями. Тогда бы проблем с насыщенностью кнопочкам интерфейса IDE
по умолчанию не возникало, но:
Мне кажется, стОит в этом случае говорить о том, чтобы интегрировать консольный компилятор и средства Intellisense в какой-то известный расширяемый редактор. Например. в VS Code.
Так-с, пока я пытался оставить замечание по среде разработки, у меня появились замечания по сайту:
Теперь по IDE: Режим автозавершения кода работает странно В настройках стоит конвертация Tab в 4-е пробела. Если написать “begin” и нажать Enter, произойдет автозавершение и между операторными скобками появится отступ в 2-а пробела. В редакторе стоит моноширинный шрифт, благодаря чему можно заметить, что ставится отступ из 2-х пробелов:
Я понимаю, что это две разные вещи (конвертация tab и отступ), но почему бы отступ не делать по кол-ву пробелов в конвертации?!Не очень удобно, что в RegEx.Replace можно указывать количество раз, а в строке.Replace - нельзя, не говоря о стартовой позиции.
Может есть смысл добавить перегрузки с параметрами:
Заранее прошу простить ежели не доглядел и уже было.
Вы сами сказали, что это разные вещи. Мы считаем правильным форматирование с отступом в 2 пробела.
Возможно, стоит, прописать где-нибудь это явно, например, прямо в настройках, если менять не собираетесь, но и не хотите снова таких вопросов от пользователей.
Имеется следующая задача:
Ее можно решить как в традиционном, так и в функциональном стиле. Сравним.
begin
var n := ReadInteger;
var a := ReadArrInteger(n);
// функциональный стиль
a.Select((v, i) -> (v, i))
.Where(t -> Abs(t[0]) mod 10 = 7)
.Select(t -> t[1] + 1)
.Sum
.Println;
// традиционный стиль
var s := 0;
for var i := 0 to a.High do
if Abs(a[i]) mod 10 = 7 then
s += i + 1;
s.Println;
end.
Функциональное решение по длине не короче традиционного, но выглядит существенно сложнее и требует определенных добавочных знаний.
Я вижу здесь причину в том, что задача требует получить набор (последовательность, массив - не суть важно) индексов массива на основании свойств элементов этого массива. Поэтому придется сначала формировать кортежи с элементами и их массивами, а после выборки снова выделять из кортежей индексы.
Если индекс один - у нас есть чудесные средства FindIngex и FindIndexLast. Но почему же нет FindIndices? Тогда у нас была бы возможность решить такую задачу куда понятнее и красивее:
begin
var n := ReadInteger;
var a := ReadArrInteger(n);
a.FindIndices(t -> Abs(t) mod 10 = 7)
.Sum(i -> i + 1)
.Println
end.
Также, расширение массива .FineIndices, дающее массив, могло бы сослужить отличную службу при использовании результата в качестве вектора для MatrSlice.
Может быть, имеет смысл подумать над таким расширением? Было бы отличное симметричное дополнение для .FindAll.
В функциональном стиле - я бы решал так:
begin
var a := ReadArrInteger(ReadInteger);
a.Numerate
.Where(t-> Abs(t[1]) mod 10 = 7 )
.Sum(t->t[0]).Println
;
end.
Функции нахождения всех индексов таки много где пригодилась бы. Но если делать - лучше называть FindAllIndices
, раз это индексный вариант FindAll
, и чтоб визуально проще было отличить от FindIndex
.
Сразу пример реализации и использования:
function FindAllIndeces<T>(self: sequence of T; pred: T->boolean; from: integer): sequence of integer; extensionmethod;
begin
foreach var a in self do
begin
if pred(a) then yield from;
from += 1;
end;
end;
// потому что yield всё ещё не совместимо с параметрами по-умолчанию
function FindAllIndeces<T>(self: sequence of T; pred: T->boolean): sequence of integer; extensionmethod := self.FindAllIndeces(pred, 0);
begin
var a := ReadArrInteger(ReadInteger);
a.FindAllIndeces(x-> Abs(x) mod 10 = 7, 1)
.Sum.Println
;
end.
Ну, есть оно - вы же книгу писали:
begin
ReadArrInteger(ReadInteger).Indices(t -> Abs(t) mod 10 = 7).Sum(i -> i + 1).Println
end.
Вот же… Когда писал код, почему-то Intellisence упорно не хотел вариант с лямбдой показать. Я и подумал… Разве все упомнишь? Все же какое счастье, что оно уже есть))))
Обновился до сборки 2281 от 2112. Предыдущую сборку проверить не успел. Что-то случилось с автозавершением кода; во всяком случае, оно меня буквально изнасиловало на условных операторах. В ветке then после оператора по нажатию Enter упорно втыкается точка с запятой. Может, кому-то нравится этот С-подобный синтаксис, но при большом количестве условных операторов, особенно сложных с else if, постоянно нырять на предыдущую строку и затирать точку с запятой - ну это может достать очень сильно!
В общем, я был бы очень благодарен, если убрать автовставку символа “;” после then <оператор>. Ибо достало реально! На самом деле таких неполных if, где ветка else отсутствует, статистически не должно быть много в программах.
Авто завершение кода ждёт от вас что если else будет - то на строчке с оператором, а не на следующей. Определить, собираетесь ли вы ставить else на следующей строке - невозможно. А обычно ;
после оператора таки необходимо.