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 doc”,“多行注释”等内容,在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。

我没有想到doc-strings作为用例,但这也是一个很好的用例。

这个论点很好,因为这个可能引入的工具体现复杂。对heredoc或类似内容的解析可能会更加困难。

另外,如果你看看Ruby,Perl和Python,你会发现似乎没有人能够达成一致的最佳做法,这三个语言的实现都支持多种方式。

说到不值得为此付出的努力这一方面。实际上,这是工具也可以解决的一个问题。虽然不是为了doc-string用例,但对我来说是一个用例。我知道在IntelliJ中,有一个模式会在另一个缓冲区为你打开一个自由输入的窗口,它会自动将你输入字符串内的内容Java转义。我可能也会考虑为Emacs做类似的东西。
@sean 抓住了关键点。无论解决方案是什么,我个人倾向于使用读标签。所以 #s """ """ 或者类似的东西。这将解决该问题。
只是注意到 Java 15 也引入了这个特性(我知道这是一个编译器特性,所以 clojure 实现与此无关),但也许解决方案空间扩大了一点。

只是注意到“原始字符串”(即不需要太多引号的字符串)与读宏一起,可以实现很多酷炫的功能,而目前这些功能已经足够令人烦恼,以至于没有人会去麻烦。
+1

从现状来看,将 XML 和 HTML 当作文本一直让非 Clojurist 陷入糟糕的麻烦,包括格式错误、注入、笨拙的转换,以及难以评估正确性的代码!

Clojure 部分源自数据(而非字符串)的惯例所带来的良好声誉得益于(我的经验尚不能量化)运行时成本低廉。所以,“Hiccup”和“clojure.xml”规范对 HTML 和 XML 非常有效,可以在不将 blob 插入代码的情况下提供美好的一面。如果你原本就有 blob,你可以尽早用 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。

为此,“文本块”是必需的,如果不是引号问题太让人烦恼。
...