Pull to refresh

Comments 22

Известно же, что
Объекты — замыкания для бедных

и
Замыкания — объекты для бедных
Я ставил цель показать почему кеш на самом деле один на всю программу. Если вы напишите то же самое на C# он будет новый каждый раз, если вы конечно не примените похожую схему, засунув его в замыкание и позаботившись чтобы оно использовалось каждый раз.

Я не думаю что это очевидно с первого взгляда, особенно когда смотришь на весь этот синтаксис F# :)
Так по идее и не должно быть очевидно. Один из поинтов функциональных языков как раз в том, что нас интересует ЧТО, но совершенно не интересует КАК.
Если вы напишите код на SQL так, что вас не будет интересовать КАК он выполяется — вы далеко не уедете. Я согласен, что не должно быть очевидно. И я согласен, что надо писать ЧТО нас интересует, а не как. Но при этом надо обязательно знать КАК это работает внутри. Иначе можно получить «странные и непонятные» баги, проблемы с производительностью, продолжить по вкусу.
Я против копания в кишках ничего и не говорил. Это очень полезно. Просто C#, по-моему, тоже далеко не самый прямой язык (в смысле, не содержащий наслоений всяческих абстракций), чтобы на его примере объяснять принципы работы.
Можно, конечно, объяснять на MS IL. Но не думаю что от этого будет проще :) В данном случае не используются какие-либо синтаксические подсластители C#. Думаю, он вполне выполняет свою задачу.
«Мемоизация» пишется без «р».
см. теги.
Пишется и так и так. По английски memoization, без да.
Поясню еще раз свою позицию, так как оригинальный термин memoization был придуман специально для данного случая. Я использую более общий термин означающий в данном случае «сохранение вычисленных значений», а не «avoid repeating the calculation of results for previously-processed inputs». И как мне кажется, термин с «р» в данном случае подходит больше, чтобы не плодить buzzwords, поскольку смысл все равно настолько близкий, насколько это возможно.
> Количество результатов явно не в пользу бездумной кальки :)

А качество? Серьёзно, предоставленная вами поисковая выдача практически однозначно свидетельствует в пользу «мемоизации».
Ладно, сдаюсь. Мне так больше нравится :)

На самом деле я не знаю зачем корежить язык в данном случае. Довольно давно есть термин «меморизация», который означал сохранение промежуточных результатов вычислений с целью потом их использовать. Например динамическое программирование очень часто это использовало.

Потом появляется спаситель на белом коне и придумывает термин «memoization». И понеслось. Причем это же не слово какое-то. Человек сознательно выкидывает одну букву чтобы было «не как у всех». А потом у нас появляются идиотсткие термины. Типа «тред» или «нить». Хотя «поток» так и просится как перевод к слову thread.

Собственно это вопрос предпочтений. Менять в статье наверное не буду, либо если кому-то еще не все равно то поменяю на латиницу. А «мемоизацию» глаз как-то не терпит.
> Хотя «поток» так и просится как перевод к слову thread.

«Поток» много к чему просится, и к «stream», и к «flow». Только кальками и спасаемся.
Да, а потом говорят что в речи програмистов ничего не поймешь. )
Хорошо что у нас не немецкий профессиональный язык, а то бы ведь намного хуже было.

P.S.: Щас подумал, прикинул… в работе я все-таки больше пользуюсь англоязычными терминами, видимо именно по этой причине.
Вы смотрели тексты по ссылке? Меморизация — запоминание чего-то, увековечивание, мемоизация — оптимизация путём запоминания результатов. Разница — как между причиной и следствием.
Интересно, а можно ли оптимизировать этот код, воспользовавщись «хвостовой рекурсией» для функции вычисления факториала? Что-то вроде передавать текущий «х» в memoizedFactorial, которая просто до-умножит на «х» результат.

По идее в таком случае в IL-коде Invoke должен появится префикс «FE 14» (Tailcall). По идее в F# есть такой тип оптимизации.
Хвостовая рекурсия в данном случае не даст эффекта memoization. Потому что при memoization будут сохранены уже вычесленные результаты для функции factorial с конкретным аргументом. В данном случае для всех от 0 до 10100. Поэтому в данном случае рекурсия нам нужна как воздух чтобы применить memoization. Без рекурсии у вас будет оптимизированный цикл, который, понятно дело, не будет вызывать себя же с другими параметрами. И мемоизация сработает только на самом верхнем уровне. Для аргументов от 10000 до 10100. И когда вы будете вычислять факториал для 9999, оно начнет считаться с самого начала.

А так оптимизация хвостовой рекурсии очень нужная вещь, да :)
Ясно. Техника «мемоизации» фактически является способом превращения рекурсивного алгоритма в алгоритм динамического программирования полу-прозрачным методом :)

Кстати, а может тогда воспользоватся «слабыми ссылками» для memorized-значений функции?

В динамическом программировании один из этапов оптимизации — выбрасывание значений, которые в дальнейшем могут не понадобится.

(я не нудный, просто всегда пытають ответить на вопрос «can you do better?» © google interviewers) :)
Конечно можно воспользоваться слабыми ссылками. И я даже думаю нужно, если кеш достаточно большой. Только в данном случае «в лоб» воспользоваться не получиться, потому что Dictionary будет хранить слабую ссылку на объект, а больше ссылок не будет. Потому при первой же сборке мусора они все «улетучаться».

Вообще в нете тема слабых ссылок очень тонкая и деликатная. Я бы сказал даже интимная. Нужно 100 раз подумать и просчитать ситуации, прежде чем их использовать. Особенно в кешах где время жизни объекта просчитать трудно.

Для уменьшения кеша я бы в данном случае наверное просто бы завел счетчики времени последнего доступа

P.S.: Ну это не пост про новый айфон, тут каждый комментарий на вес золота :)
Sign up to leave a comment.

Articles