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

Нет, просто вы неправильно используете.

Само их существование - ничего не делает с производительностью.

Нет, не искажает, потому что юнит-тесты надо делать.

Да, с таким подходом вам самому придётся искать где именно медленное место.

Но как я и сказал, надо мониторить всё и сразу - ищите или пишите программу которая работает для C#, для паскаля тоже сработает.

Но ожидать что это случится в ближайшем будущем не приходится, ибо некому.

1 лайк

Для .NET есть внешние профилировщики насколько я помню.

1 лайк

Ну, я примерно про такое и говорил, но не знал как это называется…

@NRA вот первое дефолтное от микрософта:

Но наверняка найдётся что-нибудь более качественное на гитхабе.

P.S. Мда, такое впечатление что этот стандартный профайлер делал школьник, даже окна не настроены нормально))) (ну то есть даёт менять размер, так что контролы не помещаются…)

А значит обязательно кто то уже сделал что то получше.

2 лайка

Подскажите пожалуйста. Как сделать учет, склад и соединить это с считывателей QR или штрих кодов? Есть ли готовые примеры? Что нужно: например: пробирка - штук на складе, штук выдано, цена такая-то, возможно несколько фото пробирки. при скармливании программе штрих кода или qr > штук на складе-1 выдано+1.

С чего начать? в чем хранить? как взаимодействовать с внешними устройствами?

Возможно такое вообще сделать?

Хранить скорее всего в словаре, с ключами - записями (хранящими QR код и кастомными операторами сравнения на равенство и методом получения хеш-кода), и значениями - классами хранящими информацию о кол-ве и о самом товаре.

Есть ли формула вроде RNG или способ через Seq/Where получить случайную уникальную последовательность, допустим, от 0 до 100 без повторений и без вспомогательного буфера (в данном случае, на 101 элемент)? Или хоть подскажите, что искать.

Благодарю

Буфер всё равно понадобится, разумеется, потому что надо сравнивать с предыдущими. Но можно чтоб это был внутренний буфер функции:

begin
  SeqWhile(Random, o->Random, o->true)
  .Select(r->r)//умножение, сложение чтоб получить нужную область чисел
  .Distinct
  .Take(10)
  .Print
end.

В Distinct что то вроде:

var prev := new HashSet<T>;
foreach var curr in self do
  if prev.add(curr) then
    yield curr;
1 лайк

Спасибо, Сергей. Вроде и этот цимес подходит

Я так делаю

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, другие версии не подходят).