Опубликованы конспекты лекций по курсу Основы программирования (сен-дек 2017)
https://drive.google.com/file/d/1bmzWPX5PFwoUwJXYAlDVK-Ri7AnhFeBj/view?usp=sharing
Огромное спасибо Ломакиной Евгении!
Опубликованы конспекты лекций по курсу Основы программирования (сен-дек 2017)
https://drive.google.com/file/d/1bmzWPX5PFwoUwJXYAlDVK-Ri7AnhFeBj/view?usp=sharing
Огромное спасибо Ломакиной Евгении!
Опубликована программа курса Основы программирования для подготовки к экзамену
https://drive.google.com/file/d/1AoXj7LLErlURN01cKT7U4ZBpkGoqf13H/view?usp=sharing
Станислав Станиславович, подскажите, пожалуйста, почему тип предиката, объявленный в библиотеке, не виден в основной программе? На лекции мы разбирали такой пример, относящийся к 54 вопросу экзаменационной программы:
library MyLib;
procedure p := Print(1);
function add(a, b: real) := a + b;
type
IntPredicate = integer->boolean;
end.
{$reference MyLib.dll}
begin
p;
println;
print(Add(7, 333));
var f: IntPredicate;
f := x -> x < 5;
if f(2) then
print('<5');
end.
При компилировании основной программы возникает ошибка:
Неизвестное имя 'IntPredicate'
, при этом подпрограммы библиотеки (p
и add
) работают нормально.
Хороший вопрос. Синонимы типов не сохраняются в dll, потому что в .NET для них нет никаких сущностей. Поэтому это можно считать особенностью PascalABC.NET
Станислав Станиславович,как правильно реализовать печать последовательности? Нужен ли для этого оператор yield
?
Дело в том, что тот вариант, который мы писали на лекции ничего не печатает. А если попытаться взять напечатанные элементы и еще раз их напечатать, то получится что-то странное.
///Метод взятия первых n элементов последовательности
function Take<T>(seq: sequence of T; n: integer): sequence of T;
begin
var c := 0;
foreach var x in seq do
begin
yield x;
c += 1;
if c = n then
exit
end
end;
///Метод печати элементов последовательности
function MyPrint<T>(seq: sequence of T): sequence of T;
begin
foreach var x in seq do
begin
print(x);
yield x
end
end;
begin
var q := Seq(5, 6, -5, 1, 2, 3, 4, 7, 8, 9, -11);
MyPrint(Take(q, 6));
println;
Take(MyPrint(q), 6).Print;
end.
Да, не очень удачную функцию написал я на лекции для печати. Дело в том, что она возвращает последовательность, а последовательность ленива. Чтобы она “выполнилась”, необходимо превратить её в скаляр любым способом - например:
MyPrint(Take(q, 6)).Count;
Немного глуповато выглядит.
Правильнее написать просто процедуру, печатающую последовательность безо всякого yield:
procedure MyPrint<T>(seq: sequence of T);
begin
foreach var x in seq do
print(x);
end;
Понятно. Спасибо большое!
Станислав Станиславович, проконсультируйте, пожалуйста, насчет использования метода GroupBy
. В примере мы группировали массив студентов. Однако возникает сложность при проходе по каждому элементу группы. То есть не работает цикл foreach var s in g do
, где g
— элемент условно двумерной последовательности gg
.
Возникает ошибка «name не объявлен в типе integer
».
type
student = auto class
public
Name: string;
Age: integer;
Group: integer;
end;
begin
var a := arr(new Student('Иванов', 20, 1), new Student('Петров', 19, 2),
new Student('Сидоров', 17, 1), new Student('Зайцев', 16, 3), new Student('Шевченко', 21, 2));
var gg := a.GroupBy(s -> s.Group).OrderBy(g -> g.Key);
gg.Println;
foreach var g in gg do
begin
print(g.key);
{g.println;}
foreach var s in g do
print(s.name, s.Age);
end;
end.
Можно, конечно, убрать внутренний foreach
и печатать через g.println;
. Но так неудобно, ведь будет выводиться группа студента несколько раз:
1 (Иванов,20,1) (Сидоров,17,1)
Я скопировал код к себе - он работает. Выводит:
[(Иванов,20,1),(Сидоров,17,1)] [(Петров,19,2),(Шевченко,21,2)] [(Зайцев,16,3)]
1 Иванов 20 Сидоров 17 2 Петров 19 Шевченко 21 3 Зайцев 16
Может, у Вас старая версия Паскаля? Посмотрите, какая версия и от какого числа
Да, действительно, дело было в версии Паскаля. На сборке 1534 от 09.09.17
не работает, а вот на 1611 от 06.01.18
все в порядке
Мне кажется, что в выложенных лекциях ошибка в бинарном поиске, там не r:=k, а r:=k-1 иначе цикл не прервется
Да, точно. Правильный код такой:
function BinarySearch(a: array of integer; x: integer): integer;
begin
var k: integer;
var (l,r) := (0, a.Length-1);
repeat
k := (l+r) div 2;
if x>a[k] then
l := k+1
else r := k-1;
until (a[k]=x) or (l>r);
Result := a[k]=x ? k : -1;
end;
Станислав Станиславович, у меня какая-то проблема с композицией функция, если я ее делаю обобщенной функцией(как на лекции) возникает исключение, но с определенным типом все хорошо, можете проконсультировать?
Это связано с тем, что Sin и Cos перегружены для типа Complex. И компилятор не может выбрать. Так всё работает:
function Si(x: real) := Sin(x);
function Co(x: real) := Cos(x);
function Comp<T>(f,g: T->T): T->T := x->f(g(x));
begin
Comp(Si,Co);
end.
Нам на практике еще давали такой способ решения: явно указать тип, подставляемый вместо T
, насколько я понимаю.
function Composition<T>(f1, f2: T->T): T->T := x -> f1(f2(x));
begin
var f := Composition&<Real>(sin, cos);
print(f(pi));
end.
Так тоже работает
Какую официальную шпаргалку можно взять на экзамен? Случайно, не этот файл? Шпаргалка PascalABC.NET 2017.pdf (232,6 КБ)
Да, она самая
Конечно работает! В моём примере компилятор тип T сам старается - выводит, а тут Вы ему явно помогаете
Извините пожалуйста, забыл спросить на консультации, а как работает сортировка массива записи по критерию сравнения(это вопрос 86), как я понял, мы придумываем критерий, определяем для него в отдельной процедуре правило, по которому будем сравнивать и затем просто сортируем массив, используя вместо операции сравнения нашу процедуру. Так ли это?
Ну да, именно так. И можно тогда сделать процедуру обобщённой