Помощь новичкам

Как правильно перезагрузить оператор вызова?

type
  t1 = class
    
    function operator() (a,b: byte) := a+b;
    
  end;

begin
  var a := new t1;
  var i := a(1,2);
end.

Вроде можно было, но это не точно…

И так тоже не работает:

type
  t1 = class
    
    property exec1[a,b: byte]: byte read a+b;
    property exec2(a,b: byte): byte read a+b;
    
  end;

begin
  var a := new t1;
  var i1 := a.exec1[1,2];
  var i2 := a.exec2(1,2);
end.

@Сергей, лично с подобным не сталкивался и думал заковырка в public static, но в доке MS упоминают скобки лишь в контексте индексации и приведения типов через ex/implicit, а задумка интересная. Через делегаты не пойдёт?

Смысл в том, чтоб объект можно было и вызвать, и при этом чтоб у него кастомные свойства были… А наследовать от делегатов нельзя.

Нет, это в C++ такое было. В NET нельзя

1 лайк

Уважаемые,

1) подскажите как правильно и без лишних прибамбасов вроде RegEx перезагрузить .Replace для строк, чтобы кроме указания искомого и замены можно было указывать кол-во удаляемых вхождений (cardinal?)

Пока такой вариант выкусывания подстроки
Function string.operator-(s1,s2:string):string;
begin
  if IsNullOrEmpty(s1) or IsNullOrEmpty(s2) then exit; //nothing
  var _pos := s1.IndexOf(s2,0);
  if (_pos >-1) then Result:= s1.Substring(0, _pos) + s1.Substring(_pos + s2.Length);
 // может есть что улучшить по новым канонам, кроме Left/Right или Result:=s1.Remove(_pos,s2.Length);?
end;

2) Как оптимальнее подсчитывать количество вхождений подстроки?

3) также пока не особо понятно почему в отличие от того же stringbuilder, перегрузка “плюса” через Concat не даёт ощутимых преимуществ при обработке массивов строк

Благодарю

Вот я не понимаю той смысловой нагрузки, которую Вы придаете взятым Вами же в кавычки словам в контексте программирования. По-моему, Вы (причем, уже не в первый раз) смешиваете алгоритм и его реализацию в конкретном языке.

Правильно с какой точки зрения? Алгоритмически правильно все, что приводит к нужному результату в рамках условия и поставленных ограничений. Программно правильно все, что реализует алгоритм на вычислительной установке в рамках имеющейся аппаратной и программной платформы.

Оптимально с какой точки зрения? Понимания кода, компактности кода, скорости выполнения программы, затратах на оперативную память, времени написания программы… ?

Спасибо, @Алекс, но там нет кавычек и, насколько я понимаю, полемику и умственные рефлексии хотя иногда и полезны, однако им место скорее в “Болталке” или оффтоп.

Разумеется, для решения большинства задач достаточно парадигмы структурного программирования, а в данном контексте (как ни странно) речь о современном подходе для PascalABC .NEТ

Да, извините, там КУРСИВ.

Что касается парадигмы структурного программирования, она никак не определяет ни правильности алгоритма (да и не может определять), ни оптимальности кода. Неправильно в структурном программировании то, что нарушает его концепцию - и только. Поэтому вопрос о “правильности” остается открытым".

Термин “современное программирование” каждый волен трактовать по-своему, но в любом случае в контексте поставленной задачи, а не в виде “сферического коня в вакууме”.

Перегрузить*

function Remove(self: string; s: string; c: integer): string; extensionmethod;
begin
  var sb := new StringBuilder(self);
  //ToDo
  Result := sb.ToString;
end;

begin
  'abcabcabc'
  .Remove('b',2)
  .Print;
end.

Потому что:

s1 + s2 + s3

Это:

(s1 + s2) + s3

То есть:

Concat(Concat(s1, s2), s3);

То есть внутренний Concat создаст лишнюю строку.

А это вообще зря. Concat реализован через StringBuilder, что, хоть и быстро, но, думаю, внутренняя реализация сложения 2 строк должна всё же быть быстрее, ибо там через неуправляемую часть кода всё делается (если я правильно помню).


Вот это как раз в болталку стоило бы. Потому что слова красивые но по делу мало. Лучше бы, всё же, ответили, что вы имеете в виду под “оптимально”.

1 лайк

Можно спросить, зачем придумана вся эта путаница с индексацией строк, в одном случае они индексируются с 1, в другом с 0? Например:

begin
  var s := '15x + 17 = 0';
  s.IndexOf('x').Println;//2
  s[:s.IndexOf('x')].Println;//1
end.

я хочу выделить все символы строки до символа ‘x’, использую метод IndexOf, в методах считается, что строки индексируются с 0, потом беру срез и… а срез считает, что строки индексируются с 1. И поди запомни все это.

С 1 индексируется только в s[]. Это из за совместимости со старыми паскалями. Там, вроде, в s[0] хранилась длинна строки. Во всех остальных случаях индексация идёт человеческая, то есть с 0.

Она и теперь хранится там.

В строках с нуля нумерация производится:

  • в процедуре Delete;
  • в методах .Substring, Insert, .Remove, .ReverseString;
  • в методах, унаследованных от последовательностей и содержащих в имени слово “Index”.

С чего вдуруг?

begin
  var i := 'abc'[0];
  i.Print
end.

.Net строки хранят своё содержимое без всяких костылей. Или вы имели в виду в старых паскалях?

Легче всё же запомнить что только в [] нумерация с 1. Ибо вы ещё и не всё назвали (к примеру ещё есть .CopyTo), и даже так - запоминать тут многовато.

В старых, конечно. А в PascalABC.NЕТ при выводе в бинарный файл короткой строки Вы также можете обнаружить этот дескриптор.

.CopyTo - это .NET-экзотика, она даже в Справке не описана.

Ну это Вы увлеклись… подпрограмм, считающих символы в строке от 1, все же большинство.

1 лайк

Как будто там есть хотя бы половина языка))) И это не экзотика, это даже не экстеншн-метод, а обычные и 1 из основных методов строк, так же как .Remove, к примеру.

Это каких?

Я не собираюсь в Вами спорить, потому что Вы как мыслили категориями языков семейства С, так и продолжаете мыслить. Для Вас “язык” - это все, что можно подлинковать из .NET-библиотек. В Справке описано то, что так или иначе относится именно к PascalABC.NЕТ.

Я не хочу перечислять тут то, на что потратил две недели, когда писал полсотни страниц части 6 своей будущей книги.

Я не нашёл там части про методы строк, поэтому залез в PABCSystem.pas. Там со строки 1469 перечислены все методы для строк. Ну и + экстенш-методы которые видны по точке.

И единственный который индексирует строку с 1 - это Copy, то есть старьё существующее только для совместимости. Оно даже исключения не вызывает, просто игнорируя ошибочные случаи, что в современном программировании считается очень плохим стилем.

Нет подождите, мне всё же интересно понять… То есть вы говорите что раз оно не описано в справке, даже если находится в том же пространстве имён (то есть его показывает по точке для любой строки, при чём в самом начале) - это не часть PascalABC.Net?

Я же говорю не про функцию, ради которой надо что то подключать, а про то, что поумолчанию есть в каждой программе. Я так же мог бы понять, если бы вы имели в виду что часть языка - это то что запрограммировали разработчики. Но тот же .Remove - это тоже встроенная в .Net функция, которая отличается от .CopyTo только тем, что её нету в справке паскаля. А по справке сравнивать странно потому что:

Так же, разработчики сами писали когда то, что не собираются делать справку по всему что даёт .Net, ибо оно уже задокументировано на msdn, это была бы лишняя трата времени. То есть та справка так же может считаться описывающей часть данного языка. Или нет?

И можете ещё подробнее объяснить:

Я вообще не понял к чему это тут. Я хоть 2 из них знаю, но не использую, откуда у меня какое то мышление в их стиле?

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

Это вовсе не обязательно часть РasacalABС.NЕТ. И не нужно делать вид, что это Вас удивило. Вы же не считаете, что при использовании #include в С++ все перечисленное там станет частью языка? А в PascalABC.NЕТ по умолчанию часть библиотек уже прилинкована, но частью языка от этого содержимое библиотек не стало. Такими рассуждениями можно дойти до того, что весь .NET - тоже часть языка, если разработчики создадут соответствующее пространство имен.

Писал не раз, не хочу повторяться. Хотите - считайте это моим частным мнением.

Забавная дискуссия. Как не косяк, так везде С-мышление виновато! Ох же ж оно, Кернигана с Ритчи надо ретроактивно абортировать!

От сабжа ушли. Кто б там, и каким образом не был виноват в ситуации, факт остаётся фактом: то, что в пределах одного языка строки и массивы индексируются то с нуля, то с единицы - фундаментально неправильно. И, кстати, лечится оно собственной реализацией набора тех самых extension-методов для сих структур данных, если я все правильно понимаю (может быть, и нет, поправьте, если нельзя). Пользователь языка не должен уметь отличать методы PABC.NET от методов .NET. Я б сказал, это вещь, достойная Issue на гитхабе.

1 лайк

Наследие совместимости. Ну вот решил когда-то так Н.Вирт, что символы в строках надо от единицы нумеровать. Как по мне, так оно правильно именно от единицы. Вот опять мне тут сейчас про Кернигана с Ритчи напомнят, но до “языка Це” массивы индексировались либо от единицы (Фортран, Бейсик), либо от описанной нижней границы (Алгол, PL/1), а символы в строках нумеровались от единицы. И это понятно: нормальные люди, как правило, издавна ведут счет от единицы. Нумерация от нуля была только в ассемблере из-за удобства работы со смещением от начала массива.

Вы что предлагаете? Совместимость со всеми остальными паскалями уничтожить, или индексировать массивы от нуля, а строки от единицы всегда, для чего перегрузить все, взятое из .NET? А LINQ тоже будем перегружать? С Matches как - там тоже от нуля нумерация?

Тут можно подискутировать, но не не хочется.