Dmitrii Kashin -> debian-russian@lists.debian.org @ Sat, 17 Oct 2015 00:17:13
+0300:
>> >> DK> За время работы с ним меня приятно удивило после Haskell:
>> >>
>> >> DK> 1) Позволяет более просто комбинировать функциональное и
>> императивное
>> >> DK> программирование: не надо изворачиваться монадами, чтобы добиться
>> >> DK> последовательного выполнения команд.
>> >>
>> >> ...
>> >>
>> >> а зачем, собственно, добиваться последовательного выполнения никак не
>> >> связанных между собой команд?
>>
>> DK> Я думаю, тут есть недоразумение. Требование последовательного
>> выполнения
>> DK> определённых команд как раз и определяет связь между ними. Если конечно
>> DK> не считать, что связь -- это "результат А нужен для вычисления B". Тут
>> DK> важно понять, что императивное программирование -- это именно
>> DK> программирование с изменением состояния системы.
>>
>> Тогда это, натурально, связанные между собой команды. Для вычисления B
>> требуется состояние системы, полученное после вычисления A.
>>
>> Хаскельный компилятор просто более аккуратно подходит к вопросу
>> зависимости (он машина, ему внимания не жалко), и может обнаружить
>> независимость там, где программист ее не обнаружил, и по умолчанию
>> полагает, что зависимость есть.
DK> Теоретически это наверное плюс. Но мне бы реальных ситуаций. У меня
DK> такое чувство, что вполне себе может случится обратное: зависимость
DK> есть, а компилятор её не обнаружил, и решил что-нибудь
DK> соптимизировать. В этом случае мне кажется, чем тупее система -- тем
DK> лучше.
Если компилятор ее не обнаружил, то он не смог скомпилировать код. Ему
же надо превратить функциональную зависимость в императивный код.
Он же работает по схеме "для вычисления вот этого мне нужно вот это, вот
это и вот это. Где я их возьму?" А если ему в процессе этого выяснения
что-то _не_ понадобилось, то от него зависимости нет по построению.
>> DK> Зачем это нужно? Ну, бывают разные случаи.
>>
>> DK> Бывает, что это повышает производительность. В случае большого словаря
>> DK> создание его дубликата при изменении значения одного ключа создаёт
>> очень
>> DK> большие накладные расходы.
>>
>> Это, как я уже писал, вопрос не императивности, а мутабельности. Нам,
>> вообще говоря, совершенно незачем выполнять строго последовательно
>> изменения значений у двух разных ключей.
DK> Извините, у меня в мозгу императивность и мутабельность неразрывно
DK> связаны. Объясните, почему Вы разделяете их? Мутабельность -- это
DK> возможность объекта менять состояние. Императивность -- стиль
DK> программирования, при котором программа проходит через
DK> последовательность состояний.
Императивность - это стиль программирования, при котором единица
программирования - это выполнение инструкции, самой по себе
бессмысленной, и только в комплекте со всеми остальными решающей
задачу — преобразовать вход в выход.
Модель типа такая: вот у нас на входе реальный мир. Мы подкрутили
чуть-чуть тут, потом чуть-чуть здесь... Опа, внезапно на выходе у нас
реальный мир с дополнительными нужными свойствами (и дополнительными
ненужными, которые мы не заметили :).
Каждое изменение производится локально, но имеет неопределенные
последствия при взгляде из точки изменения.
Функциональный стиль тоже преобразует реальный мир на входе в реальный
мир на выходе, т.е. мутирует его. Но в иной модели:
Мы хотим, чтобы вот тут было вот так. Для этого надо взять вот это и
вот это и вот так их скомбинировать. Вот это можно получить вот так...
Что именно при этом изменится в мире, можно тупо выяснить автоматически,
пройдя по дереву зависимостей. То, что не затронуто деревом
зависимостей, гарантированно не изменится в результате _наших_ действий.
А так мутировать-то мы его мутируем...
>> Хаскель, кстати, будет делать дубликат не всего словаря, а только той
>> ветки, в которой поменяли значение. Для, допустим, Map это O(log n).
DK> Ну и таки да, Хаскель не будет делать дубликат словаря, ибо эти "разницы
DK> между исходной версией и данной" для него суть thunk-и, и это одно из
DK> полезных следствий ленивости.
Нет, не поэтому. Когда он вычислит эти thunk'и, у него появится shared
structure. Потому что остальной словарь не затронут, и его можно
использовать as is, копия не требуется.
DK> Но тут мы вроде бы занимались выяснением вопроса "почему иногда
DK> императив всё-таки нужен".
А выяснили пока что, зачем _в некоторых очень отдельных местах_ нужна
мутабельность. Причем если рассмотреть задачу в целом, внезапно
выяснится, что целиком мутабельный словарь выгоднее только в сферическом
случае в вакууме, когда к нему обращаются (и на изменение, и на чтение)
строго последовательно. Иначе всю выгоду от более быстрого изменения
может сожрать обеспечение консистентности.
>> DK> Бывает, что это упрощает описание алгоритма. Например, если Вы
>> DK> реализуете программу, алгоритм которой описан в императивном стиле в
>> DK> некоторой