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

Я так делаю

begin
  var m := 20;
  var a := SeqRandom(1000 * m, 0, 100)
      .Distinct.Take(m).ToArray;
  a.Println;
end.

В счетчике там все равно что ставить, хотя бы на пару порядков больше m )))

1 лайк

А с чего вы решили что там не будет повторяющихся чисел?

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

Поставтье 100000000

Я кстати сейчас попробовал… Вот так вообще по феншую:

begin
  SeqGen(1,i-> Random(1,100) ).Cycle
  .Distinct
  .Take(10)
  .Print
end.
2 лайка

А если бы массивы можно было бы, то

begin
  Range(1, 100).ToArray.Shuffle.Print;
end.
1 лайк

Вообще Range(1, 100).ToArray работает медленно, оно создаст очень много лишних массивов. Лучше ArrGen(100,i->i+1) - оно создаст только 1 массив.

Чуть поразбирался с четырьма классами таймеров в NET, и попытался перевести код

c#

// https://professorweb.ru/my/csharp/thread_and_files/1/1_15.php

using System; using System.Threading;

namespace ConsoleApplication8_Timers { class Program { static void PrintTime(object state) { Console.Clear(); Console.WriteLine("Текущее время: "+ DateTime.Now.ToLongTimeString()); }

    static void Main()
    {
        // Делегат для типа Timer
        TimerCallback timeCB = new TimerCallback(PrintTime);

        Timer time = new Timer(timeCB, null, 0, 1000);
        Console.WriteLine("Нажми чтоб выйти");
        Console.ReadLine();
    }
}

}

получается

uses System.Threading;

procedure PrintTime(state: object);
begin
   print('Текущее время:  ', DateTime.Now.ToLongTimeString());
end;

begin
   // Делегат для типа Timer
   var timeCB: TimerCallback = new TimerCallback(PrintTime); //ОШИБКА: нужен объект
   
   var time: timer = new Timer(timeCB, null, 0, 1000);
   Print ('Нажми чтоб выйти');
   ReadLine();
end.

однако или что-то снова под вечер туплю, или же есть нюанс

Вы не туда поставили ``` у выделения C# кода.

По вопросу - ищите такое на msdn.

TimerCallback - это тип делегата, то есть процедуры в данном случае. У него есть operator implicit как у любого другого делегата, для совместимости с другими делегатами у которых такие же параметры и возвращаемое значение:

uses System.Threading;

procedure PrintTime(state: object);
begin
   print('Текущее время:  ', DateTime.Now.ToLongTimeString());
end;

begin
   // Делегат для типа Timer
   var timeCB: TimerCallback := PrintTime;
   
   var time: timer = new Timer(timeCB, nil, 0, 1000);//вообще, можно и саму PrintTime передавать в конструктор
   
   Print ('Нажми чтоб выйти');
   readln();
end.

Что касается конструктора - я не уверен на 100%, но поидее должно работать так:

uses System.Threading;

type
  t1 = class
    
    procedure PrintTime(state: object);
    begin
      print('Текущее время:  ', DateTime.Now.ToLongTimeString());
    end;
  
  end;

begin
  var a := new t1;
  var timeCB: TimerCallback := new TimerCallback(
    a,//объект для которого будет вызываться метод. Если метод статичный - передавайте nil
    System.Delegate(a.PrintTime).Method.MethodHandle.Value
  );
  
  var time: timer = new Timer(timeCB, nil, 0, 1000);
  
  Print('Нажми чтоб выйти');
  readln();
end.

(Правда, сейчас получаем внутреннюю ошибку))) #1552)

Кстати, глобальные подпрограммы как в вашей программе - тоже при компиляции превращаются в статичные методы. То есть для них в качестве объекта тоже надо передавать nil.

1 лайк

Правда, в несколько раз медленнее… Но ведь Range(a, b) – это родной дотнетовский? Странное поведение такого распространённого генератора…Что ж, спасибо за подсказку, будем знать.

Дело не в генераторе а в том как вы его используете. Range возвращает yield последовательность, то есть чтоб вычислить её длину - надо пройтись по всем элеметам.

А .ToArray позволено пройтись по последовательности только 1 раз. То есть перед тем как он узнает сколько всего есть елементов - ему придётся куда то сохранить те элементы по которым он пройдёт. Поэтому он работает так (я декомпилировал):

Создаётся массив на 4 элемента и заполняется. Если не хватило - создаётся массив в 2 раза больше, в него копируется то что есть, предыдущий удаляется и заполнение продолжается для нового массива. Последнее повторяется пока yield последовательность не скажет что достигли последнего элемента. В самом конце создаётся ещё 1 массив, уже с нужным кол-вом элементов, и в него снова копируется то что прочитали.

Но, кстати, если на вход в .ToArray подать IList<T> последовательность (то есть любой список, массив, словарь, всё с известной длиной) - будет создан только 1 массив, нужной длины.


В общем у ленивых вычислений свои применения, а у IList<T>-ов - свои. К примеру это:

Range(1,100).Sum

Будет лучше чем это (по скорости Range может капельку медленней, а по памяти - огромное преимущество):

ArrGen(100,i->i+1).Sum

Надеюсь, понятно почему. Если нет - почитайте презентацию по ленивым вычислениям, на pascalabc.net (да название паскаля работает как ссылка). Эту презентацию создавали преподаватели с корочкой, а не самозванцы вроде меня)) Так что там должно рассказываться лучше.

1 лайк

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

Win10? Скольки-битная и т.п.?

И - попробуйте удалить .Net4.0 (если установлено) и установить заново (именно 4.0, другие версии не подходят).

Win8 64x Хорошо

О как! Ну да, ему (ToArray) деваться, в общем-то, некуда если размер заранее неизвестен.

Про ленивость всё ясно, только очень она многоликая, проявляется там, где не ожидаешь :slight_smile:

Спасибо за подробный ответ!

А это с чего вдруг? Ленивость возможно только у нескольких типов, специально прописанных.

К примеру, Range возвращает sequence, это видно при открытии скобочки и если навести на него мышку. А значит - он будет возвращать ленивую последовательность.

Похоже на антивирус. Запишите рабочую папку паскаля в исключения.

Да это-то ясно. Я имел в виду, что если мало сталкивался с “ленивостью”, то можно сразу не сообразить, что Range(1, 100).ToArray будет при работе плодить массивы. Привыкать надо такие штуки замечать, я об этом.

1 лайк

Попробуйте декомпилировать свои программы (я использую для этого DotPeek) - найдёте и более интересные штуки)).

Вам пора завести новую тему: интересные штуки :slight_smile: Будем с удовольствием читать.

“Кунштюки РАВС”

1 лайк