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 赞:

这已经被请求,并且被拒绝过几次,在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)
在搜索“原始字符串”、“字符串字面量”、“here文档”、“多行注释”等内容时,Clojure和Clojure-dev谷歌邮件列表上有很多关于它们的讨论。

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

我认为应该将“拒绝”改为“缺乏兴趣”;我认为Rich generally认为这种事情有很多细微的复杂性(尤其是对于工具),但带来的好处相对较低。
反对使用三引号方法的一个论点是,这已经在Clojure中是合法的。

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

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

我没有想到doc字符串也用得着,但这也是一个很好的用例。

关于可能导致工具复杂性这点,这是一个很好的观点。解析here文档或类似的更困难。

同时看看Ruby、Perl和Python,似乎没有一个人能够确定如何处理这个问题,他们三者最终都支持多种方法。

说到工具规定的复杂性。这实际上是工具也可以解决的问题。虽然不是为了doc-string场景,但对我来说是一个片段。我知道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 JEP的开发方式实验Clojure的特性 - 有预览版进行探索和改进,直到最终确定并添加到核心中? https://openjdk.java.net/jeps/326

我对Clojure相当新,并且不太熟悉这个语言及其所有历史和传统。我喜欢挑战传统,因为世界正在变化。曾经使我们的做事方式有意义的理由现在可能不再成立。

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

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

在Clojure本地副本中添加此类功能将非常简单直观。但这并不能帮助在分布式Clojure程序中使用此类功能,因为没有人能够在Clojure官方版本中使用新特性来编译和运行源代码。
by
我还希望Clojure中有文本块。
我的用例是将其他编程语言,如Python嵌入。

"文本块"是这一需求之一,如果不是引用问题太烦人。
...