Когда следует использовать макрос стрелки clojure?
В попытке остаться с функциональным стилем я с трудом понимаю, когда я должен предпочесть:
(-> [1 2 3] reverse last)
над
(last (reverse [1 2 3]))
Когда я сталкиваюсь с обоими стилями в проекте, я нахожу, что он прерывает мой поток, поскольку мне приходится переключаться между мышлением о композициях функций и думать о промежуточных состояниях.
Что я должен использовать в какое время?
Ответы
Ответ 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 уровней гнездования. В длинной форме вам иногда приходится мысленно разбирать круглые скобки, переходить на самый низкий уровень, а затем прокладывать себе путь, чтобы понять, что происходит.