В этом семестре (осенью 2012) был проведён факультатив по языку Clojure в Белорусском ГУ. В посте будет описан факультатив: причины, программа, задания, результаты, впечатления.
Начало
Я студент 5 курса факультета прикладной математики и информатики в БГУ. Увлекаюсь функциональным программированием, но в курсе нашего обучение в университете ФП не рассматривается вообще, а из парадигм программирования проходили только ООП (java, c++). Я же считаю, что студенты, которые обучаются по специальности информатика должны иметь хоть какое-то представления о ФП (а желательно и других парадигмах). Поэтому и решил попробовать хоть немного исправить ситуацию и провести факультатив. И т.к. опыта и знаний для проведения факультатива по ФП в целом у меня немного, то решил сосредоточиться на более прикладном и простом — на языке Clojure. Clojure — функциональный язык, современный диалект лиспа, исполняющийся в основном на JVM.
В качестве картинок будут использованы скриншоты из задач, которые надо было решить в течении курса.
Змейка. Задача — написать бота.
Программа курса
- Введение в Clojure. Описание синтаксиса. Функции. Анонимные функции. Простые арифметические и логические операции. Рекурсия.
- Работа с коллекциями. Различные виды коллекций: вектор, множество, ассоциативный массив (map). Функции для работы с ними: map, reduce, filter и т.д. Неизменяемость коллекций.
- Работа с коллекциями. Ленивые вычисления. Деструктуринг.
- Средства для работы с изменяемым состоянием. Атомы, агенты, рефы (ref). Транзакционная память.
- Макросы.
- Принцип работы неизменяемых структур данных. Разобрали реализацию PersistentVector и PersistentHashMap
- Мультиметоды.
- Протоколы, типы и записи (protocols, types, records).
- Немного λ-исчисление. Арифметика и логические значения в λ-исчисление.
- λ-исчисление. Рекурсия. Реализация списков в λ-исчисление. Пример типизированного λ-исчисления.
Игра «Дурак». Бот игрока — снизу.
Задания
После каждого занятия давалось домашнее задание. Домашнее задание было 2 типов: решение задач на 4clojure и решение интерактивных задач. 4сlojure — сайт с набором небольших задачек от очень простых до весьма сложных и онлайн проверкой. На 4clojure есть удобная особенность — возможность смотреть решения других участников после того, как решил задачу. Я думаю это помогало узнавать, как можно «более функционально» решить задачу.
Интерактивные задачи — задачи, которые должны быть решены на Clojure, при этом решение большинства из них заранее визуализированы, т.е. можно было смотреть на результат решения. Для визуализации были использованы библиотеки Quil (обёртка над Processing'ом для кложура) и Incanter (использовалась для построения графиков).
Список задач:
- ПВО. Нужно сбить цель задавая угол выстрела. Было 2 варианта. Первый — без учёта гравитации, ракета летит по прямой, цель тоже летит по прямой. Второй вариант учитывал гравитацию (можно стрелять навесом), цель висит в воздухе не двигаясь.
- Змейка. Реализовать бота для змейки. Бот должен учитывать наличие стен.
- Дурак. Реализовать бота для карточной игры «Дурак». В основном реализовывали бота без запоминания предыдущих состояний. Но один человек всё же написал бота с запоминанием.
- Клеточный автомат. Релизовать «фреймворк» для 2-мерного клеточного автомата: написать визуализацию, сделать возможным взаимодействие с программой (остановить, изменить состояния клеток) и самое главное — сделать возможность простого подключения произвольных правил (таких как Жизнь, Brian's Brain, Wireworld и другие).
- k-means. Реализовать алгоритм k-means с фиксированным k. А также попробовать написать алгоритм, который будет подбирать наилучшее k.
- Символьное дифференцирование. Написать функцию, которая на вход принимает кложурное выражение, например
(* 2 x)
, на выход отдаёт производную:(+ (* 0 x) (* 2 1))
. Упрощать полученный результат не требовалось. Визуализация — построения графиков функции и её первой, и второй производных. - λ-исчисление. Реализовать арифметические функции (+, -, *, ^). Написать рекурсивную функцию для вычисления суммы арифметической прогрессии чисел от 1 до n. Реализовать функции для работы со списками (head, tail, cons, empty?). Доп задание — написать map и reduce для таких списков.
Клеточный автомат Wireworld. Автомат реализует логический XOR.
Процесс
Занятия проводились по субботам, 1 раз в неделю. Для внеклассного общения использовалась гугло-группа. Задания по 4clojure естественно проверялись на самом сайте. Для решения интерактивных задач студенты форкали репозиторий на гитхабе и решали в форке. Проверять было весьма удобно, особенно учитывая то, что гитхаб позволяет оставлять комментарии к коммитам. Так что я мог указывать на неэффективные или не очень красивые места в решениях. У всех конечно вначале были императивные решения, использующие явные циклы, часто использовали изменяемые состояния и атомы там, где они на самом деле были лишними. К сожалению не могу точно оценить, насколько изменились решения к концу факультатива, насколько они стали более функциональными, но надеюсь, что стали.
Проекты
Была идея — чтобы все разбились на группы по 2-3 человека и каждая группа в течение семестра делала свой проект. Были предложены такие варианты: мультиплеерная змейка, простой физический движок, утилита для обработки текстовых документов (статистика, ещё что-нибудь), сделать аналог этого приложения. Ну и конечно можно было предлагать свои варианты. Но идея как-то не нашла отклика. Возможно домашних заданий и так хватало, учитывая, что мой факультатив был добровольным и к учёбе в университете никак не относился.
Символьное дифференцирование. f = sin(2x). Изображены f, f', f''
Мотивация и подарки
В начале факультатива домашка никак не контролировалась. И она как-то слабо выполнялась, хотя судя по анонимному опросу «была интересной»… Тогда появилась идея награждать какими-то плюшками за решение домашек. После обсуждения с друзьями была предложена идея, которая мне очень понравилась: тот, кто выполнит больше 50% домашки, получит именную кружку со своим результатом. Так что был стимул выполнить на 100%, чтобы потом 90% глаза не мозолили. Для этого был создан рейтинг — табличка в гуглодоках, в которой вёлся учёт успехов студентов.
Кстати в конце я спросил, помогло ли это в выполнении заданий. Все сказали что, да. Большинство мотивировал рейтинг, в котором они могли видеть свой прогресс. Некоторых мотивировала сама кружка :)
Итоги
По финальному опросу можно сделать вывод, что факультатив понравился. Я думаю он был полезен, если даже они и не будут использовать clojure или ФП в повседневной жизни. Что касается меня, то мне очень понравилось. Кстати идея о факультативе зародилась на парах педагогики, где мы все жаловались, что наше высшее образование плохое и нас учат никому не нужной ерунде. Тогда наш преподаватель и спросил, почему же мы сами ничего по этому поводу не пытаемся сделать.
И напоследок немного фактов:
- На факультатив ходило человек 10, в основном студенты 2 курса.
- Было задано 65 задач с 4clojure. В среднем каждый решил 59.
- Было задано 8 интерактивных задач. В среднем каждый решил 6.
- Один из студентов нашёл 1 серьёзный баг в Quil.
- 3 студента выполнили задания на 100%. Средний результат: 88%
- Все, кто делал домашку и продержались до конца — получили кружку. Таких 8 человек. 2 человека посещали, но не выполняли задания.
Именные кружки.
Автор: Nikelandjelo