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

Как в PascalABC.NET использовать EventHandler, а именно: события public event SpeakStarted, SpeakCompleted, SpeakProgress, BookmarkReached, VoiceChange, PhonemeReached, VisemeReached, StateChanged в unit Speech, namespace System.Speech.Synthesis?

event используется так:

type
  t1 = class
    event ev: procedure(o: object; e: System.EventArgs);
    
    procedure CallEv;
    begin
      var ev := ev;
      if ev<>nil then ev(self, new System.EventArgs);
    end;
    
  end;
  
begin
  var a := new t1;
  a.ev += (o,e)->Writeln('Ивент вызван');
  a.CallEv;
end.

EventHandler объявлен так:

type EventHandler = procedure(o: object; e: System.EventArgs);

Но, обратите внимание, это не синоним типа, а объявление нового типа делегата.
Разница в том, что typeof(EventHandler) = typeof(EventHandler), потому что это 2 обращения к одному и тому же типу.
А каждый раз как вы пишете тип procedure(o: object; e: System.EventArgs) - вы создаёте новый анонимный тип делегата.

Достаточно и правильно ли использовать ss.SpeakStarted += (o,e)->begin end, чтобы реагировать на событие в следующем примере?

uses System.Speech.Synthesis;
{$reference System.Speech.dll}
  
begin
  var ss: SpeechSynthesizer := new SpeechSynthesizer;
  ss.SpeakStarted += (o,e)->begin end;
  ss.Speak('');
end.

Как удалить ненужную переменную после её описания?

Ну, вы как бы отреагировали… И в ответ ничего не сделали. Я в своём примере сделал чтоб на консоль выводило строку в момент вызова, чтоб было визуально заметно когда ивент вызывается…

А если вы пытались сделать минимальный пример - лучше (o,e)->exit(), немного короче получается.

Что значит удалить?

Если у меня в программе используется много оперативной памяти, а в какой-то момент она уже не будет нужна, как её освободить? Кроме того, возможно ли сделать так, что программа “забудет”, что некоторая переменная была инициализирована (при выполнении var), и можно будет инициализировать переменную с новым типом, но с тем же названием?

Почему ss.SpeakAsync читает строку, находящуюся только до ss.Speak, а если ss.Speak не существует в коде, то ss.SpeakAsync вообще не работает?

uses System.Speech.Synthesis;
{$reference System.Speech.dll}
  
begin
  var ss: SpeechSynthesizer := new SpeechSynthesizer;
  ss.SpeakStarted += (o,e)->Writeln('Начало.');
  ss.SpeakProgress += (o,e)->Writeln('Продолжение.');
  ss.SpeakCompleted += (o,e)->Writeln('Конец.');
  ss.SpeakAsync('Начальное предложение не читается, если ничего не читается синхронно позже.');
  //ss.Speak('Второе предложение читается всегда, когда выполняется соответствующая строка.');
  ss.SpeakAsync('Конечное предложение не читается, если ничего не читается синхронно позже, то есть вообще не читается.');
end.

А сборщик мусора на что? Откройте справку данного паскаля и внимательно перечитайте первую страницу.

Сборщик мусора сам удаляет все объекты, когда считает что они уже не нужны. А локальные переменные, которые нигде больше не сохранили, удаляются прямо при выходе из подпрограммы:

type
  t1 = class
    // Этот метод вызывается прямо перед удалением объекта
    protected procedure Finalize; override :=
    Writeln('Finalize');
  end;
  
begin
  var a := new t1;
  Writeln(a);
end.

Достаточно чтоб переменная вышла из зоны видимости:

uses System.Speech.Synthesis;
{$reference System.Speech.dll}
  
begin
  begin
    var ss: SpeechSynthesizer := new SpeechSynthesizer;
    ss.SpeakStarted += (o,e)->exit();
    ss.Speak('abc');
  end;
  //Ошибка: Неизвестное имя, потому что тут ss уже не существует
  ss.Speak('def');
end.

После этого можно объявлять и новую переменную, даже с таким же именем.

Ну, вы же понимаете что значит Async? Оно успешно вызывается, но программа продолжает выполняться не ожидая окончания воспроизведения. И, в итоге, завершается до того как ss успеет начать говорить.

Для такие тестовых программ - всегда добавляйте что то типа Readln в конце программы. А в более сложных придётся думать по случаю.

Есть ли стандартная подпрограмма для вычисления корня n-ной степени? Если нет, то что лучше для вычисления: sign(x)*exp(ln(abs(x))/n), Sign(x)*Power(Abs(x),1/n), или что-то ещё?

Sign(x) * Abs(x) ** (1/n)

** и Power и так вызывают exp(ln()) (со своими оптимизациями), но и для Power, и особенно для ** надо меньше скобок.

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

Я использую

чтобы присвоить результат деления переменной типа integer, но выходит ошибка “Невозможно явно преобразовать тип real к типу integer”. Как мне доказать, что получится integer? .

Никак. Round(x) возвращает integer, Round(x, n) возвращает real.

Как в консоли обрабатывать нажатие клавиш, не прерывая ввод и не вызывая Console.ReadKey?

Точнее через System.Convert. Это паскалевские Round, Ceil и т.п. сразу конвертируют результат округления в integer. Но сами операции округления на уровне процессора реализованы только для чисел с плавающей запятой. А конвертирование в целые для процессора отдельная операция.

Объясните подробнее.

Я хочу сделать так, чтобы можно было менять цвет текста консоли во время ввода значений с клавиатуры, но для этого нужны горячие клавиши, то есть обработка нажатий на клавиши.

То есть вы хотите чтоб, к примеру, вы могли вводить значение с помощью ReadInteger, но когда пользователь держит Ctrl - введённые цифры этого числа становились красными? Или как?

Попробуйте, лучше, объяснить свою ситуацию, то есть для какой задачи вам это нужно, а не как вы думаете это можно реализовать.

При нажатии определённой клавиши следующий символ не отображается, а следующая нажатая клавиша определяет цвет текста: “Y” — текст дальше вводится жёлтым, “B” — синим и т. д.

Для красоты.

Можно присвоить экземпляр своего класса переменной CurrentIOSystem, если вы используете паскалевские подпрограммы чтения (как ReadInteger), или передать в Console.SetIn, если вы используется .Net-овские средства, как Console.ReadLine.

При этом в обоих случаях использовать старые CurrentIOSystem/Console.In соответственно в своём класса, чтоб выполнять собственно чтение, но при этом поверх добавлять свои проверки, чтоб при нажатии некоторых клавиш переключался цвет текста.

Но это всё сложно и долго, в простых случаях, всё же, лучше использовать Console.ReadKey.

Существует ли готовое решение, чтобы преодолеть проблему нехватки места в окне консоли при одновременном выводе больших строк (если текста слишком много, текст выше уходит за верх и пропадает), например, вывод сообщения “Для продолжения нажмите любую клавишу . . .” вместо текста в зависимости от размера части, которую необходимо вывести далее?

Текст сначала уходит из окна консоли (у которого Console.WindowHeight строк), но остаётся в буфере (то есть можно прокрутить скролбар чтоб вернуть ту часть текста в видимость).

А полностью пропадает текст только если заполнено Console.BufferHeight строк.

И то и то настраивается в настройках самой консоли. Но если вы хотите сделать что то программно - вы всегда можете переставлять курсор как вам угодно.

Почему некоторые символы в скомпилированной программе отличаются от этих же символов в окне вывода ИСP, например, “∈” превращается в “?”? Как это предотвратить?