Есть ли идиоматический способ избежать длинных строковых литералов Clojure?

Различные руководства по стилю Clojure рекомендуют избегать строк длиной более 80 символов. Мне интересно, существует ли идиоматический способ избежать длинных литералов String.

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

Вот несколько примеров (я склонен следовать за первым):

;; break the String literal with `str`
(println (str
    "The quick brown fox "
    "jumps over the lazy dog"))

;; break the String literal with `join`
(println (join " " [
    "The quick brown fox"
    "jumps over the lazy dog"]))

Я знаю, что Clojure поддерживает многострочные литералы String, но использование этого подхода имеет нежелательный эффект интерпретации символов новой строки, например. используя repl:

user=> (println "The quick brown fox
  #_=>   jumps over the lazy dog")
The quick brown fox
  jumps over the lazy dog

Ответ 1

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

EDIT:

В соответствии с запросом я продемонстрирую, как вы можете читать длинные строки во время компиляции.

(defmacro compile-time-slurp [file]
  (slurp file))

Используйте его следующим образом:

(def long-string (compile-time-slurp "longString.txt"))

Вы можете придумать похожие макросы для обработки файлов свойств Java, конфигурации XML/JSON, SQL-запросов, HTML или всего, что вам нужно.

Ответ 2

Мне удобно использовать str для создания строк и использовать символьные литералы, такие как \newline или \tab вместо "\n", чтобы их разбить. Я редко нарушаю правило 80 столбцов таким образом.

Ответ 3

Самые идиоматические способы, о которых я знаю, следующие:

1) Используйте (str) для разделения строки на несколько строк.

(str "User " (:user context)
     " is now logged in.")

Это, вероятно, самое идиоматическое использование. Я видел это в нескольких библиотеках и проектах. Это быстро, поскольку (str) использует StringBuilder под капотом. Он также позволяет вам смешивать код прозрачно, как я сделал в этом примере.

2) Разрешить строкам прерывать ограничение 80 char самостоятельно, когда это имеет смысл.

(format
  "User %s is now logged in."
  (:user context))

В принципе, это нормально, чтобы прервать ограничение 80 char для строк. Скорее всего, вам маловероятно, что вы будете следить за чтением строки при работе с кодом, и, в случае необходимости, вам нужно будет прокручивать по горизонтали.

Я завернул строку в (формат) здесь, чтобы иметь возможность вводить код аналогично моему предыдущему примеру. Вам не нужно.


Менее идиоматические способы:

3) Поместите свои строки в файлы и загрузите их оттуда.

(slurp "/path/to/userLoggedIn.txt")

С файлом: /path/to/userLoggedIn.txt содержащий:

User logged in.

Я советую против этого, потому что:

  • Он вводит побочные эффекты IO
  • У этого есть потенциал, чтобы потерпеть неудачу, сказать, что путь неправильный, ресурс отсутствует или поврежден, ошибки диска и т.д.
  • У него есть последствия для производительности, чтение дисков происходит медленно.
  • Сложно вводить контент из кода, если вам тоже нужно.

Я бы сказал, сделайте это, только если ваш текст действительно большой. Или, если содержимое строки должно быть изменено не devs. Или если содержимое получено извне.

4) Имейте пространство имен, в котором вы определяете все свои строки и загружаете их оттуда.

(ns msgs)
(defn logged-in-msg [user]
  (format
"User %s is now logged in."
    user))

Что вы затем используете так:

(msgs/logged-in-msg (:user context))

Я предпочитаю это над # 3. Вам все равно нужно разрешить использовать # 2 здесь, где это нормально, чтобы строки прервали ограничение 80 char. Фактически, здесь вы помещаете строки сами по строке, поэтому их легко форматировать. Если вы используете анализ кода, например checkstyle, вы можете исключить этот файл из правила. Он также не страдает от проблем № 3.


Если вы собираетесь С# 3 или # 4, у вас, вероятно, есть специальный прецедент для ваших строк, например, интернационализация или редактирование бизнеса и т.д. В таких случаях вам может быть лучше, если вы создадите более надежное решение, которые могут быть вдохновлены вышеупомянутыми методами или использовать библиотеку, которая специализируется на этих случаях использования.