2024 年 Clojure 状态调查 中分享您的想法!

欢迎!请参阅 关于 页以了解更多关于此处如何工作的信息。

+8
语法和读取器
编辑了

问题

尽管在我的一些 Clojure 代码中零零星星地包含了一些 JavaScript、XML 和 HTML,但不得不转义引号仍然很麻烦,容易出错。这在脚本和运行 shell 命令时也同样适用,你可能会遇到复杂的转义场景。

解决方案

添加一个字符串字面量,可以适应包含任何类型的字符串,而无需转义。

建议

文本块

某些其他语言提供一种称为文本块的功能,您可以在此处使用三个或更多的引号来编写字符串,其中允许所有字符

(println """
         This " is allowed,
         and no need to escape it.
         """

文本块通常还带有其他一些功能,第一个和最后一个换行符不属于字符串的一部分。并且源代码中三引号的位置区分引号中行的开始。因此,上述代码打印出

This " is allowed,
and no need to escape it.

而不是

         This " is allowed,
         and no need to escape it.

虽然文本块在视觉上很整洁,因为它们在源代码中有很好的对齐。但是,它们是空白相关的,而 Clojure 一直是一个空白无关的语言,这意味着空白不重要。我认为最好是保持这种方式。因此,接下来的两个建议。

原始字符串

有时没有“块”功能的文本块被称为原始字符串字面量

(println """This " is allowed,
and no need to escape it.
Also support multi-line, but
not the "block" style of text blocks.""")

因此

(println """
         This " is allowed,
         and no need to escape it.
         """

打印出

         This " is allowed,
         and no need to escape it.

不像文本块。

如果您需要三引号,只需把分隔符换成四引号

""""This """ is now allowed as well.""""

原始字符串的问题在于,如果您使用双引号作为您的分隔符

""This is a raw " string!""

但想将单引号放在开头或结尾

"""{{hello}}"""

我想的字符串是:"{{hello}}",不是 {{hello}},但原始字符串无法区分这两者,因为现在它认为这是三引号分隔符。

一个解决方案是允许仅在开头或结尾使用转义引号

""\"{{hello}}\"""

但不能在中间使用

""\"{{he\llo}}\"""

这是这个字符串:"{{he\llo}}"

所以转义字符 \\ 出现在除开头外任何地方,如果后面跟着引号;在结尾处,如果后面跟着引号。

但我仍然觉得这并不理想。规则太多,仍然有需要转义的情况。

未转义的字符串(我最喜欢的)

这里的想法是允许任何字符串作为分隔符。因此,对于我们要嵌套在Clojure代码中的任何可能字符串,我们都可以找到一个不包含它的字符串用作分隔符。

假设添加了读取宏 #text。它期望以下形式是普通字符串,以此告诉它后续读取形式的分隔符。

(println #text "|" |"{{hello}}"|)

会打印

"{{hello}}"

《#text》的第一个参数告诉它以下原始字符串的分隔符应该是哪个。这样,你绝对不需要在原始字符串内使用转义序列。对于任何给定的字符串,你都可以找到一个不包含它的分隔字符串以正确处理。

关于这种方法,我想的一个疯狂的点是,如果你使用一个足够随机的字符串作为分隔符,这可能是一种奇怪的方式来防止注入。

(println #text "xIBgdSl4TCCOIdqdMu9G" xIBgdSl4TCCOIdqdMu9G
Can't nobody guess the delimiter to escape the string context :p
xIBgdSl4TCCOIdqdMu9G)

谢谢

3 答案

+1
by

这已经在Clojure的生命周期中被请求和拒绝多次,我认为这里没有新的论点。

by
嗯,我首先尝试搜索了一番。没有找到任何东西。我受到即将推出的Java JEPs的启发:https://openjdk.java.net/jeps/355https://openjdk.java.net/jeps/326
如果您搜索“原始字符串”、“字符串字面量”、“here document”、“多行注释”等,可以在Clojure和Clojure-dev谷歌邮件列表中找到许多讨论。

旧设计页面: https://archive.clojure.org/design-wiki/display/design/Alternate%2Bstring%2Bquote%2Bsyntaxes.html

我觉得我应该将“拒绝”改为“缺乏兴趣”;我认为Rich一般认为这类事情(特别是对于工具)有很大的微妙复杂性,而好处相对较小。
不使用三重引号方法的论据是,这已经是合法的Clojure代码。

user=> (println """
这已经是有效的Clojure
""")
 
这已经是有效的Clojure
 
nil
user=>

(它并不代表你想要的意思,但今天是有效的,尽管我怀疑任何真正的代码都不会这样做)
好吧,我承认我仅仅搜索了谷歌,而不是具体搜索邮件列表 :p。

我没有想过文档字符串是一个用例,但这也是一个好的用例。

有关这可能引入的工具复杂性的好点子。解析here document或类似的内容可能会更困难。

还有,如果你看看Ruby、Perl和Python,你会发现似乎没有人能就如何正确地做到这一点达成一致,三者最终都支持多种方式。

说到不值得一试的工具。这实际上也是工具可以解决的问题。虽然不是为了文档字符串用例,但对我来说是用的到的。我知道在IntelliJ中有一个模式,它会为你打开一个另一个缓冲区,你可以自由输入,它会自动在字符串中对你输入的内容进行Java转义。也许我也会为Emacs开发类似的功能。
@sean 很不错的发现。无论是什么解决方案,我建议个人倾向于使用阅读器标记。比如 #s """ """ 或类似的东西。这将解决此问题。
仅指出,Java 15 也引入了这一特性(我知道这是一个仅编译器功能,因此 Clojure 实现与之无关),但也许解决方案空间增加了一点点。

仅指出,“原始字符串”,即无需过多引号的字符串,加上阅读器宏,允许执行许多目前足够麻烦以至于没人愿意做的事情。
+1

从现状的积极方面看,-- 将 XML 和 HTML 视为文本一直让非 Clojurists 遭遇糟糕的麻烦,包括格式不正确的输出、注入、折衷的转换,以及很难评估正确性的代码!

Clojure 赢得了良好的可靠性声誉,部分得益于基于数据(而非字符串)的约定。“Hiccup”和“clojure.xml”约定已被证明在处理 HTML 和 XML 时非常有效,并且在(我个人未量化的经验中)运行时非常节省,这使得避免在代码中放置数据块成为一种美妙的好处。如果您确实有数据块要开始,您可以尽早使用 Enlive 等工具解析它们,并完成数据结构处理。

嗯,JavaScript 可能有点牵强。最好是直接从资源中获取?如果在 ClojureScript 中编码,您可以使用宏在编译时从与 cljs 文件相同的类路径中获取资源。

总的来说,我认为 Clojure 不使用嵌入和调整 HTML 和 XML 文字嵌入代码的便利性是一个明智的选择(我们很幸运)。起初这可能看起来像是一个缺失的功能,但其缺失反而使 Clojure 代码的可靠性受益匪浅。

观点很棒。对于HTML和XML,我也同意。我的动力来自服务器端渲染,需要在Hiccup中嵌入JavaScript。

我确实想过CLJS是否可以以这种方式嵌入,但我不认为它可以。尽管如此,如果它可以,那将会非常棒。
+1

重新展示

你好,

我也希望支持将此功能添加到clojure中。我认为一个很好的用例是支持类似styled components这样的功能 https://styled-components.npmjs.net.cn/

const Button = styled.a`
  /* This renders the buttons above... Edit me! */
  display: inline-block;
  border-radius: 3px;
  padding: 0.5rem 0;
  margin: 0.5rem 1rem;
  width: 11rem;
  background: transparent;
  color: white;
  border: 2px solid white;

  /* The GitHub button is a primary button
   * edit this to target it specifically! */
  ${props => props.primary && css`
    background: white;
    color: palevioletred;
  `}
`

上述代码的主要优点是,大多数情况下这只是纯CSS - 无需转换为Clojure。

在Clojure中添加原始字符串/块文本有问题吗?是的。
让我们就此展开讨论,看看我们能走多远。

是否有类似现在Java JEPs开发方式的方法来实验Clojure特性 - 有预览版以供发现和改进,直到它最终确定并添加到核心? https://openjdk.java.net/jeps/326 .

我对Clojure相当陌生,对语言及其所有历史和传统不太熟悉。我喜欢挑战传统,因为世界正在变化。使我们的做事方式有道理的原因可能现在不再成立。

Clojure没有类似Java JEPs的流程。如果Rich Hickey对某个功能不感兴趣,他就不会将其作为Clojure官方版本的一部分。

世界上任何人都可以根据自己的需求对Clojure源代码进行本地修改并使用。  我听说有些组织运行定制版的Clojure供内部使用。

这样的功能对于您自己本地版本的Clojure来说很简单。  但这并不帮助在分布式Clojure程序中使用这样的功能,因为使用官方版本Clojure的人将无法使用新功能编译和运行源代码。
  by
我也希望Clojure中也有文本块。
我的用例是将其他编程语言(如Python)嵌入其中。

“文本块”对此类功能是有要求的,如果不是引号问题真是太烦人了。
...