Занятие 6. Pascal abc.net: Lambda-выражения

Рассматривается работа с лямбда-выражениями в abc.net

Лямбда-выражения

  • Лямбда-выражение представляет собой некоторое безымянное выражение, представляющее функциональную зависимость.
  • На его основе компилятор строит функцию, некоторым образом идентифицирует ее и подменяет этим идентификатором лямбда-выражение.
  • Лямбда-выражение можно сохранить в процедурных переменных, либо передать в качестве параметров процедурного типа.
  • Пример 1: Пример лямбда-выражения, возвращающей сначала квадрат параметра, а затем возвращает параметр в третьей степени. Лямбда-выражение сохранено в процедурной переменной x.
    1. Описание процедурной переменной, а затем связывание ее с лямбда-выражением:

    begin
     var x: integer-> integer;
     x:= t -> t * t;
     Print(x(7)); // 49
     x := t -> t * t * t;
     Print(x(7)); // 343
    end.

    2. Описание и одновременно инициализация процедурной переменной:

    begin
     var x: integer-> integer:= t -> t * t;
     Print(x(7)); // 49
     x := t -> t * t * t;
     Print(x(7)); // 343
    end.
    IDE PascalABC.NET позволяет вместо -> использовать красивую стрелочку (на клавиатуре: при зажатой клавише Alt набираем 26 на малой цифровой клавиатуре).
    Пример 2: Пример процедурной переменной с двумя параметрами, которая возвращает максимальный из параметров, используя лямбда-выражение.
    begin
      var f: (integer,integer)integer :=(x, y) -> if x > y then result:=x else result:=y;
      print(f(5,13))
    end.
    Если процедурная переменная предназначена для хранения процедур (а не функций), то при ее описании после стрелки -> надо указать пустые скобки ().
    Пример 3: Пример процедурной переменной с двумя параметрами, которая распечатывает максимальный из параметров, используя лямбда-выражение.
    begin
      var f: (integer,integer)() :=(x, y) -> if x > y then print(x) else print(y);
      f(5,13)
    end.
    Пример 4: Пример лямбда-выражения, распечатывающей квадрат параметра.
    begin
    var x: integer-> () := t -> (t * t).Print();
    x(5) // 25
    end.
    Пример 5: Пример процедурной переменной, с кортежным присваиванием: переменная связана с лямбда-выражением, которое принимает два целых числа и возвращает их сумму и произведение:
    1. Классическое решение через процедуру:

    procedure Pr(a,b:integer; var sum,mult:integer);
    begin
      sum:=a+b;
      mult:=(a*b);
    end;
    begin
      var sum,mult:integer;
      Pr(2,4,sum,mult);
      print(sum,mult) // (6,8) 
    end.

    2. Решение через процедурную переменную с кортежным присваиванием и лямбда-выражение:

    begin
      var f: (integer,integer) -> (integer, integer);
      f := (a, b) -> (a + b, a * b);
      print(f(2, 4)) // (6,8) 
    end.
    Лямбда-функция в виде параметра
    Пример: Написать процедуру, выводящую таблицу значений произвольной функции одного аргумента на отрезке [a;b].

    Результат при a=-5, b=-1 и функции x -> x * x:

    -5 25 
    -4 16 
    -3 9 
    -2 4 
    -1 1 
    

    ✍ Решение:

      procedure Lamb(a, b: integer; f: real-> real);
      begin
        for var x := a to b do 
        begin
          Println(x, f(x));
        end
      end;
       
      begin
        Lamb(-5, 3, x -> x * x);
        Writeln;
      end.

    Решение задач

    Задание 1: Создайте процедурную переменную с одним параметром — двузначное число, возвращающую число, в котором поменяны местами цифры. Свяжите переменную с лямбда-выражением для выполнения задания. Выполните задание дважды: процедурная переменная возвращает значение и процедурная переменная распечатывает значение. (см. пример 2, 3, 4)

    Результат:

    введите двузначное число 
    >> 72
    27 
    

    [файл: Lam01.pas]

    Задание 2: Вычислить значение переменной у по одной из двух ветвей:

    Для решения создать процедурную переменную с двумя параметрами — a и b, и связать ее с лямбда-выражением. Выполните задание дважды: процедурная переменная возвращает значение и процедурная переменная распечатывает значение. (см. пример 2, 3, 4)

    Результат:

    введите два числа 
    >>2
    >>5
    результат: 3 
    

    [файл: Lam02.pas]

    Задание 3: Описать функцию TriangleP(a,h), находящую периметр равнобедренного треугольника по его основанию a и высоте h, проведенной к основанию. (см. пример 5 решение 2)

    1. Опишите процедурную переменную TriangleP, определив ее тип как функцию, принимающую два вещественных параметра и возвращающую вещественный результат:

    var TriangleP: (real, real) -> real;

    2. Затем присвойте этой переменной лямбда-выражение, которое по двум параметрам a и h — основанию и высоте равнобедренного треугольника — вычисляет периметр этого треугольника (P = 2b+a; нахождение стороны: b2 = (a/2)2 + h2)

    Результат:

    введите два числа 
    >>4
    >>6
    результат: 16.6491106406735 
    

    [файл: Lam03.pas]

    Задание 4: Описать процедуру TrianglePS(a, P, S), вычисляющую по стороне a равностороннего треугольника его периметр P = 3·a и площадь S = a2·(3)1/2/4 (a — входной, P и S — выходные параметры; все параметры являются вещественными). С помощью этой процедуры найти периметры и площади трех равносторонних треугольников с данными сторонами. Выполнить двумя способами: классическая процедура и процедурная переменная, связанная с лямбда-выражением. (см. пример 5 решение 1 и 2)

    Результат:

    >>2
    61.73205080756888
    >>5
    1510.8253175473055
    >>6
    1815.5884572681199
    

    [файл: Lam04.pas]