Версия PascalABC.NET 3.1

Ошибку с последовательностями исправили

Ну, это ошибка в реализации. Неожиданная - на ровном месте. Ищем.

Еще один “сюрпризец”. Неожиданный, раньше работало нормально.

// PascalABC.NET 3.1, сборка 1171 от 15.02.2016
type
  tM=array[1..3,1..3] of integer;

begin
  var a:array[1..3,1..3] of integer:=
    ((1,2,3),(4,5,6),(7,8,9));
  Writeln('a:  ',a);
  var b:tM:=((1,2,3),(4,5,6),(7,8,9));
  Writeln('b:  ',b);
end.

Результат выполнения программы:

a:  [[1,2,3],[4,5,6],[7,8,9]]
b:  ([[1,2,3],[4,5,6],[7,8,9]],1,3)

В сборке 1172 ошибка устранена.

Известно, что для нахождения суммы членов последовательности можно использовать метод .Sum, для нахождения среднего арифметического - метод .Average. А вот с произведением все оказывается далеко не так красиво. То ли его решили изначально в LINQ не вводить из-за возможности неконтролируемого арифметического переполнения в операции умножения целых (обычно в целях эффективности контроль переполнения разрядной сетки не делается), то ли еще какая-то есть причина, - но так, или иначе, метода .Prod у нас нет. И приходится выкручиваться. Поскольку разработчикам лучше, чем кому бы то ни было, известна внутренняя “кухня” реализации, хотелось бы получить рекомендацию, как эффективнее (и красивее) находить произведение членов числовой последовательности. И необязательно даже по критерию отбора: ведь его при необходимости можно организовать через предшествующий .Where.

Product это, как и Sum, как и многое другое, это экземпляр свёртки (fold, в Линке это называется Aggregate). Примерно так.

a.Aggregate(1, (prod, x) -> prod * x);

(Надеюсь, с синтаксисом нигде не напутал, WDE не работает, чтобы проверить.)

Есть известная байка на схожую тему в мире функционального программирования.

3 лайка

fac n = product [1…n] - вот это как раз то, чего бы хотелось увидеть))) А байку оценил, “внушаить” (с)

И - да, спасибо, работает выражение.

Гхм, такого количества способов я не видел. Спасибо! :smile: Интересный материал.

Print() удобен тем, что он разделяет пробелом выводимые значения, но это хорошо лишь для целых величин и, возможно, символов. А для вещественных это зло… Вот если бы имелся какой-то PrintReal, выводящий вещественные (с автоприведением к ним целочисленных) значения, у которого первый параметр задавал бы число знаков в дробной части (в целой не надо, потому что Print’ом таблицы все равно не рисуют), это было бы превосходно.

В .Net это делается переопределением метода ToString или добавлением строки форматирования к тому же complex.ToString("{0:MyComplex}"). Не много замарочливо, но возможно каждому самому под себя делать любой вывод в зависимости от типа Возможно ли это реализовать тут?

Всё, что есть в библиотеке .NET, будет работать и тут

Обновился сегодня до последней версии и заметил одну странность - есть у меня один проект WinForms - компилируется он успешно, а при запуске падает по System.ArgumentNullException: Value cannot be null.

Внутренняя ошибка компилятора в модуле [pabcnetc.exe] :'System.Exception: System.ArgumentNullException: Value cannot be null.
Parameter name: key
   at System.Collections.Generic.Dictionary`2.FindEntry(TKey key)
   at System.Collections.Generic.Dictionary`2.ContainsKey(TKey key)
   at PascalABCCompiler.NETGenerator.ILConverter.ConvertFromTree(IProgramNode p, String TargetFileName, String SourceFileName, CompilerOptions options, String[] ResourceFiles)
   at PascalABCCompiler.CodeGenerators.Controller.Compile(IProgramNode ProgramTree, String TargetFileName, String SourceFileName, CompilerOptions options, Hashtable StandartDirectories, String[] ResourceFiles)
   at PascalABCCompiler.Compiler.Compile()'

и потом уже ничего не собирается. при этом собранный exe’шник запускается и работает нормально, проблема только при попытке запуска прямо из IDE. раньше это работало.

Это странно. У нас все проекты WinForms работают

А это пасхалочка от разработчиков такая? промахнулся и качай в 10 раз больше?) а я нашел) Случайно увидел что ссылка при наведении не целиком подсвечивается.

Тут вот у @Ret_ReT была проблема с запуском приложения с использованием CRT, я попробовал запустить свой проект winForms без связи с оболочкой, появилась консоль ProgramRunner.exe с единственной строкой - программа завершена, нажмите любую клавишу… - как будто запускается пустая программа типа begin end. То есть вроде бы ничего общего, но на мысли наталкивает.

В последних версиях появились операции, порождающие из обычной последовательности “последовательности последовательностей” или разбивающие её на несколько последовательностей. Возник вопрос: как эффективно “собрать назад” такие конструкции?

// PascalABC.NET 3.1, сборка 1200 от 13.03.2016
begin
  var a:=Range(0,11); // Sequence of integer (по Intellisence)
  Writeln(a); // [0,1,2,3,4,5,6,7,8,9,10,11]
  
  var b:=a.SplitAt(4); // System.Tuple<integer>
  Writeln(b); // ([0,1,2,3],[4,5,6,7,8,9,10,11])
  var b1:=b.Item1+b.Item2; // integer - ОШИБКА Intellisence?
  Writeln(b1); // [0,1,2,3,4,5,6,7,8,9,10,11]
   
  var c:=a.Batch(4); // Sequence of integer
  Writeln(c); // [[0,1,2,3],[4,5,6,7],[8,9,10,11]]
  // как все это собрать "назад" в исходную последовательность?
end.
2 лайка

SelectMany

А нельзя дописать этот самый SelectMany, как он должен выглядеть в предложенной программе?

  c.SelectMany(x->x).Println;

SelectMany превращает иерархическую последовательность в плоскую

1 лайк

Спасибо! С любым уровнем иерархии?

Нет. Только с одним. Думаю, поприменяйте несколько раз :slight_smile:

1 лайк

Так все и задумано?

// PascalABC.NET 3.1, сборка 1200 от 13.03.2016
begin
  Range(10,16).Println;    // 10 11 12 13 14 15 16
  Range(16,10).Println;    // пустая строка
  Range(10,16,1).Println;  // 10 11 12 13 14 15 16
  Range(16,10,1).Println;  // 16 17 18 19 20 21 22 ???
  Range(10,16,-1).Println; // 16 15 14 13 12 11 10
  Range(16,10,-1).Println; // 10 9 8 7 6 5 4       ???
end.
2 лайка