The Racket Guide阅读笔记,chapter 3.
3 Built-In Datatypes
3.1 Booleans
略
3.2 Numbers
略
3.3 Characters
Racket字符可以对应到一个Unicode标量。这个标量是一个21位整型。通过char->integer
以及integer->char
可以在整型和字符之间互相转化。
字符常量默认的打印暑促以#\
为前缀。如果使用display
来打印,就不会加上那个前缀。
3.4 Strings (Unicode)
字符串是具有一定长度的字符序列。字符串可以是可变化的或者不可变的。常量形式的字符串是不可变的。通过make-string
生成的字符串可以通过string-set!
修改。
字符串提供一些支持本地化的操作,例如:
string-locale<?
string-locale-ci<?
3.5 Bytes and Byte Strings
字节是一个值从0到255的整型。判定诀byte?
可以用来将整型识别为字节。
字节串和字符串类似,不过其单位是字节而不是字符。字节串的写法如#"Apple"
。
display字节串的时候不会做转码,具体显示成什么样子取决于终端的编码。
一些字节串和字符串之间的转换示例:
(bytes->string/utf-8 #"\316\273")
(bytes->string/latin-1 #"\316\273")
3.6 Symbols
符号名是编译器识别的字符串,形如'a
。除了 ( ) [ ] { } " , ' `` ; # | \
之外的字符可以直接以常量的形式写做符号名,否则要通过 string->symbol
来转化。
Actually, # is disallowed only at the beginning of a symbol, and then only if not followed by %; otherwise, # is allowed, too. Also, . by itself is not a symbol. Whitespace or special characters can be included in an identifier by quoting them with | or .
write函数打印符号名的时候不会带'
,display也一样。
gensym
生成随机不重复的符号名。string->uninterned-symbol
可以生成跟以外任何符号名都不重复的符号名,即便内容相同,也就是说(eq?, eqv?, equal?都返回#t)
3.7 Keywords
关键字跟符号名点像,但是打印出来是以#:
为前缀。更准确的说,关键字有点像标识符,可以升格(quote)成符号名。string->keyword
可以将字符串转为关键字。非升格(unquote)的关键字就像非升格的标识符,它们不是表达式,无法产生符号名。
下面两个例子都不是表达式:
not-a-symbol-expression
#:not-a-keyword-expression
关键字常用于函数调用参数列表以及一些其他语法形式内。
3.8 Pairs and Lists
list* is used to abbreviate a series of conses that cannot be abbreviated using list
例子:
> (cons 1 (cons 2 (srcloc "file.rkt" 1 0 1 8)))
(list* 1 2 (srcloc "file.rkt" 1 0 1 8))
write或者display打印对子或者连对的时候,不会添加额外的'
,list
,list*
之类的辅助修饰符。
Racket中的对子是非可变数据类型(跟传统的lisp不一样)。pair?
和list?
只能用于非可变对子。mcons
构成的对子是可变的,可以使用set-mcar!
以及set-mcdr!
来修改。可变list上使用mcar
和mcdr
来获取对子头和对子尾。可变连对打印的时候会用mcons
修饰,通过write
和display
打印的时候会用{ }
表示。
3.9 Vectors
串列(vector)是一个定长数组,其元素可以是任意类型数据。其常量表示方式跟连对有点像,不过需要使用#
前缀,后面可以跟串列长度,例如:#4(baldwin bruce)
会产生值'#(baldwin bruce bruce bruce)
。
串列跟连对可以互相转化:vector->list
以及list->vector
。和连对一样,常量串列是不可改的,只有动态创建的串列才具有可修改性。
3.10 Hash Tables
hash, hasheqv, hasheq从初始值序列中创建不可改的哈希表。make-hash
则用来创建可修改的哈希表。可以使用#hash
,#hasheq
, #hasheqv
来创建一个常量哈希表。
可修改的哈希表可以采用弱引用的方式来处理键值的留存,例子如下:
> (define ht (make-weak-hasheq))
> (hash-set! ht (gensym) "can you see me?")
> (collect-garbage)
> (hash-count ht)
0
如果哈希表中的键和值互相引用,可能会导致其无法释放,一个解决办法是采用ephemeron:
> (define ht (make-weak-hasheq))
> (let ([g (gensym)])
(hash-set! ht g (list g)))
> (collect-garbage)
> (hash-count ht)
1
> (define ht (make-weak-hasheq))
> (let ([g (gensym)])
(hash-set! ht g (make-ephemeron g (list g))))
> (collect-garbage)
> (hash-count ht)
0
3.11 Boxes
一个盒子就像是一个单元素的串列。其常量前缀是#&
。例子:
> (define b (box "apple"))
> b
'#&"apple"
> (unbox b)
"apple"
> (set-box! b '(banana boat))
> b
'#&(banana boat)
3.12 Void and Undefined
一些表达式或者执行诀其实是不需要有返回值的。比如执行诀display的调用目的是为了产生副作用,而不是为了求得结果。这种情况下,返回值是#<void>
。
执行诀void
可以接受任意个数的参数并返回#<void>
。
undefined常量,打印形式为#<undefined>
。用的地方较少,只在share形式的某些案例下使用。
(本篇完)