- PVSM.RU - https://www.pvsm.ru -

Clojure в Белорусском ГУ

БГУ лого
Clojure logo
В этом семестре (осенью 2012) был проведён факультатив по языку Clojure в Белорусском ГУ. В посте будет описан факультатив: причины, программа, задания, результаты, впечатления.

Начало

Я студент 5 курса факультета прикладной математики и информатики в БГУ. Увлекаюсь функциональным программированием, но в курсе нашего обучение в университете ФП не рассматривается вообще, а из парадигм программирования проходили только ООП (java, c++). Я же считаю, что студенты, которые обучаются по специальности информатика должны иметь хоть какое-то представления о ФП (а желательно и других парадигмах). Поэтому и решил попробовать хоть немного исправить ситуацию и провести факультатив. И т.к. опыта и знаний для проведения факультатива по ФП в целом у меня немного, то решил сосредоточиться на более прикладном и простом — на языке Clojure. Clojure [1] — функциональный язык, современный диалект лиспа, исполняющийся в основном на JVM.

В качестве картинок будут использованы скриншоты из задач, которые надо было решить в течении курса.

Задача 2. Змейка.
Змейка. Задача — написать бота.

Программа курса

  1. Введение в Clojure. Описание синтаксиса. Функции. Анонимные функции. Простые арифметические и логические операции. Рекурсия.
  2. Работа с коллекциями. Различные виды коллекций: вектор, множество, ассоциативный массив (map). Функции для работы с ними: map, reduce, filter и т.д. Неизменяемость коллекций.
  3. Работа с коллекциями. Ленивые вычисления. Деструктуринг.
  4. Средства для работы с изменяемым состоянием. Атомы, агенты, рефы (ref). Транзакционная память.
  5. Макросы.
  6. Принцип работы неизменяемых структур данных. Разобрали реализацию PersistentVector [2] и PersistentHashMap [3]
  7. Мультиметоды.
  8. Протоколы, типы и записи (protocols, types, records).
  9. Немного λ-исчисление. Арифметика и логические значения в λ-исчисление.
  10. λ-исчисление. Рекурсия. Реализация списков в λ-исчисление. Пример типизированного λ-исчисления.

Задача 3. Дурак.
Игра «Дурак». Бот игрока — снизу.

Задания

После каждого занятия давалось домашнее задание. Домашнее задание было 2 типов: решение задач на 4clojure и решение интерактивных задач. 4сlojure [4] — сайт с набором небольших задачек от очень простых до весьма сложных и онлайн проверкой. На 4clojure есть удобная особенность — возможность смотреть решения других участников после того, как решил задачу. Я думаю это помогало узнавать, как можно «более функционально» решить задачу.

Интерактивные задачи [5] — задачи, которые должны быть решены на Clojure, при этом решение большинства из них заранее визуализированы, т.е. можно было смотреть на результат решения. Для визуализации были использованы библиотеки Quil [6] (обёртка над Processing'ом [7] для кложура) и Incanter [8] (использовалась для построения графиков).

Список задач:

  • ПВО. Нужно сбить цель задавая угол выстрела. Было 2 варианта. Первый — без учёта гравитации, ракета летит по прямой, цель тоже летит по прямой. Второй вариант учитывал гравитацию (можно стрелять навесом), цель висит в воздухе не двигаясь.
  • Змейка. Реализовать бота для змейки. Бот должен учитывать наличие стен.
  • Дурак. Реализовать бота для карточной игры «Дурак». В основном реализовывали бота без запоминания предыдущих состояний. Но один человек всё же написал бота с запоминанием.
  • Клеточный автомат. Релизовать «фреймворк» для 2-мерного клеточного автомата: написать визуализацию, сделать возможным взаимодействие с программой (остановить, изменить состояния клеток) и самое главное — сделать возможность простого подключения произвольных правил (таких как Жизнь, Brian's Brain [9], Wireworld [10] и другие).
  • k-means. Реализовать алгоритм k-means с фиксированным k. А также попробовать написать алгоритм, который будет подбирать наилучшее k.
  • Символьное дифференцирование. Написать функцию, которая на вход принимает кложурное выражение, например (* 2 x), на выход отдаёт производную: (+ (* 0 x) (* 2 1)). Упрощать полученный результат не требовалось. Визуализация — построения графиков функции и её первой, и второй производных.
  • λ-исчисление. Реализовать арифметические функции (+, -, *, ^). Написать рекурсивную функцию для вычисления суммы арифметической прогрессии чисел от 1 до n. Реализовать функции для работы со списками (head, tail, cons, empty?). Доп задание — написать map и reduce для таких списков.

Задача 4. Клеточный автомат.
Клеточный автомат Wireworld. Автомат реализует логический XOR.

Процесс

Занятия проводились по субботам, 1 раз в неделю. Для внеклассного общения использовалась гугло-группа. Задания по 4clojure естественно проверялись на самом сайте. Для решения интерактивных задач студенты форкали репозиторий на гитхабе и решали в форке. Проверять было весьма удобно, особенно учитывая то, что гитхаб позволяет оставлять комментарии к коммитам. Так что я мог указывать на неэффективные или не очень красивые места в решениях. У всех конечно вначале были императивные решения, использующие явные циклы, часто использовали изменяемые состояния и атомы там, где они на самом деле были лишними. К сожалению не могу точно оценить, насколько изменились решения к концу факультатива, насколько они стали более функциональными, но надеюсь, что стали.

Проекты

Была идея — чтобы все разбились на группы по 2-3 человека и каждая группа в течение семестра делала свой проект. Были предложены такие варианты: мультиплеерная змейка, простой физический движок, утилита для обработки текстовых документов (статистика, ещё что-нибудь), сделать аналог этого [11] приложения. Ну и конечно можно было предлагать свои варианты. Но идея как-то не нашла отклика. Возможно домашних заданий и так хватало, учитывая, что мой факультатив был добровольным и к учёбе в университете никак не относился.

Задача 6. Производные.
Символьное дифференцирование. 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

Источник [12]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/clojure/24091

Ссылки в тексте:

[1] Clojure: http://ru.wikipedia.org/wiki/Clojure

[2] PersistentVector: http://blog.higher-order.net/2009/02/01/understanding-clojures-persistentvector-implementation/

[3] PersistentHashMap: http://blog.higher-order.net/2009/09/08/understanding-clojures-persistenthashmap-deftwice/

[4] 4сlojure: https://www.4clojure.com/

[5] Интерактивные задачи: https://github.com/nbeloglazov/clojure-interactive-tasks

[6] Quil: https://github.com/quil/quil

[7] Processing'ом: http://processing.org/

[8] Incanter: https://github.com/liebke/incanter

[9] Brian's Brain: http://en.wikipedia.org/wiki/Brian%27s_Brain

[10] Wireworld: http://en.wikipedia.org/wiki/Wireworld

[11] этого: http://habrahabr.ru/company/luxoft/blog/150966/

[12] Источник: http://habrahabr.ru/post/164701/