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

这已经被请求并拒绝了好几次,我相信这里没有新的论据。

嗯,我确实尝试搜索了一下。找不到任何东西。我是从有关Java JEPS的这些内容中受到启发的: https://openjdk.java.net/jeps/355https://openjdk.java.net/jeps/326








""")
 

 











@sean 抓得很好。无论是什么解决方案,我个人倾向于使用reader标签。所以 #s """ """ 或者这样的。这将解决此问题。
只是提醒一下,Java 15 也引入了这一特性(我知道这是一个只涉及编译器的特性,所以 Clojure 实现与这一特性无关),但这可能也使解决方案空间扩大了一点。

提醒一下,“原始字符串”,即需要较少引号转义的字符串,结合reader宏可以实现很多令人兴奋的功能,但目前令人烦恼的程度足以让任何人都不在意。
+1

看看现状的积极面,-- 将XML和HTML作为文本处理始终会使非Clojure开发者陷入糟糕的麻烦,包括输出格式错误、注入、拙劣的转换以及很难评估其正确性的代码!

Clojure的部分良好声誉归功于其在数据(而不是字符串)上建立的传统。"Hiccup"和"clojure.xml"的传统在处理HTML和XML方面已被证明非常有效,而且(据我的经验)在运行时 surprisingly便宜,从而证明了避免在代码中嵌入blob的巨大优点。如果你 真有 blob,你可以尽早使用Enlive等进行解析,并将处理作为数据结构完成。

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

总的来说,我认为Clojure明智(并且我们很幸运)不依赖于嵌入和调整代码中的HTML和XML字面量。一开始可能看起来像是缺失的功能,但它的缺失对Clojure代码的可靠性是个福音。

by
非常好的观点。至于HTML和XML,我也同意。我的动力来自于进行服务器端渲染,并在Hiccup中嵌入JavaScript。

我实际也想过CLJS是否可以以这种方式嵌入,但我不认为它可以。尽管如此,如果可以的话,那就很好了。
+1
by
重新展示 by

你好,

我也想支持将此功能添加到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 JEP一样实验Clojure功能 - 拥有预览版本,以便发现和改进,直到它最终确定并添加到核心中? https://openjdk.java.net/jeps/326

我相当新于Clojure,并且对语言及其历史传统并不熟悉。我确实喜欢挑战传统,因为世界正在变化。我们过去行事的原因可能现在不再成立。

by
Clojure没有类似于Java JEP的流程。如果Rich Hickey对某个功能不感兴趣,那么他就不会将其纳入Clojure的官方发行版。

世界上任何人都可以为Clojure源代码创建自己的本地更改并使用它,如果他们这样的话。我听说有一些组织运行用于他们自己使用的Clojure修补版。

在 Clojure 的本地副本中添加这样的功能相对简单。但这并不能解决在分布式 Clojure 程序中使用此功能的问题,因为没有人能够使用 Clojure 的官方版本来编译和运行使用新功能的源代码。
by
我也希望 Clojure 中有文本块。
我的用例是嵌入其他编程语言,比如 Python。

“文本块”是这一点上的一个要求,如果不这样,引用问题会非常烦人。
...