Когда следует использовать макрос стрелки clojure? - программирование
Подтвердить что ты не робот

Когда следует использовать макрос стрелки clojure?

В попытке остаться с функциональным стилем я с трудом понимаю, когда я должен предпочесть:

(-> [1 2 3] reverse last)

над

(last (reverse [1 2 3]))

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

Что я должен использовать в какое время?

4b9b3361

Ответ 1

В основном я избегаю использования -> для функций с одним аргументом; это намного более полезно, когда у вас есть функции с несколькими аргументами, потому что это позволяет вам сохранять каждую функцию рядом с ее "дополнительными аргументами", без объекта фокусировки, скрывающего ее.

Но также вам не нужно выбирать одну или другую крайность: одна из моих любимых вещей о -> заключается в том, что она позволяет вам писать функции в любом порядке вообще, и вы можете использовать эту свободу для напишите код так, как вы считаете наиболее читаемым. Например, возможно, вы хотите подчеркнуть, что вы берете последнюю из коллекции, а в контексте тот факт, что она полностью изменилась, неинтересна:

(last (-> [1 2 3] (reverse)))

Или, может быть, важно обратить вспять, и последнее скучно:

(-> (reverse [1 2 3]) (last))

Отметьте, что я написал (last) и (reverse) здесь, а не только last и reverse, даже если макрос -> неявно вставляет скобки для вас, если вы их не оставляете. Это было специально: хотя это не очень популярный стиль, я считаю, что рекомендуется всегда использовать круглые скобки в формах, указанных в ->. Для этого есть несколько причин:

  • Это означает, что вы не удивлены, когда (-> (blah) (fn [x] (+ 1 (* x 5)))) странно расширяется, потому что вы привыкли думать, что -> принимает форму, а не функцию.
  • Он поддерживает связь между "вот открытая скобка" и "функция вызывается". Приятно иметь возможность grep для вызовов определенной функции, а также приятный визуальный намек. Если вы опускаете круглые скобки, функции вызываются без визуального указания.
  • Он выглядит более регулярным в многострочном -> с некоторыми унарными функциями и другими функциями с несколькими аргументами. Например:

    (-> attrs
        (update :sessions inc)
        frobnicate
        save-to-disk
        (get :uuid))
    

    Разве не так важно иметь эти две вещи в среднем смещении, выглядящие иначе, чем все остальное?

Единственный аргумент, который я когда-либо видел для исключения (), состоит в том, что он сохраняет два символа ввода, что не является аргументом вообще.

Ответ 2

Мое короткое эмпирическое правило ", которое ближе к более декларативному английскому предложению". Если вы грубо переводите их в описательные предложения, я склоняюсь к выбору того, что более подробно говорит о вещи созданный над опцией, описывающей процесс создания результата. Некоторые люди захотят выбрать другой путь. Все это всегда дело вкуса.

например:

  • (last (reverse [1 2 3])) почти "последний от обратного 1 2 3"
  • (-> [1 2 3] reverse last) сортируется как "от 1 2 3, наоборот, занимает последнее"

Я нахожу первый более декларативный и выбираю его в этом случае, другие будут выбирать по-другому.

Ответ 3

Поскольку они функционально идентичны, главное, чтобы рассмотреть , что делает код более читабельным и поддерживаемым?

В основном это вызов для решения.

-> часто полезен в ситуациях, когда:

  • Вы хотите четко указать, что последовательность операций должна выполняться последовательно.
  • Возможно, вы захотите вставить новые шаги в будущем. Легко - просто добавьте новую строку/форму.
  • В ваших шагах есть дополнительные аргументы (это делает очень заметным, что эти аргументы являются частью шага)
  • Глубоко вложенные вызовы функций в противном случае были бы путаными (хотя, если это действительно проблема, есть и другие способы рефакторинга....)
Стиль

(f (g x)) полезен при других обстоятельствах:

  • Это часто более естественный стиль для математических операций/вычислений, поскольку он более точно отражает нотацию математической функции
  • Он более гибкий, поскольку он не имеет требования, чтобы переданное значение всегда было первым (с ->) или последним (с ->>) аргументом
  • У него нет умственных накладных расходов, чтобы представить дополнительный аргумент

Ответ 4

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

Ответ 5

Ничего плохого в других ответах, но я просто добавлю, что когда -> действительно имеет смысл для меня, это когда вы хотите подчеркнуть, что существует последовательность операций. Чтение слева направо означает, что вы, естественно, видите порядок, в котором функции оцениваются, что действительно помогает, когда вы получаете более 2 или 3 уровней гнездования. В длинной форме вам иногда приходится мысленно разбирать круглые скобки, переходить на самый низкий уровень, а затем прокладывать себе путь, чтобы понять, что происходит.