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

unit Program1;

interface

type
  t1=class;
  t2=class;
  
  t1=class
    a:t2;
    procedure p1;
  end;
  
  t2=class
    a:t1;
    procedure p1;
  end;

implementation

procedure t1.p1 := writeln(self.a.a);

procedure t2.p1 := writeln(self.a.a);

end.

Спасибо, но Вы меня не поняли. Нужна примерно такая структура:

Type
  B = class
    procedure MB();
    Begin
      //Тут нужно использовать текущие значение a1 и a2.
      //Эти классы могут быть расположены в разных модулях
    End;
  end;
  A = class
    a1,a2: integer;
    procedure MA();
    Begin
      Var B1 := new B; //Тут в конструктор B можно передать a1 и a2,
      //но при их изменении в объекте класса A они не изменятся в B1
    End;
  End;
Begin
  
End.
unit Program1;

interface

type
  A=class;
  B=class;
  
  A=class
    a1,a2:integer;
    procedure MA;
  end;
  
  B=class
    procedure MB;
  end;

implementation

procedure A.MA;
begin
  Var B1 := new B; //Тут в конструктор B можно передать a1 и a2,
  //но при их изменении в объекте класса A они не изменятся в B1
end;

procedure B.MB;
begin
  //Тут нужно использовать текущие значение a1 и a2.
  //Эти классы могут быть расположены в разных модулях
end;

end.

В этой программе оба метода относятся к классу A. Тогда должно быть

procedure B.MB;
begin
  //Тут нужно использовать текущие значение a1 и a2.
  //Эти классы могут быть расположены в разных модулях
end;

но из этого метода нельзя обратиться к a1,a2

Ой действительно, опечатался, уже исправил.

a1 и a2 это поля класса A. Так будет работать:

procedure B.MB;
begin
  var varA := new A;
  varA.a1 := 5;
end;

Будет, но мою задаю это не решает=)) Надо ведь наоборот: в методе A.MA создать экземпляр класса B и в методе B.MB использовать переменные a1,a2 того объекта, в котором этот экземпляр создаётся. Наверно, здесь это невозможно… в C# есть вложенные классы, в ABC.NET можно создать нечто подобное через анонимные классы. Но это гораздо более громоздко, и не позволяет использовать все возможности вложенных классов.

Ну можно a1 и a2 передать в виде параметров конструктора или процедуры, а вообще я не совсем понял задание)) Давайте хотя бы на C# код.

Да на C#-то это легко реализуется: https://docs.microsoft.com/ru-ru/dotnet/csharp/programming-guide/classes-and-structs/nested-types а здесь так нельзя… Эх, кажется я плохо понимаю, что делаю. Вопрос закрыт.

Чтобы получить доступ к вмещающему типу, передайте его в качестве аргумента в конструктор вложенного типа. (это я со страницы с вашей ссылки скопировал)

Как я и сказал, передавайте данные через конструктор.

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

Пример для ForEach имеется в стандартной поставке:

\PABCWork.NET\Samples\!MainFeatures\01_First\Foreach.pas

Что касается примера “ForEach с применением индекса” - Вы сами хорошо осознаете, что просите? Метод ForEach, как и цикл ForEach используется для перебора всех элементов БЕЗ обращения к их индексу, даже если таковой имеется. Откуда же в ForEach (и зачем) этот индекс возьмется?

Есть 2 Foreach:

  1. цикл Foreach var a in arr do, он работает не для массивов а для последовательностей. Массив тоже последовательность, но не у все последовательности индексированы, поэтому он не работает с индексами.

  2. функция sequence.Foreach, вторая её перезагрузка производит свою индексацию, поэтому можно сделать так:

begin
  var a := new byte[3](5,7,8);
  a.ForEach((el,ind)->begin a[ind] *= ind end);
  a.Println;
end.

0 7 16

Но это как то через 5 точку, лучше так:

begin
  var a := new byte[3](5,7,8);
  a := a.Select((el,ind)->byte(el*ind)).ToArray;
  a.Println;
end.

Теперь хотя бы нет обращения из лямбды к внешней переменной, хотя конечно обычный цикл for всё равно будет быстрее, используйте такой метод только если производительность не важна.

1 лайк

Нужен пример вот этого: “procedure ForEach(Self: sequence of T; action: (T,integer) -> ()); extensionmethod; Применяет действие к каждому элементу последовательности, зависящее от номера элемента”

1 лайк

Благодарю.

С недавних пор есть еще один вариант – через цикл foreach и метод расширения .Indexes для одномерных массивов:

begin
  var a := new byte[3](5,7,8);  
  foreach var i in a.Indexes do a[i]*=i;
  a.Println;
end.

Красиво, но, к сожалению, работает тоже немного медленнее классического цикла for

2 лайка

Можно пример с операторами + и * для функций? Как это вообще работает?

Для функций это не работает. Работает только для процедур без параметров:

var p3 := p1 + p2;

Тут p3 присваивается процедура которая выполняет p1 и затем p2.

var p2 := p1*5;

А тут p2 присваивается процедура которая выполняет p1 5 раз.

Для функций нет

Извините, ошибся. А будет?

Ну operator+ почему то расширять не даёт, а вот operator* можно так самому:

function operator*(a: byte->byte; c: integer): byte->byte; extensionmethod;
begin
  
  Result := b -> begin
    
    loop c do Result += a(b);
    
  end;
  
end;

begin end.

(сейчас не компилируется благодаря #533)