问题 是否有一种惯用的方法来避免长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

11663
2018-01-13 18:36


起源

@Chiron:“有没有一种惯用的方法来避免长字符串文字?”这不是一个真正的问题吗?真?我的小学教育是骗人的吗? - Chuck


答案:


您应该将该字符串存储在外部文本文件中,并从您的代码中读取该文件。如果您仍然觉得需要在代码中存储字符串,请继续使用 str

编辑:

根据要求,我将演示如何在编译时读取长字符串。

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

像这样用它:

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

您可以创建类似的宏来处理Java属性文件,XML / JSON配置,SQL查询,HTML或您需要的任何其他内容。


5
2018-01-13 22:18



您可能不应该在大多数时间将字符串放在文本文件中,除非我们说的是非常大的文本。它增加了运营成本,性能成本和代码复杂性。正确的答案是使用(str)。 - Didier A.
这是Clojure。 (slurp "myBigString.txt") 不会增加代码的复杂性(并且不如字符串中的新行复杂)。如果文件IO的性能是一个问题,那么该命令可以在编译时通过宏运行。 - WolfeFan
它引入了您现在需要考虑的不必要的可能故障,这是更高的代码复杂性。您是否真的建议人们在单个文本文件中放置超过80个字符的字符串?副作用自由功能的整个想法怎么了?只在文件中放入文本 真 大,或外部提供,或动态生成,需要持久。 - Didier A.
作为第二个注释,您不需要Clojure中的字符串换行符,字符串文字可以跨越多行,并将换行符保留为字符串的一部分。 - Didier A.
字符串需要由开发人员轻松编辑。对于多行字符串,我自己的经验是,在文本文件中编辑它们比在源代码中的文字更容易。获取代码以读取文件的额外复杂性对于将文本编辑为单独文件的便利性而言是值得的。 - WolfeFan


我觉得使用起来很方便 str 创建字符串并使用字符文字,如 \newline 要么 \tab 而不是“\ n”打破他们。 我很少以这种方式违反80栏规则。


3
2018-01-14 12:06





我所知道的最常用的方法如下:

1) 使用(str)将字符串拆分为多行。

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

这可能是最惯用的用法。我已经在多个库和项目中看到过这种情况。它很快,因为(str)在引擎盖下使用了StringBuilder。它还允许您透明地混合代码,就像我在示例中所做的那样。

2) 当有意义时,允许字符串自己打破80个字符限制。

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

基本上,可以打破字符串的80字符限制。有可能你在使用代码时不太可能关心读取字符串,而且在你需要的时候,你需要特别需要水平滚动。

我在这里用(格式)包装了字符串,以便能够像我之前的例子一样注入代码。你不需要。


较少惯用的方式是:

3) 将您的字符串放在文件中并从那里加载它们。

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

用文件: /path/to/userLoggedIn.txt 含:

User logged in.

我建议不要这样做,因为:

  • 它引入了IO副作用
  • 它有可能失败,说路径错误,资源丢失或损坏,磁盘错误等。
  • 它具有性能影响,磁盘读取速度很慢。
  • 如果你需要,很难从代码中注入内容。

我会说,只有你的文字是这样做的  大。或者如果非开发人员需要更改字符串的内容。或者如果内容是从外部获得的。

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,您可能会为您的字符串设置特殊用例,例如国际化,或者有业务编辑等等。在这些情况下,您可能会更好地构建更强大的解决方案,从上述方法中获得灵感,或使用专门用于这些用例的库。


3
2018-05-04 22:47