符号
+、concat和java.lang.String这样的形式都被称为符号,用来为事物命名。
Clojure 中,符号用来对各式各样的东西命名。
● 函数,例如str和concat。
● 操作符,例如+和-,终究不过是函数罢了。
● Java类,例如java.lang.String和java.util.Random。
● 命名空间和Java包,例如clojure.core和java.lang。
● 数据结构和引用类型。
符号不能以数字开头,但可以包含字母、数字、加号(+)、减号(-)、乘号(*)、除号(/)、感叹号(!)、问好(?)、英文句号(.)和下划线(_)。
Clojure 会采用一些未文档化的其他字符作为其内部符号,另外将来也可能会为符号增加更多的合法字符。
/和.会被Clojure加以特殊对待,用于支持命名空间。
字符串与字符
字符串是一种读取器形式。
Clojure字符串就是Java字符串。它们使用双引号来划定界限,并且可以跨越多行。
"This is a\nmultiline string"
-> "This is a\nmultiline string"
"This is also
a multiline string"
-> "This is also\na multiline string"
REPL 回显字符串的字面量时,总是包括了换行转义符。如果确实“打印”了一个多行字符串,那它就会以多行的方式输出。
(println "another\nmultiline\nstring")
| another
| multiline
| string
-> nil
Clojure并未封装大多数的Java字符串功能。作为替代,你可以使用Clojure的Java互操作形式来直接调用它们。
(.toUpperCase "hello")
-> "HELLO"
toUpperCase前面的句点告知Clojure,应该将其视为一个Java方法,而非Clojure函数。
被Clojure封装了的字符串功能之一是toString。无需直接调用toString,而是应该使用Clojure的str函数。
(str& args)
str函数与toString有两点不同。一是它能接受多个参数,二是它会跳过nil而不引发错误。
(str 1 2 nil 3)
-> "123"
Clojure字符同样也是Java字符。其字面语法是\{letter},letter可以是一个字母,或者下列这些字符的名称:backspace、formfeed、newline、return、space和tab。
(str \h \e \y \space \y \o \u)
-> "hey you"
和字符串一样,Clojure 并未封装 Java 的字符处理功能。同样可以使用Java互操作,比如Character/toUpperCase。
(Character/toUpperCase \s)
-> \S
字符串是由字符组成的序列。当对字符串调用Clojure的序列处理函数时,会得到由这些函数返回的一个字符序列。
interleave函数来。
(interleave "Attack at midnight" "The purple elephant chortled")
-> (\A \T \t \h \t \e \a \space \c \p \k \u \space \r
\a \p \t \l \space \e \m \space \i \e \d \l \n \e
\i \p \g \h \h \a \t \n)
不能使用str函数把字符打包进一个字符串。
(str (interleave "Attack at midnight" "The purple elephant chortled"))
-> "clojure.lang.LazySeq@d4ea9f36"
最主要的问题是,str函数接受的是数量可变的参数,但传给它的参数只有一个,一个包含了参数列表的序列。解决方案是apply函数。
(apply f args* argseq)
apply函数接受一个函数f、一些可选的args和一个序列argseq作为参数。然后,会调用f,并将args和argseq解开为一个参数列表传给f。
使用(apply str ...)由字符序列来创建一个字符串。
(apply str (interleave "Attack at midnight" "The purple elephant chortled"))
-> "ATthtea cpku raptl em iedlneipghhatn"
还可以再次使用(apply str ...),显示那条机密消息。
(apply str (take-nth 2 "ATthtea cpku raptl em iedlneipghhatn"))
-> "Attack at midnight"
调用(take-nth 2 ...),会从序列中依次剔除每第2个元素,这样就还原了被混淆的消息。