Comments 5
Информация была полезна, благодарю.
Мне всегда интересно читать о собственных реализациях чего бы то ни было. Именно из такого рождаются новые ниши и стандарты. Спасибо что поделились, я знаю как не просто на это решиться в наше время : )
Но есть вопрос. Разве создание копии массива в момент переопределения его элемента - не ведет к путанице при отладке? По моему в таких случаях проще вызывать явное копирование массива. И как быть, если понадобилось изменить исходный массив, имея ссылку на него? По моей беглой оценке, поведение, описанное в статье требуется в очень редких случаях. Буду рад если мои рассуждения ошибочны : )
Попробую предположить, что автор этого языка хочет подтолкнуть пользователей к более функциональному стилю, который среди прочего требует иммутабельности.
Сравните:
var data = ReadData();
EnrichData(data);
return data;
let rawData = ReadData();
let mappedData = EnrichData(rawData);
return mappedData;
Второй подход, на первый взгляд, мало отличается от первого, и к тому же может потребовать большего потребления памяти. Но при этом он не хранит и не модифицирует состояние, что очень сильно облегчает отладку, а также открывает возможности для функциональной композиции с отложенным вычислением результата по требованию.
более функциональному стилю, который среди прочего требует иммутабельности
На Shar больше всего влияния оказал Haskell и мне очень нравится функциональный подход, правда только и лишь в сочетании с ленивостью. Но у функционального подхода есть и множество недостатков: непредсказуемое потребление памяти, недетерминированность кода. Также слышал от человека, который использовал Haskell в продакшене, что отлаживать программы на Haskell очень тяжело и бывали случаи когда без дебага программа падала, а с ним - нет. В Shar я взял лучшее (то что я считаю лучшим) из Haskell, а именно - возможность писать функции не обращая внимание на на данные вне функции, а также классы типов, но в Shar нет недостатков (то что я считаю недостатками) Haskell. Shar - детерминированный язык, даже освобождение памяти происходит в предсказуемом месте кода.
И как быть, если понадобилось изменить исходный массив, имея ссылку на него?
В языке нет ссылок.
По моей беглой оценке, поведение, описанное в статье требуется в очень редких случаях.
Я увлекаюсь программированием вот уже 21 год и за всё это время, самые сложные в исправлении баги с которыми я сталкивался, были вызваны тем, что есть несколько ссылок на объект и происходит запись по ссылке, которая была рассчитана только на чтения. Такая проблема обычно сразу себя не проявляет, а программа некоторое время работает, а затем происходит ошибка, при этом код который вызвал ошибку полностью корректен и никак собственно с проблемой не связан. Бывало что я тратил десяток часов на поиск и исправление ошибок. Подход используемый в Shar делает невозможным совершение подобных ошибок.
Также некоторое время я программировал на Haskell и мне очень нравилось то, что не нужно париться про состояние данных вне функции, что позволяет абстрагироваться от всего кода и сфокусироваться на одной функции. Тоже самое и в Shar, только в Haskell это достигается за счёт иммутабельности, а в Shar за счёт невозможности изменить данные одного объекта при изменении другого.
Разве создание копии массива в момент переопределения его элемента - не ведет к путанице при отладке?
Сейчас никакого отладчика нет. Честно признаюсь - последний раз я пользовался отладчиком лет 10 назад, но из моих воспоминаний я не понимаю почему должна быть путаница.
По моему в таких случаях проще вызывать явное копирование массива.
Проще. Но это приведёт к значительно увеличению потребления памяти, а так же к снижению производительности.
Тесты своей реализации ассоциативных массивов vs хеш-таблица