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/355](https://openjdk.java.net/jeps/355) 和 [https://openjdk.java.net/jeps/326](https://openjdk.java.net/jeps/326)
如果您在 Clojure 和 Clojure-dev Google 群组邮件列表上搜索“原始字符串”、“字符串字面量”、“这里文档”、“多行注释”等,会发现有很多讨论。

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

我认为我应该将“衰落”更改为“缺乏兴趣”;我认为Rich普遍认为这类事情有很多微妙复杂之处(尤其是对于工具),而收益相对较低。
不采用三引号方法的论据是,这已经在 Clojure 中是合法的

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

(它并不意味着你想的意思,但它现在仍然有效,尽管我怀疑没有真正的代码这样做)
好吧,我承认只查了Google,而没有特别查邮件列表 :p。

我没想到doc字符串也是一个用例,但这也是一个不错的用例。

关于这可能会引入的实用程序复杂性的观点也很正确。解析here doc或类似的内容可能会更困难。

再看 Ruby、Perl 和 Python,您会发现似乎没有人能够就如何正确做这件事达成一致,三者的确都支持多种方式。

说到对于工具来说不值得努力的事情。这实际上也是工具可以解决的问题。不是针对doc-string用例,而是针对我的片段用例。我知道在IntelliJ中,有一个模式会为你打开另一个缓冲区,你可以自由地输入,并且它会自动将你的字符串内的输入进行Java转义。也许我也会为Emacs做类似的工作。
@sean 很棒的一个捕捉。无论解决方案是什么,我个人倾向于使用读数标签。所以 #s """ """ 或类似的。这将解决这个问题。
简单提醒一下,Java 15 也引入了这个功能(我知道这是一个仅编译器功能,所以与 Clojure 的实现无关),但也许解决方案空间增长了一点点。

简单提醒一下,“原始字符串”,即无需过多引号的字符串,加上读数宏,可以实现很多目前令人烦恼的酷炫功能。
+1

着眼于现状的积极方面,将 XML 和 HTML 作为文本处理,__()

Clojure 部分应该归功于其数据(而非字符串)建立的习惯,从而形成了一些良好的斗志。 "Hiccup" 和 "clojure.xml"

Er,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 JEP类似的流程。如果Rich Hickey对某个特性不感兴趣,那么他就不会将其作为Clojure官方版本的一部分。

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

在这样的本地区域副本中添加一个这样的特性将会相当简单。但是,这对于在分布式Clojure程序中使用该特性并没有帮助,因为没有使用官方Clojure版本的人将无法编译并运行使用新特性的源代码。
我也希望Clojure有文本块。
我的用途可能是在Clojure中嵌入其他编程语言,如Python。

“文本块”是这种需要的必需品,如果不是引号问题太烦人。
...