2017-02-08 21 views
3

Мое основное понимание линзирования is that «Объектив - это значение, представляющее карты между сложным типом и одним из его составляющих. Эта карта работает в обоих направлениях: мы можем получить или« получить доступ »к составляющей и set или «mutate» it »Scala: Lensing vs mutable design

Я наткнулся на это, когда я разрабатывал библиотеку машинного обучения (нейронные сети), которая требует сохранения большой структуры данных параметров, группы которых необходимо обновлять на разных этапах алгоритма , Я хотел создать неизменную структуру данных параметров, но изменение одной группы параметров требует копирования всех параметров и воссоздания новой структуры данных, что звучит неэффективно. Не удивительно other peoplehave thought это тоже. Некоторые люди предлагают использовать линзы, которые в некотором смысле позволяют изменять неизменяемые структуры данных. В то время как некоторые другие люди предлагали просто использовать для этого переменные. К сожалению, я ничего не мог найти при сравнении этих двух парадигм, по скорости, по пространству, по сложности кода и т. Д.

Теперь вопрос в том, какие плюсы и минусы использования линзирования или изменчивого дизайна?

ответ

4

Компромисс между ними в значительной степени, как вы догадались. Объективы менее сложны, чем отслеживание изменений в большой неизменяемой структуре данных вручную, но для этого требуется более сложный код, чем изменчивая структура данных, и есть некоторая часть служебных данных во время выполнения. Чтобы знать, сколько, вы должны были бы измерить, но это, вероятно, меньше, чем вы думаете, потому что большая часть обновленной структуры не копируется, но поделился.

Мутируемые структуры данных проще и несколько быстрее модифицировать, но сложнее рассуждать, потому что теперь вы должны учитывать функции заказа, учитывать беспокойство о параллелизме и т. Д.

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

Например, у вас может быть два отдельных Maps с одним и тем же типом ключей и различными типами простых значений, а не один Map с более сложным значением. Это не только повышает производительность, но и упрощает модульный код.

+0

Спасибо за приятный ответ. Один вопрос: почему линзирование не создает проблем для параллелизма? (например, если он похож на mutables, имеет смысл, если он имеет те же проблемы с параллелизмом) – Daniel

+1

Lensing по-прежнему неизменен, он просто создает API, похожий на глубокую мутацию. Когда вы делаете «набор», любой, у кого есть ссылка на какую-либо часть старой структуры, по-прежнему будет иметь старое неизмененное значение. Вы должны назначить результат новой переменной в новой области. –