Зарелизился Clojure 1.7.0-alpha5.
Попробовать можно:
- скачав jar
- через Leiningen: [org.clojure/clojure "1.7.0-alpha5"]
Несколько нововведений в alpha5:
Трансдьюсеры map-indexed, distinct и interpose теперь принимают меньше параметров, подготавливая коллекцию к обработке с помощью transient! и таким образом стали быстрее. См. подробнее CLJ-1601.
Функции set и vec теперь быстрее во многих случаях. См. подробнее CLJ-1546 и CLJ-1618. Некоторые улучшения для vec блокируются CLJ-1499, который будет принят позднее.
Исправлены 2 бага с AOT компиляцией: CLJ-979 and CLJ-1544, а также их многочисленные дубликаты. Спасибо Nicola Mometto за отладку.
Все остальных изменения помечены в общем списке ниже как (alpha5)
.
Изменения с 1.6.0
Новое и улучшенное
Трансдьюсеры
Трансдьюсеры - это новый способ отделить логику алгоритмических преобразований от их применения в конкретном случае, это функции, которые изменяют поведение функций, основанных на reduce, чтобы составить общий план по применению всех трансформаций разом.
Подробнее можно почитать тут: http://clojure.org/transducers
Множество существующих функций над коллекциями теперь могут принимать другой набор агрументов (на один меньше чем ранее). Такой набор будет возвращать трансдьюсер, который оборачивает логику преобразования, но независим от ленивой обработки коллекции. Эти функции включают в себя:
- conj (conjs to [])
- map
- mapcat
- filter
- remove
- take
- take-while
- drop
- drop-while
- cycle
- take-nth
- replace
- partition-by
- partition-all
- keep
- keep-indexed
- map-indexed (alpha5)
- distinct (alpha5)
- interpose (alpha5)
Также добавлены новый функции-трансдьюсеры:
- cat - конкатенирует содержание каждого объекта на входе
- de-dupe - удаляет повторяющиеся элементы
- random-sample - отдает случайные элемены из коллекции
А “completing” функция может использовать для маркирования конечной трансформации.
Следующие функции могут использоваться для применения трансдьюсеров разными способами:
- sequence - принимает трансформацию и коллекцию и возвращает ленивую последовательность
- transduce - обрабатывает коллекцию трансформацией (жадно)
- eduction - возвращает итератор с элементами после применения к ним трансдьюсера
- run! - используется для применения трансформаций с побочными эффектами
Также сделано несколько внутренних изменений для поддержки трансдьюсеров:
- volatiles - набор функций (volatile!, vswap!, vreset!, volatile?) для создания и использования volatile контейнеров для трансдьюсеров с внутренним состоянием. Volatiles быстрее чем атомы, но не дают атомарных гарантий и должны быть использованы только в thread-safe среде
- array iterators - добавлена поддержка для итераторов по массивам
А также несколько других исправлений во время разработки этой функциональности:
- CLJ-1511
- CLJ-1497
- CLJ-1549
- CLJ-1537
- CLJ-1554
- CLJ-1601 (alpha5)
- CLJ-1606 (alpha5)
- CLJ-1621 (alpha5)
- CLJ-1600 (alpha5)
Создание keyword и symbol
В ответ на CLJ-1439 были сделаны следующие изменения:
- при создании символов и ключей “бутылочным горышком” было “интернирование” их имени и создание строк с именем пространства имен.Устранение этого привело к увелечению производительности
- ключи уже кешируются, но теперь еще и очищается очередь закешированных ссылок, при промахе мимо кеша
Предупреждение о “упакованной” математике
Одной из причин снижения скорости на арифметических операциях было оперирование “упакованными” значениями.
Чтобы сделать обнаружение такого рода проблем проще, введен параметр *unchecked-math*, который будучи равен :warn-on-boxed,
сгенерирует предупреждение об этом.
Например:
user> (defn plus-2 [x] (+ x 2)) ;; нет предупреждения об "упаковке"
#'user/plus-2
user> (set! *unchecked-math* :warn-on-boxed)
true
user> (defn plus-2 [x] (+ x 2)) ;; включаем предупреждение
Boxed math warning, NO_SOURCE_PATH:10:18 - call: public static java.lang.Number
clojure.lang.Numbers.unchecked_add(java.lang.Object,long).
#'user/plus-2
user> (defn plus-2 [^long x] (+ x 2)) ;; используйте подсказку для избежания "упаковки"
#'user/plus-2
update - как update-in для первого уровня
update
- новая функция для update-in поведения над ключами верхнего уровня:
(update m k f args...)
Например:
user> (update {:a 1} :a inc)
{:a 2}
user> (update {:a 1} :a + 2)
{:a 3}
user> (update {} :a identity) ;; отсутствующий ключ будет иметь значение nil
{:a nil}
См. CLJ-1251
Улучшения
Сообщения об ошибках
- CLJ-1261
Указание на правильный неймспейс при наличии в нем некорректного defrecord - CLJ-1169
Вывод строки, столбца и файла при ошибках в макросах - CLJ-1297
Более подробная подсказка, если пространство имен с символом “-” не найдено в файле с символом "_"
Документация
- CLJ-1417
Исправлена документация к clojure.java.io/input-stream - CLJ-1357
Опечатка в документации gen-class doc-string - CLJ-1479
Опечатка в примере к filterv - CLJ-1480
Опечатка в документации defmulti - CLJ-1477
Опечатка в документации deftype - CLJ-1478
Опечатка в справке clojure.main
Производительность
- CLJ-1430
Улучшена производительность partial - CLJ-1384
clojure.core/set использует transients - CLJ-1429
Кеширование метода для значения по умолчанию в multimethod - CLJ-1529
Увеличение скорости компиляции устранением лишних Class.forName() - CLJ-1546 (alpha5)
vec стал быстрее - CLJ-1618 (alpha5)
set стал быстрее
Другие улучшения
- CLJ-1191
apropos теперь показывает пространство имен, где найден символ - CLJ-1378
Подсказки типов работают с анонимными функциями - CLJ-1498
удалена проверка владельца потока из transients - это препятствовало некоторым корректным случаям использования transients в core.async, когда transient, созданный в одном треде использовался в другом потоке пула, сохраняя потокобесопасность - CLJ-803
Интерфейс IAtom выделен из Atom. - CLJ-1315
Классы не инициализируются при импорте - CLJ-1330
Устранено перекрытие имен функций и именованных замыканий - CLJ-1349
Обновлена зависимость test.generative и добавлена зависимость от test.check - CLJ-1546 (alpha5)
vec работает только с тем, что реализует Iterable или IReduceInit - CLJ-1618 (alpha5)
set работает только с тем, что реализует Iterable или IReduceInit - CLJ-1633 (alpha5)
PersistentList/creator корректно обрабатывает ArraySeqs
Фиксы
- CLJ-1362
Reduce корректно обрабатывает примитивные векторы - CLJ-1388
Корректное сравнение структур от вложенных вызовов map->record - CLJ-1274
Возможность указать опции компиляции через системные свойства - CLJ-1241
Ошибка при неявном переопределении функции из clojure.core - CLJ-1185
reductions теперь не игнорирует clojure.lang.Reduced значение - CLJ-1039
Использование def с метаданными {:type :anything} вызывало ClassCastException во время вывода на экран - CLJ-887
Error when calling primitive functions with destructuring in the arg vector - CLJ-823
Замыкание двух seque друг на друга вызывало блокировку - CLJ-738
Double/NaN неконсистентно сравнивалось - CLJ-1408
Keyword and Symbol сериализуются теперь в transient значение - CLJ-1466
clojure.core/bean эксплицитно реализует Iterable - CLJ-1578
перезагрузка функций сlojure.core бросало исключение - CLJ-1501
Логика эквивалентности ленивых последовательностей теперь не использует equiv() - CLJ-1572 (alpha5)
into (и другие функции, полагающиеся на reduce) требуют релизации только IReduceInit интерфейса - CLJ-1619 (alpha5)
PersistentVector теперь явно реализует reduce без начального значения - CLJ-1580 (alpha5)
Transient коллекции теперь гарантируют видимость в потоке - CLJ-1590 (alpha5)
Некоторые имплементации IReduce/IReduceInit игнорировали reduced значение - CLJ-979 (alpha5)
Исправлена компиляция deftype классов - CLJ-1544 (alpha5)
Исправлена AOT компиляция пространств имен, загруженных до начала компиляции