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

欢迎!请查看关于页面以了解有关其工作方式的更多信息。

+8
语法和阅读器
编辑了

问题

在此处和那里不得不包含一些JavaScript、XML和HTML在我的Clojure代码中时,转义引号可能会很麻烦且容易出错。这同样适用于脚本编写和运行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个投票

这已经在Clojure的生命周期中被请求过,也曾经被拒绝过,并且我认为这里没有新的论点。

哼,我首先尝试搜索它。但没有找到任何东西。我受到关于这个的Java JEPs的激励:[https://openjdk.java.net/jeps/355](https://openjdk.java.net/jeps/355) 和 [https://openjdk.java.net/jeps/326](https://openjdk.java.net/jeps/326)
by
如果您在Clojure和Clojure-dev谷歌邮件组中将“原始字符串”、“字符串字面量”、“heredoc”、“多行注释”等搜索出来,会发现有许多讨论。

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

我想我应该将“拒绝”改为“缺乏兴趣”;我认为Rich一般认为这种事情包含许多细微的复杂性(尤其是对于工具),但收益相对较低。
by
不支持三重引号方法的论据之一是这已经是合法的Clojure代码。

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

(它并不表示你想要的意思,但今天它是有效的,尽管我不认为有任何真正意义上的代码这样做)
by
好吧,我承认我只在谷歌上搜索,而不是特别搜索邮件列表:p。

我之前没想过文档字符串作为一个用例,但这也是一个很好的用例。

这是一个很好的观点,这种方法可能会引入的工具复杂性。解析heredoc或者类似的可能更困难。

此外,如果你看看Ruby、Perl和Python,你会发现似乎没人能确定如何做这件事,它们都支持多种方法。

说到不值得为工具费劲,这实际上是工具可以解决的问题。虽然不是为文档字符串用例,但对我自己的代码片段来说也是如此。我知道在IntelliJ中有一种模式,它为您打开另一个缓冲区,您可以在其中自由键入,它会自动为您输入的字符串中的文本Java转义。也许我也会为Emacs做类似的事情。
@sean 捕获得好。无论是什么解决方案,我个人倾向于使用阅读器标签。所以 #s """ """ 或类似的东西。这将解决这个问题的。
只是想指出,Java 15 也引入了这一功能(我知道这是一个仅编译器的特性,因此 Clojure 的实现与之无关),但也许解决方案空间又增加了一点点。

只是想指出,“原始字符串”,即需要较少引号注释的字符串,连同阅读器宏一起,实现了很多很酷的特性,这些特性目前足以让人厌烦,以至于没人愿意去处理。
+1个投票

从现状的良好方面来看,将 XML 和 HTML 视为文本,已经成为非 Clojure 开发者陷入可怕困境的常见做法,包括产生格式不正确的输出、注入、笨拙的转换和难以评估正确性的代码!

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嵌入其中。

如果不仅仅是引用问题,文本块是可以满足这种需求的一项要求。
...