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

Вы можете дать чёткие правила, в каких случаях (подобных данному) ставить begin-end ?

В выражениях функцию, возвращающую функцию, нельзя записать с помощью короткого синтаксиса. Надо записывать с помощью длинного.

В типе можно испоользовать тип функции, возвращающей функцию.

Это недостаток нашей грамматики. Может, неустранимый.

А в данном случае что делать:

type
  TClass<T, T2> = class
    property P: () -> (() -> T, () -> T2) read () -> begin Result := (() -> default(T), () -> default(T2)); end;
  end;

begin
end.

? :slight_smile: Требуется вернуть кортеж из двух функций.

А вот и нет))) Сначала создаётся новый экземпляр типа System.Tuple, в конструктор которого передаётся 3 параметра, а потом значения вытягиваются по 1. И это дольше, потому что надо создавать экземпляр и значения оказываются в итоге в куче а не на стеке.

Можно - всегда:

begin
  var f:()->byte := ()->
  begin
    Result := 0;
  end;
end.

Нужно - когда без этого не обойтись:

begin
  var i:integer;
  var f:()->byte := ()->
  begin
    i += 1;
    Result := i;
  end;
end.

Ой, я бы повесился)) Или лучше расписал бы как отдельные подпрограммы, вместо того чтоб строить пизанские башни))))

Если честно, я ради интереса спросил, а не для того, чтобы этим пользоваться повседневно. Точнее - развлекаюсь как только могу. И все-таки, почему ругается?

А хотя не, можно сделать без дополнительных подпрограмм. Но надо воспользоваться древней забытой техникой - форматированием своего кода:

type
  TClass<T1, T2> = class
    property P1: () -> (() -> T1, () -> T2)
    read () ->
    begin
      var f1: ()->T1 := () -> default(T1);
      var f2: ()->T2 := () -> default(T2);
      Result := (f1, f2);
    end;
  end;

begin end.

Если бы она была такой древней и такой забытой, то я боюсь представить как бы выглядели бы исходные коды программ. :slight_smile:

Ну не знаю, вы то её не использовали)) Вот мне и захотелось повесится, как я увидел что строчка и близко не вмещается в ширину моего монитора)).

Я не всерьез же код писал. Если серьезно, то, странно, что если убрать переменные, то код не компилируется:

type
  TClass<T1, T2> = class
    property P1: () -> (() -> T1, () -> T2)
    read () ->
    begin
      Result := (() -> default(T1), () -> default(T2));
    end;
  end;

begin end.

. Причём, выдает:

Program9.pas(8) : Встречено ‘)’, а ожидалось выражение

. Issue делать?

Сделайте issue с формулировкой “неправильная ошибка”. Должно ли компилироваться - это отдельный вопрос. Но если не должно - пусть хоть скажет почему.

Ласковее, я же говорил:

type
  TClass<T, T2> = class
    property P: () -> (() -> T, () -> T2) read () -> begin Result := new System.Tuple&<() -> T, () -> T2>(() -> default(T), () -> default(T2)); end;
  end;

begin
end.
2 лайка

Погодите, но ведь кортежи с синтаксисом (Item1, Item2, …) основаны на System.Tuple<T, T1, …>.

Да, правильно, а точнее на System.Tuple.Create<T, T1, …>. Но грамматика много ещё где не выдерживает.

Я все-таки сделаю Issue. Разработчики, когда будет время, подправят.

1 лайк

Сделайте issue именно про неправильную ошибку. А моменты где компилятор вообще не справляются - не всегда исправляют.

Нет ну а сократить? Расширенные свойства, к примеру, тут не при чём. Уберите из программы-примера всё что не обязательно.

Вас понял. Подправил.

Почему во втором случае не удается неявно преобразовать integer к byte в кортеже:

type
  TA = class
    property P: byte read 1;
  end;
  
  TB = class
    property P: (byte, byte) read (1, 1); // Program9.pas(8) : Нельзя преобразовать тип Tuple<integer,integer> к Tuple<byte,byte>
  end;

begin
end.

? Проверил в C# случай, аналогичный второму:

class MainClass
{
	public (byte, byte) P => (1, 1);

	public static void Main (string[] args)
	{
	}
}

, компилируется. Это особенность PascalABC.Net, или это ошибка?