openlang

Сначала динамический let, потом advice-add

Advice это самое приятное в расширении работающего редактора и одновременно то, чему я меньше всего доверяю в чужих init-файлах. (В своих тоже.)

advice-add с :around оборачивает функцию, не трогая её определение, а advice-remove снимает обёртку обратно. Всё это можно сделать из *scratch*, не закрывая редактор, и в этом вся прелесть. Подвох в том, что advice действует на всех вызывающих, включая пакеты, которые об этом не просили. describe-function показывает активные advice в буфере справки, так что C-h f на странно ведущей себя функции стоит попробовать первым.

Второй инструмент, о котором забывают, это динамическая область видимости. Переменная, определённая через defvar, специальная, поэтому let вокруг вызова перепривязывает её для всего, до чего этот вызов дотягивается, на любую глубину, а при выходе из let возвращается старое значение. С включённым lexical-binding обычные локальные переменные становятся лексическими, но специальные остаются динамическими. Привязать case-fold-search вокруг одного нужного вызова часто чище, чем что-то оборачивать в advice.

Мой примерный порядок. Хук, если пакет его даёт, динамический let, если поведением управляет переменная, и advice в последнюю очередь.

Разговор продолжается 1

Следуя доводам
  1. Ссылка на ответ

    Какие потоки видят изменение? Именно этим ваш let отличается от advice. В Clojure binding для var с ^:dynamic действует в пределах потока и откатывается при выходе из формы. alter-var-root меняет корень для всех потоков, и advice по сути это и есть. with-redefs выглядит ограниченным, но временно подменяет корень, так что другие потоки видят подмену, пока она действует.

    Запустите параллельно два теста, которые делают with-redefs для одной и той же функции. Какое определение получит каждый? Ваш let вокруг case-fold-search это случай binding. Advice это случай корня, и рассуждать о нём надо как о глобальном изменении.

Другие стороны того же вопроса

  1. Рефакторинг в объявление using переносит Dispose за Publish()

    Синтаксис короче, время жизни длиннее. Объявление using в C# освобождает ресурс в конце охватывающей области, и эту область л…