Обучение
October 17, 2022

Как учить начинающих лямбда-функциям

Лямбда-функции - один из основных примитивов современного программирования. Они эффективно используются в ряде современных языков вместе с функциями стандартной библиотеки.

Однако в мире обучения программированию начинающих существует миф, что лямбда-функции - это сложно и даже вредно, потому что якобы препятствует пониманию алгоритмов.

Развеем этот миф. Основная мысль настоящей статьи: лямбда-функции - это просто. Им надо учить начинающих. Это улучшает методику обучения, позволяя решать реальные задачи и формируя понимание, зачем вообще нужно программирование.

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

Итак, как учить лямбда-функциям?

Прежде всего давайте вспомним, что такое функция. Обычно начинающие вспоминают линейную и квадратичную функцию, и отправной точкой здесь является функция

f(x) = x*x

Она преобразует значение x в значение x*x, что можно записать так:

f: x -> x*x

Имя функции f здесь неважно, и его можно опустить. Получим следующую запись:

x -> x*x

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

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

Задача 1. Дан массив. Преобразовать в нем все элементы в их квадраты.

Решение. Воспользуемся стандартным методом a.Transform с параметром, являющимся лямбда-функцией и преобразующим элемент в его квадрат. Записать это просто:

a.Transform(x → x*x);

Читается такая запись легко: в массиве a преобразуем каждый элемент x в x*x.

Вот полная программа:

##
var a := Arr(1..9);
a.Println;
a.Transform(x → x*x);
a.Println;

Результат:

1 2 3 4 5 6 7 8 9
1 4 9 16 25 36 49 64 81

Аналогичный код, использующий алгоритм:

for var i:=0 to a.Length-1 do
  a[i] := a[i] * a[i];

Следующее принципиально другое применение лямбда-выражений - использование их в качестве условий.

Задача 2. Дан случайный массив целых. Найти в нем количество четных.

Решение 1. Традиционное решение - завести счетчик, пройтись по массиву и увеличивать счетчик всякий раз когда элемент четный:

##
var a := ArrRandomInteger(10);
a.Println;

var cnt := 0;
foreach var x in a do
  if x.IsEven then 
    cnt += 1;
Print(cnt);

Результат:

93 44 91 85 64 82 29 62 16 84
6 

Решение 2. Воспользуемся стандартным методом массивов a.Count. В качестве параметра передадим ему лямбда-условие - лямбда-функцию, в правой части которой выражение логического типа:

x → x.IsEven

Здесь стрелка читается как "такое что": x такое что оно чётное.

Итак, решение:

##
var a := ArrRandomInteger(10);
a.Println;

a.Count(x → x.IsEven).Print;

Обратим внимание, что результатом функции a.Count является целое число, которое мы выведем методом Print. Таким образом, решение состоит из одной строки вместо пяти и не менее понятно.

В качестве последнего примера в настоящей статье приведем задачу рисования графика функции. Функция разумеется будет задаваться как лямбда.

Следующая задача родственна предыдущей и известна как задача фильтрации.

Задача 3. Отфильтровать в целочисленном массиве числа, меньшие 50.

Решение. Здесь решением является не одно число, а набор чисел, удовлетворяющих условию. Причем, количество этих чисел заранее неизвестно.

Воспользуемся стандартным методом a.Where, в качестве параметра которого передается условие фильтрации x → x < 50:

##
var a := ArrRandomInteger(10);
a.Println;

a.Where(x → x < 50).Print;

Результат:

48 85 65 24 39 95 17 75 73 89
48 24 39 17

Здесь обратим внимание, что не существует сколько-нибудь короткого и не перегруженного техническими деталями решения в виде алгоритма, понятного начинающим.

В качестве последнего примера в настоящей статье приведем задачу рисования графика функции. Функция разумеется будет задаваться как лямбда.

Задача 4. Вывести график функции f(x) = x * sin(x)

Решение.

##
uses GraphWPF;

DrawGraph(x -> x*Sin(x));

Результат:

Заключение. Лямбда-функции - современный примитив программирования, позволяющий с легкостью решать стандартные задачи. Их изучение доступно школьникам - для этого необходимо использовать правильную методику, сочетая классическое обучение алгоритмам с использованием стандартных методов, в которых лямбда-функции выступают в качестве параметров.